Learning Platform
Глоссарий Troubleshooting
Урок 08.06 · 30 мин
Продвинутый
Apache ArrowC Data InterfacenanoarrowDataFusionDuckDBVeloxPolarspandasZero-Copy FFI

Ecosystem

Arrow как lingua franca

Apache Arrow — это не одна библиотека. Это стандарт — спецификация колоночного формата в памяти, который реализуют десятки проектов. Каждый из них может обмениваться данными с любым другим без сериализации — достаточно передать указатель на Arrow-буферы.

Это создаёт сетевой эффект: чем больше систем понимают Arrow, тем ценнее каждая из них. Python-скрипт → DuckDB → Polars → ML-модель → визуализация — все говорят на Arrow, ни одной конвертации.

Arrow как lingua franca: zero-copy между системами

pandas

pandas: через .to_arrow() / pa.Table.from_pandas(). С pandas 2.0+ Arrow-backed Series — данные хранятся в Arrow-формате нативно, без копирования.

Polars

Polars: нативно построен на Arrow (Rust arrow-rs). DataFrame = набор Arrow-массивов. Нет конвертации — данные уже в Arrow.

DuckDB

DuckDB: внутренний формат основан на Arrow (с расширениями). Экспорт в Arrow через .arrow() / .fetch_arrow_table() — zero-copy для большинства типов.
Arrow Columnar FormatЕдиный стандарт: validity bitmap + типизированные буферы + 64-byte alignment. Одинаков для всех языков и рантаймов.

DataFusion

DataFusion: Apache Arrow-native SQL движок на Rust. Использует arrow-rs напрямую. Встраиваемый — основа для InfluxDB 3, Comet, Arroyo, Ballista.
PyTorch / NumPyPyTorch/NumPy: .to_numpy(zero_copy_only=True) для примитивных типов. Без копирования — Arrow buffer интерпретируется как ndarray.
Spark (Comet)Spark (Comet): Apache Arrow DataFusion Comet — JNI-плагин для Spark, ускоряющий физический план через DataFusion. Arrow-формат вместо Spark InternalRow.

C Data Interface: zero-copy FFI

Главная техническая инновация Arrow-экосистемы — Arrow C Data Interface. Это набор из двух C-структур (ArrowSchema + ArrowArray), позволяющих передавать Arrow-данные между библиотеками без копирования и без общей зависимости на одну реализацию Arrow.

Проблема до C Data Interface: Python-приложение использует pyarrow (C++), Rust-библиотека — arrow-rs, Java-процесс — Arrow Java. Чтобы передать данные между ними, нужна IPC-сериализация — копирование.

С C Data Interface: любая библиотека заполняет два C-struct и передаёт указатели через FFI. Получатель интерпретирует буферы без копирования.

C Data Interface: zero-copy FFI между реализациями
pyarrow (C++)pyarrow заполняет ArrowSchema (типы, metadata) и ArrowArray (буферы, null count, offset). Буферы остаются в памяти pyarrow — не копируются.
arrow-rs (Rust)Rust-библиотека получает указатели на ArrowSchema + ArrowArray через FFI (ctypes, PyO3, cbindgen). Интерпретирует буферы как &[u8] — zero-copy.

общей библиотеки, нет сериализации, нет копирования. Только C ABI.

ArrowSchema

ArrowSchema: format string ('+s' для struct, 'l' для int64), name, metadata, children, dictionary. Рекурсивная структура — описывает любой Arrow-тип.

ArrowArray

ArrowArray: length, null_count, offset, n_buffers, buffers (указатели), children, dictionary. Буферы принадлежат producer — consumer не освобождает их.

ArrowArrayStream

ArrowArrayStream: get_schema() + get_next() + get_last_error() + release(). Потоковая передача: consumer вызывает get_next() пока не получит NULL (конец потока).
TIP

