Nimble — философия дизайна
В предыдущем уроке мы разобрали техническую архитектуру Nimble: stripes, blocks, FlatBuffers, encoding pipeline. Но самое интересное в Nimble — не структура файла, а философия проекта. Nimble осознанно отвергает модель, по которой работают все остальные форматы хранения: отдельная спецификация + множество независимых реализаций.
Девиз проекта: «More than a specification, Nimble is a product» — «Nimble — не спецификация, а продукт». Это радикальный выбор, и он вытекает из конкретного опыта Meta с Parquet.
Проблема Parquet: фрагментация реализаций
Parquet — один из самых успешных open-source форматов. Но успех multi-implementation модели имеет цену:
Parquet Specification
Apache Parquet Specification: документ, описывающий формат файла. Определяет структуру (row groups, pages, footer), типы данных, кодировки, compression. Спецификация — источник истины, но интерпретация зависит от реализации.parquet-java
parquet-java (Apache): оригинальная реализация. Поддерживает все features. Используется в Spark, Hive, Impala. Некоторые features (column encryption) — только здесь.parquet-cpp (Arrow)
parquet-cpp (Apache Arrow): C++ реализация через Arrow. Используется в PyArrow, DuckDB, Polars. Высокая производительность, но не все features parquet-java.parquet-rs (Rust)
parquet-rs (Apache Arrow): Rust реализация. Используется в DataFusion, Ballista, delta-rs. Быстро развивается, но отстаёт по feature coverage от Java.Проблемы multi-implementation модели:
Это не критика Parquet — multi-implementation модель обеспечила Parquet статус универсального стандарта. Файлы, записанные в Java Spark, читаются Python PyArrow и Rust DataFusion. Но для Meta, где скорость добавления новых кодировок критичнее универсальности, эта модель — bottleneck.
«Библиотека как спецификация»
Nimble переворачивает модель: реализация IS спецификация. Нет отдельного документа, описывающего формат — есть C++ библиотека, которая определяет, как файлы записываются и читаются:
Parquet Model
Модель Parquet: спецификация как отдельный документ. Реализации интерпретируют спецификацию независимо. Спецификация — арбитр, но не всегда однозначна.Nimble Model
Модель Nimble: библиотека = спецификация. Нет отдельного документа. Если хочешь узнать, как работает формат — читай код. Нет ambiguity, нет divergent interpretations.Преимущества library-first подхода:
-
Нет ambiguity. Вопрос «как работает encoding X?» — ответ в коде. Нет расхождений между спецификацией и реализацией.
-
Быстрая эволюция. Новая кодировка = один PR в один репозиторий. Нет согласования с другими реализациями, нет compatibility matrix.
-
Консистентность. Файл, записанный Nimble, гарантированно читается Nimble. Нет сюрпризов «этот файл записан Java-реализацией, у которой другой bloom filter формат».
Цена:
-
Vendor lock-in. Без Velox нет Nimble. Нет Python, Java, Rust readers.
-
Нет ecosystem. Нет DuckDB connector, нет PyArrow reader, нет Polars support. Только Velox-based системы.
-
Bus factor. Одна команда, одна организация. Если Meta перестанет поддерживать — формат мёртв.
Оптимизация для широких схем
Nimble архитектурно оптимизирован для таблиц с тысячами колонок. Это проявляется на нескольких уровнях:
Параллельное декодирование: scheduling без данных
Уникальная особенность блочной архитектуры Nimble — возможность планировать параллельное декодирование без загрузки самих данных:
Stripe Footer (FlatBuffers)
Stripe footer: FlatBuffers metadata с полной информацией о каждом block в каждом stream. Включает: offset, encoded size, decoded size, encoding type, value count. Достаточно для полного планирования.Decoded Columns (Velox Vectors)
Decoded column data: готовые Velox Vectors для execution engine. Весь pipeline: plan → I/O → decode — с гарантией отсутствия OOM и минимальным memory waste.Сравните с Vortex из Модуля 15: Vortex тоже использует FlatBuffers metadata и cascading encodings, но не гарантирует known decoded size на уровне каждого chunk. Nimble’s block encoding — более строгий контракт: каждый block = предсказуемый memory footprint.
OpenZL: format-aware compression
Meta разрабатывает OpenZL — compression framework, который работает совместно с Nimble. Идея: compression engine, который «знает» о формате данных:
Generic Compression
Традиционная compression: ZSTD/LZ4 работают с raw bytes. Не знают, что данные — это колоночные values. Ищут byte patterns, повторы, entropy. Эффективно, но generic.Format-Aware (OpenZL)
OpenZL: знает структуру Nimble — types, encoding pipeline, block boundaries. Может применять type-specific compression: integer delta + varint, float XOR + ZSTD, string dictionary + FSST.Сравнение implementation моделей
Kernel Scheduling: параллелизм без загрузки данных
Детальнее о механизме, который отличает Nimble от всех форматов в курсе — возможность полностью спланировать decode pipeline из одних метаданных:
Parquet Scheduler
Parquet scheduler: знает offset'ы pages из column metadata. Но decoded size pages — unknown. Dictionary page может быть 1KB или 1GB. RLE page decoded size зависит от run lengths.Nimble Scheduler
Nimble scheduler: stripe footer содержит для каждого block: encoded_size, decoded_size, value_count, encoding_type. Полная информация для планирования до загрузки данных.Для ML-training pipelines в Meta, где тысячи decode tasks конкурируют за N GPU/CPU cores, deterministic scheduling — необходимость, не оптимизация. Nimble’s block headers — это контракт: «для декодирования этого block нужно X байт памяти и ~Y микросекунд CPU».
Текущие ограничения
Философия «одна библиотека» — осознанный trade-off. Текущие ограничения:
Nimble — не формат для production use за пределами Meta. Это скорее архитектурный эксперимент, демонстрирующий подход «библиотека как спецификация». Ценность для инженера — понимание trade-offs между universal ecosystem (Parquet) и fast-evolving single-source (Nimble).
Уроки для дизайна форматов
Опыт Nimble формулирует несколько принципов, актуальных для всех форматов нового поколения:
Итоги
Nimble — это не «ещё один формат хранения», а философский statement о дизайне форматов данных:
-
«Библиотека как спецификация» устраняет фрагментацию реализаций. Один codebase = zero ambiguity, instant evolution. Цена — экосистема ограничена одним языком и одним execution engine.
-
Wide schema optimization — ответ на конкретную проблему Meta (10K+ колонок). FlatBuffers metadata + stream-per-column = O(1) доступ к любой колонке.
-
Deterministic scheduling — block encoding с known decoded sizes позволяет планировать parallel decode без загрузки данных. Для ML-training infra Meta это критично.
-
OpenZL — format-aware compression, работающая совместно с encoding pipeline. Использует знание о типах данных для лучшего compression ratio.
В следующем уроке мы перейдём к F3 — Future-proof File Format от CMU. Если Nimble — это «одна библиотека для всех файлов», то F3 — «каждый файл содержит свой собственный decoder». Два полярных подхода к проблеме расширяемости форматов.