C Data Interface — это ABI, не API. Два C-struct с фиксированной раскладкой полей. Любой язык с FFI (Python ctypes, Rust extern “C”, Go cgo, Julia ccall) может их заполнять и читать. Никакой линковки с Arrow-библиотекой не нужно.

nanoarrow: Arrow без тяжёлой зависимости

Полная реализация Arrow (C++, Java) — это мегабайты кода. Для встраиваемых систем, CLI-утилит, и IoT это overhead. nanoarrow — легковесная реализация Arrow C Data Interface:

  • 2 файла: nanoarrow.c + nanoarrow.h — можно скопировать в проект
  • ~100 KB скомпилированного кода
  • Нет зависимостей — даже stdlib опционален
  • Поддерживает все Arrow-типы, включая nested (List, Struct, Map)
  • Bindings: Python (pip install nanoarrow), R (install.packages("nanoarrow"))

Типичные сценарии:

  • Встраивание Arrow в C/C++ приложение без линковки с libarrow (~50 MB)
  • Конвертация CSV/JSON → Arrow streams в embedded-системах
  • Использование как зависимости в ADBC-драйверах (нативные драйверы PostgreSQL и SQLite ADBC используют nanoarrow)
import nanoarrow as na

# Создание Arrow-массива через nanoarrow
array = na.Array([1, 2, None, 4], na.int32())
print(array) # nanoarrow.Array<int32>[4]

# Совместимость с pyarrow через PyCapsule protocol
import pyarrow as pa
pa_array = pa.array(array) # zero-copy через C Data Interface

Arrow-native движки

Arrow породил новое поколение аналитических движков, которые хранят данные в Arrow-формате нативно, без конвертации:

Arrow-native аналитические движки
Apache DataFusionSQL-движок на Rust, использующий arrow-rs. Top-level ASF проект с 2024. Встраиваемый — используется как основа для InfluxDB 3, Comet (Spark accelerator), Arroyo (streaming), Ballista (distributed). 10+ extension API.
DuckDBEmbedded OLAP движок (C++). Внутренний формат основан на Arrow (с расширениями для строк и nested типов). Читает/пишет Arrow напрямую. 'SQLite для аналитики'.
Velox (Meta)C++ vectorized execution engine от Meta (Facebook). Arrow-совместимый формат данных. Используется внутри Presto, Spark (Gluten plugin). Open source.
PolarsDataFrame-библиотека на Rust (arrow-rs). Lazy evaluation + query optimizer. Не SQL-движок, а DataFrame API. Альтернатива pandas с 10-100× производительностью.

DataFusion заслуживает отдельного внимания: это не просто движок, а конструктор движков. Проекты берут DataFusion как основу и добавляют свой storage layer:

ПроектПоверх DataFusionНазначение
InfluxDB 3Arrow Flight + custom storageTime-series database
CometJNI bridge to SparkSpark query accelerator
ArroyoCustom streaming runtimeStream processing
BallistaDistributed schedulerDistributed SQL
delta-rsDelta Lake readerLakehouse
lanceLance format readerVector database

Языковые реализации

Arrow — multi-language стандарт. Каждая реализация совместима с другими через IPC или C Data Interface:

ЯзыкБиблиотекаОсобенности
C++Apache Arrow C++Каноническая реализация. Compute kernels, IPC, Parquet, CSV, Flight
Rustarrow-rs (arrow crate)Независимая реализация. Основа DataFusion, Polars, delta-rs
JavaArrow JavaJNI bridge к C++. Используется в Spark, Flink, Trino
PythonpyarrowBindings к C++ через Cython. pandas/NumPy интеграция
Goapache-arrow-goPure Go. ADBC, Flight, Parquet
JavaScriptapache-arrow (npm)TypeScript. Observable, Perspective, deck.gl
C#Apache.Arrow (NuGet).NET. Используется в ML.NET, Power BI connectors
Rubyred-arrow (gem)Bindings к C++ через GObject Introspection
NOTE

Rust-реализация (arrow-rs) и C++-реализация — независимые кодовые базы. Они совместимы по формату (IPC, C Data Interface), но не делят код. Это design decision: Rust-экосистема (DataFusion, Polars, delta-rs) развивается быстрее с собственной реализацией.

Интеграция: pandas, NumPy, ML

pandas 2.0+ Arrow backend

С pandas 2.0 появился Arrow-backed dtype — Series хранит данные в Arrow-формате:

import pandas as pd
import pyarrow as pa

# Arrow-backed Series — нет конвертации при создании
s = pd.Series(["Alice", "Bob", None, "Diana"],
 dtype="string[pyarrow]")

# Или целый DataFrame
df = pd.DataFrame({
 "name": pd.array(["Alice", "Bob"], dtype="string[pyarrow]"),
 "score": pd.array([95.5, 87.3], dtype="float64[pyarrow]"),
})

# Конвертация в pyarrow Table — zero-copy
table = pa.Table.from_pandas(df)

NumPy zero-copy

Для примитивных типов (int, float) Arrow → NumPy zero-copy:

import pyarrow as pa
import numpy as np

arr = pa.array([1.0, 2.0, 3.0, 4.0, 5.0])
np_arr = arr.to_numpy(zero_copy_only=True) # без копирования!

# np_arr.base указывает на Arrow-буфер
# Изменения в np_arr не влияют на arr (Arrow immutable)
WARNING

Zero-copy работает только для non-null примитивных типов. Если массив содержит NULL — Arrow хранит validity bitmap отдельно, а NumPy не поддерживает bitmap nulls → нужна копия с заменой NULL на NaN.

ML frameworks

import pyarrow as pa
import torch

# Arrow → PyTorch через NumPy bridge
arr = pa.array([1.0, 2.0, 3.0, 4.0])
tensor = torch.from_numpy(arr.to_numpy(zero_copy_only=True))
# tensor разделяет память с Arrow-буфером

Arrow PyCapsule Protocol

С Arrow 14.0 (2023) появился PyCapsule protocol — стандарт передачи Arrow-данных между Python-библиотеками без зависимости на pyarrow:

# Любой объект с __arrow_c_array__ / __arrow_c_stream__
# автоматически совместим с pyarrow, polars, DuckDB, nanoarrow

import polars as pl
import pyarrow as pa

# Polars Series → pyarrow Array (через PyCapsule, без pyarrow import в Polars)
series = pl.Series("x", [1, 2, 3])
pa_array = pa.array(series) # uses __arrow_c_stream__ internally

Это позволяет библиотекам обмениваться Arrow-данными без общей зависимости на pyarrow — каждая реализует PyCapsule protocol через C Data Interface.

Ключевые выводы

  1. Arrow как lingua franca — единый формат в памяти для десятков систем. pandas → DuckDB → Polars → ML — без конвертации
  2. C Data Interface — два C-struct (ArrowSchema + ArrowArray) для zero-copy FFI. Не нужна общая библиотека, только C ABI
  3. nanoarrow — lightweight Arrow (~100 KB, 2 файла). Для embedded, CLI, ADBC-драйверов
  4. Arrow-native движки — DataFusion (ASF top-level, конструктор движков), DuckDB (embedded OLAP), Velox (Meta), Polars (DataFrame)
  5. Языковые реализации — C++, Rust (arrow-rs, независимая), Java, Python, Go, JS, C#, Ruby. Совместимы через IPC + C Data Interface
  6. pandas 2.0+ — Arrow-backed dtype: string[pyarrow], float64[pyarrow]. Zero-copy конвертация в Arrow Table
  7. PyCapsule protocol (Arrow 14.0+) — стандарт обмена Arrow-данными между Python-библиотеками без зависимости на pyarrow
Python: Arrow C Data Interface на практике

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 4. C Data Interface позволяет передавать Arrow-данные между pyarrow (C++) и arrow-rs (Rust) без копирования. Что именно передаётся через FFI?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 7