A fast, pure C library for reading and writing Apache Parquet files.
- Pure C11 with three external dependencies (zstd, zlib, lz4) -- all auto-fetched by CMake
- ~200KB binary vs ~50MB+ for Arrow
- Built-in CLI for file inspection (
schema,info,head,tail,stat, ...) and C code generation (codegen) - 70x faster reads than Arrow C++ on uncompressed data (mmap zero-copy), 150x faster than PyArrow
- 1.2-2.6x faster compressed reads than Arrow C++ on the same file (cross-read benchmark)
- Writes 1.0-2.3x faster than Arrow C++ across codecs and platforms
- Reads 10M uncompressed rows in 0.25ms (mmap zero-copy on Apple M3)
- Full Parquet spec: all types, encodings, compression codecs, nested schemas, bloom filters, page indexes
- SIMD-optimized (SSE4.2, AVX2, AVX-512, NEON, SVE) with runtime detection and scalar fallbacks
- PyArrow, DuckDB, Spark compatible out of the box
- Arrow C Data Interface bridge (
carquet_arrow_export_*/carquet_arrow_import_*/carquet_writer_write_arrow/carquet_reader_read_arrow) for zero-dependency, copy-light interchange with the Arrow ecosystem, with arbitrary-depth nested read/write (struct/list/map at any depth)
At 10M rows (the most representative size); higher ratio = Carquet faster. ARM (Apple M3): Carquet 0.6.0 vs Arrow C++ 24.0.0. x86 (Xeon D-1531): Carquet 0.4.4 vs Arrow C++ 23.0.1.
| x86 (Xeon D-1531) | ARM (Apple M3) | |||
|---|---|---|---|---|
| Codec | Write | Read | Write | Read |
| snappy | 1.55x | 1.25x | 1.88x | 1.59x |
| zstd | 1.31x | 1.04x | 2.23x | 1.30x |
| lz4 | 1.02x | 0.83x | 1.89x | 1.59x |
| none | 1.13x | 40.6x* | 1.97x | 52.9x* |
* Uncompressed reads use mmap zero-copy -- see note below.
Compressed reads involve full decompression and decoding of every value, no shortcuts — and both libraries use the same system lz4/zstd shared libraries, so the raw codec speed is identical. The most meaningful comparison is the same-file cross-read table (below), where both libraries read the exact same Parquet file: Carquet reads compressed data 1.5-2.6x faster than Arrow C++ on that apples-to-apples test.
To run the benchmarks yourself, see Running Benchmarks.
Benchmark methodology
All benchmarks use identical data (deterministic LCG PRNG), identical Parquet settings (no dictionary, BYTE_STREAM_SPLIT for floats, page checksums, mmap reads), trimmed median of 11-51 iterations, with OS page cache purged between write and read phases and cooldown between configurations. Schema: 3 columns (INT64, DOUBLE, INT32). Compared against Arrow C++ 23.0.1 low-level Parquet reader (bypassing Arrow Table materialization) and PyArrow 23.0.1.
The same-file cross-read benchmark is the fairest comparison: both libraries read the exact same Parquet file (written by one, read by both). This eliminates differences in page sizes, encoding choices, and row group layout.
Uncompressed reads marked with * use Carquet's mmap zero-copy path: for PLAIN-encoded, uncompressed, fixed-size, required columns, the batch reader returns pointers directly into the memory-mapped file with no memcpy. Arrow always materializes into its own buffers. The compressed read numbers are the most representative measure of end-to-end read throughput.
Full x86 results (Intel Xeon D-1531, Linux)
12 threads @ 2.2GHz, 32GB RAM, Ubuntu 24.04 -- ZSTD level 1
| Codec | Carquet Write | Arrow C++ Write | W ratio | Carquet Read | Arrow C++ Read | R ratio | Size |
|---|---|---|---|---|---|---|---|
| none | 1557ms | 1766ms | 1.13x | 1.25ms | 50.8ms | 40.6x* | 190.7MB |
| snappy | 1002ms | 1549ms | 1.55x | 78ms | 97.8ms | 1.25x | 125.1MB |
| zstd | 1311ms | 1714ms | 1.31x | 76.8ms | 80.2ms | 1.04x | 95.3MB |
| lz4 | 1521ms | 1554ms | 1.02x | 59.1ms | 49.0ms | 0.83x | 122.9MB |
| Codec | Carquet Write | Arrow C++ Write | W ratio | Carquet Read | Arrow C++ Read | R ratio |
|---|---|---|---|---|---|---|
| none | 180ms | 196ms | 1.09x | 0.22ms | 6.2ms | 28x* |
| snappy | 141ms | 148ms | 1.05x | 8.1ms | 11.6ms | 1.44x |
| zstd | 131ms | 185ms | 1.41x | 10.3ms | 9.1ms | 0.88x |
| lz4 | 143ms | 149ms | 1.04x | 8.5ms | 6.1ms | 0.72x |
| Codec | Carquet Write | Arrow C++ Write | W ratio | Carquet Read | Arrow C++ Read | R ratio |
|---|---|---|---|---|---|---|
| none | 14.1ms | 18.4ms | 1.30x | 0.11ms | 2.18ms | 19.8x* |
| snappy | 10.1ms | 10.6ms | 1.05x | 1.27ms | 5.97ms | 4.70x |
| zstd | 8.7ms | 14.1ms | 1.62x | 1.58ms | 3.88ms | 2.46x |
| lz4 | 9.6ms | 11.0ms | 1.14x | 0.77ms | 2.78ms | 3.61x |
Both libraries read the same Parquet file — the fairest apples-to-apples comparison.
| Codec | Writer | Carquet Read | Arrow C++ Read | Ratio |
|---|---|---|---|---|
| none | Carquet | 0.99ms | 73.6ms | 74x* |
| none | Arrow | 7.6ms | 51.2ms | 6.8x* |
| snappy | Carquet | 41.0ms | 107ms | 2.61x |
| snappy | Arrow | 43.4ms | 101ms | 2.33x |
| zstd | Carquet | 46.1ms | 88.4ms | 1.92x |
| zstd | Arrow | 49.1ms | 79.5ms | 1.62x |
| lz4 | Carquet | 34.8ms | 74.8ms | 2.15x |
| lz4 | Arrow | 27.4ms | 52.0ms | 1.90x |
| Codec | Carquet Write | PyArrow Write | W ratio | Carquet Read | PyArrow Read | R ratio |
|---|---|---|---|---|---|---|
| none | 1557ms | 1806ms | 1.16x | 1.25ms | 213ms | 170x* |
| snappy | 1002ms | 1649ms | 1.65x | 78ms | 384ms | 4.91x |
| zstd | 1311ms | 1796ms | 1.37x | 76.8ms | 369ms | 4.81x |
| lz4 | 1521ms | 1676ms | 1.10x | 59.1ms | 281ms | 4.76x |
* Zero-copy mmap path
Full ARM results (Apple M3, macOS)
Carquet 0.6.0 -- MacBook Air M3, 16GB RAM, macOS 26.5, Arrow C++ 24.0.0, PyArrow 23.0.1 -- ZSTD level 1
| Codec | Carquet Write | Arrow C++ Write | W ratio | Carquet Read | Arrow C++ Read | R ratio | Size |
|---|---|---|---|---|---|---|---|
| none | 62.21ms | 122.5ms | 1.97x | 0.26ms | 13.75ms | 52.9x* | 190.7MB |
| snappy | 129.0ms | 242.6ms | 1.88x | 14.15ms | 22.47ms | 1.59x | 125.1MB |
| zstd | 149.6ms | 334.0ms | 2.23x | 21.39ms | 27.91ms | 1.30x | 95.3MB |
| lz4 | 128.1ms | 241.7ms | 1.89x | 10.13ms | 16.08ms | 1.59x | 122.9MB |
| Codec | Carquet Write | Arrow C++ Write | W ratio | Carquet Read | Arrow C++ Read | R ratio |
|---|---|---|---|---|---|---|
| none | 5.85ms | 12.65ms | 2.16x | 0.05ms | 1.54ms | 30.8x* |
| snappy | 12.39ms | 23.62ms | 1.91x | 1.36ms | 2.41ms | 1.77x |
| zstd | 15.26ms | 33.90ms | 2.22x | 2.39ms | 3.17ms | 1.33x |
| lz4 | 12.28ms | 24.51ms | 2.00x | 0.97ms | 1.77ms | 1.82x |
| Codec | Carquet Write | Arrow C++ Write | W ratio | Carquet Read | Arrow C++ Read | R ratio |
|---|---|---|---|---|---|---|
| none | 1.02ms | 1.54ms | 1.51x | 0.02ms | 0.22ms | 11.0x* |
| snappy | 1.51ms | 2.45ms | 1.62x | 0.36ms | 0.90ms | 2.50x |
| zstd | 1.65ms | 3.58ms | 2.17x | 0.63ms | 1.23ms | 1.95x |
| lz4 | 1.57ms | 2.45ms | 1.56x | 0.24ms | 0.55ms | 2.29x |
Both libraries read the same Parquet file — the fairest apples-to-apples comparison.
| Codec | Writer | Carquet Read | Arrow C++ Read | Ratio |
|---|---|---|---|---|
| none | Carquet | 0.27ms | 15.60ms | 57.8x* |
| none | Arrow | 0.91ms | 13.68ms | 15.0x* |
| snappy | Carquet | 14.63ms | 23.29ms | 1.59x |
| snappy | Arrow | 13.20ms | 22.15ms | 1.68x |
| zstd | Carquet | 20.96ms | 28.04ms | 1.34x |
| zstd | Arrow | 21.03ms | 27.73ms | 1.32x |
| lz4 | Carquet | 10.16ms | 16.89ms | 1.66x |
| lz4 | Arrow | 9.66ms | 16.09ms | 1.67x |
| Codec | Carquet Write | PyArrow Write | W ratio | Carquet Read | PyArrow Read | R ratio |
|---|---|---|---|---|---|---|
| none | 62.21ms | 176.4ms | 2.83x | 0.26ms | 36.49ms | 140.4x* |
| snappy | 129.0ms | 294.2ms | 2.28x | 14.15ms | 44.19ms | 3.12x |
| zstd | 149.6ms | 396.3ms | 2.65x | 21.39ms | 55.96ms | 2.62x |
| lz4 | 128.1ms | 305.3ms | 2.38x | 10.13ms | 38.00ms | 3.75x |
| Codec | Carquet Write | PyArrow Write | W ratio | Carquet Read | PyArrow Read | R ratio |
|---|---|---|---|---|---|---|
| none | 5.85ms | 17.13ms | 2.93x | 0.05ms | 2.55ms | 51.0x* |
| snappy | 12.39ms | 29.62ms | 2.39x | 1.36ms | 3.57ms | 2.62x |
| zstd | 15.26ms | 40.26ms | 2.64x | 2.39ms | 4.41ms | 1.85x |
| lz4 | 12.28ms | 31.15ms | 2.54x | 0.97ms | 3.11ms | 3.21x |
| Codec | Carquet Write | PyArrow Write | W ratio | Carquet Read | PyArrow Read | R ratio |
|---|---|---|---|---|---|---|
| none | 1.02ms | 1.94ms | 1.90x | 0.02ms | 0.23ms | 11.5x* |
| snappy | 1.51ms | 2.96ms | 1.96x | 0.36ms | 0.58ms | 1.61x |
| zstd | 1.65ms | 4.15ms | 2.52x | 0.63ms | 0.80ms | 1.27x |
| lz4 | 1.57ms | 3.01ms | 1.92x | 0.24ms | 0.41ms | 1.71x |
* Zero-copy mmap path
- C11 compiler (GCC 4.9+, Clang 3.4+, MSVC 2015+)
- CMake 3.16+ (or xmake — see Building with xmake)
- zstd, zlib, lz4 (auto-fetched if missing)
- OpenMP (optional, for parallel column reading)
The make wrapper drives an optimized CMake build and a /usr/local install:
git clone https://github.com/Vitruves/carquet.git
cd carquet
make # optimized build (run `make help` to list all targets)
sudo make install # install to /usr/local (override with PREFIX=/opt/carquet)Invoke CMake directly when you need specific build options or a custom prefix:
cmake -B build -DCMAKE_BUILD_TYPE=Release # add options, e.g. -DCARQUET_BUILD_SHARED=ON
cmake --build build -j$(nproc)
sudo cmake --install build --prefix /usr/localEither path installs:
libcarquet.a(or.so/.dylibwith-DCARQUET_BUILD_SHARED=ON)include/carquet/headerscarquetCLI binarycarquet.pc(pkg-config) and CMake package config forfind_package(carquet)
After installation, link with -lcarquet, or resolve flags via pkg-config --cflags --libs carquet.
Pass these to the CMake configure step:
| Option | Default | Description |
|---|---|---|
CARQUET_BUILD_DEV |
OFF | Build everything (tests, examples, benchmarks) |
CARQUET_BUILD_TESTS |
OFF | Build test suite only |
CARQUET_BUILD_CLI |
ON | Build carquet CLI tool |
CARQUET_BUILD_SHARED |
OFF | Build shared library instead of static |
CARQUET_NATIVE_ARCH |
OFF | -march=native for max performance |
CARQUET_ENABLE_SVE |
OFF | ARM SVE (experimental) |
All x86 SIMD (SSE, AVX, AVX2, AVX-512) and ARM NEON are auto-detected and enabled by default.
All build options
| Option | Default | Description |
|---|---|---|
CARQUET_BUILD_EXAMPLES |
OFF | Build example programs |
CARQUET_BUILD_BENCHMARKS |
OFF | Build benchmark and profiling programs |
CARQUET_BUILD_ARROW_CPP_BENCHMARK |
OFF | Optional Arrow C++ comparison benchmark |
CARQUET_BUILD_INTEROP |
OFF | Build interoperability tests |
CARQUET_BUILD_FUZZ |
OFF | Build fuzz targets |
CARQUET_BUILD_DOCS |
OFF | Add a docs target (needs Doxygen) |
CARQUET_ENABLE_SSE |
ON | SSE optimizations (x86, auto-detected) |
CARQUET_ENABLE_AVX |
ON | AVX optimizations (x86, auto-detected) |
CARQUET_ENABLE_AVX2 |
ON | AVX2 optimizations (x86, auto-detected) |
CARQUET_ENABLE_AVX512 |
ON | AVX-512 optimizations (x86, auto-detected) |
CARQUET_ENABLE_NEON |
ON | NEON optimizations (ARM, auto-detected) |
cmake -B build -DCARQUET_BUILD_DEV=ON
cmake --build build -j$(nproc)
cd build && ctest --output-on-failureAn xmake build (xmake.lua) is provided as an alternative to CMake, with the same options and defaults; zstd/zlib/lz4 are linked statically so binaries are self-contained.
xmake # build the static library + `carquet` CLI (release)
xmake f --dev=y && xmake # add tests, examples, benchmarks, interop
xmake test # run the test suiteConfigure options (xmake f --option=y|n)
Options mirror the CMake ones (drop the CARQUET_ prefix, lower-case):
| xmake option | Default | Description |
|---|---|---|
--dev |
n | Build tests, examples, benchmarks and interop |
--tests / --examples / --benchmarks / --interop |
n | Build one group individually |
--cli |
y | Build the carquet CLI tool |
--shared |
n | Build a shared library instead of static |
--openmp |
y | OpenMP parallel column reading (auto-disabled if unavailable) |
--native_arch |
n | -march=native for max performance (host-only binary) |
--sse / --avx / --avx2 / --avx512 / --neon |
y | SIMD instruction sets (auto-detected) |
--sve |
n | ARM SVE (experimental) |
--fuzz |
n | Build fuzz targets (use --toolchain=clang) |
xmake f -m release --shared=y # shared library
xmake f --dev=y --avx512=n && xmake # dev build, AVX-512 disabledThe public headers are annotated with Doxygen comments. Generating the HTML reference needs doxygen installed (plus optional graphviz for include/dependency diagrams); neither is required for a normal build.
# CMake — enable the target at configure time, then build it
cmake -B build -DCARQUET_BUILD_DOCS=ON
cmake --build build --target docs
# xmake — a standalone task, no configure flag needed
xmake docsBoth write to build/docs/html/index.html. If Doxygen is not installed the target/task simply reports that and does nothing.
This README stays intentionally short — a Write and a Read example below, then the manual in docs/ for everything else.
#include <carquet/carquet.h>
int main(void) {
carquet_error_t err = CARQUET_ERROR_INIT;
// Define schema
carquet_schema_t* schema = carquet_schema_create(&err);
carquet_schema_add_column(schema, "id", CARQUET_PHYSICAL_INT64, NULL, CARQUET_REPETITION_REQUIRED, 0, 0);
carquet_schema_add_column(schema, "value", CARQUET_PHYSICAL_DOUBLE, NULL, CARQUET_REPETITION_REQUIRED, 0, 0);
// Configure writer
carquet_writer_options_t opts;
carquet_writer_options_init(&opts);
opts.compression = CARQUET_COMPRESSION_ZSTD;
// Write
carquet_writer_t* w = carquet_writer_create("output.parquet", schema, &opts, &err);
int64_t ids[] = {1, 2, 3, 4, 5};
double values[] = {1.1, 2.2, 3.3, 4.4, 5.5};
carquet_writer_write_batch(w, 0, ids, 5, NULL, NULL);
carquet_writer_write_batch(w, 1, values, 5, NULL, NULL);
carquet_writer_close(w);
carquet_schema_free(schema);
return 0;
}#include <carquet/carquet.h>
#include <stdio.h>
int main(void) {
carquet_error_t err = CARQUET_ERROR_INIT;
// Open with mmap for best read performance
carquet_reader_options_t opts;
carquet_reader_options_init(&opts);
opts.use_mmap = true;
carquet_reader_t* r = carquet_reader_open("output.parquet", &opts, &err);
if (!r) { printf("Error: %s\n", err.message); return 1; }
printf("Rows: %lld, Columns: %d\n",
(long long)carquet_reader_num_rows(r),
carquet_reader_num_columns(r));
// Batch reader for efficient iteration
carquet_batch_reader_config_t cfg;
carquet_batch_reader_config_init(&cfg);
cfg.batch_size = 65536;
carquet_batch_reader_t* br = carquet_batch_reader_create(r, &cfg, &err);
carquet_row_batch_t* batch = NULL;
while (carquet_batch_reader_next(br, &batch) == CARQUET_OK && batch) {
const void* data;
const uint8_t* nulls;
int64_t n;
carquet_row_batch_column(batch, 0, &data, &nulls, &n);
const int64_t* ids = (const int64_t*)data;
// process ids[0..n-1] ...
carquet_row_batch_free(batch);
batch = NULL;
}
carquet_batch_reader_free(br);
carquet_reader_close(r);
return 0;
}Everything beyond flat read/write lives in the manual — each links to a runnable example:
| You want to… | See |
|---|---|
| Nullable columns, row groups, buffer output | docs/writing.md |
| Lists, maps, groups, definition/repetition levels | docs/nested-data.md |
| Column projection, statistics, metadata inspection | docs/reading.md |
| Predicate pushdown, page-level filtering | docs/reading.md |
| Append row groups to an existing file | docs/writing.md |
| Compression, custom codecs, writer tuning | docs/writing.md, docs/performance.md |
| mmap, zero-copy, prebuffering, I/O coalescing | docs/performance.md |
| Error codes and recovery hints | docs/error-handling.md |
mocklib/ is MetricStore — a complete, self-contained example application built on top of carquet, useful both as a reference for real-world usage and as an end-to-end integration test of the public API. It models a time-series telemetry store (ingest events, then introspect and query them) and, in doing so, exercises 114 of carquet's 128 public functions (~89%): schema construction with logical types, per-column encoding/compression/bloom tuning, page indexes and statistics on the write side; column projection, predicate pushdown, page-level filtering, bloom membership, the Arrow C Data Interface bridge, nested LIST reconstruction, buffer/append I/O and metadata introspection on the read side. It links carquet the way any downstream project would (find_package(carquet) / add_subdirectory), ships a self-checking round-trip test, and its write_sample binary emits a file for external inspection. See mocklib/README.md.
Full API is in include/carquet/carquet.h. Key types:
| Type | Purpose |
|---|---|
carquet_reader_t |
File reader (open from path, FILE*, or memory buffer) |
carquet_writer_t |
File writer |
carquet_batch_reader_t |
High-level batch iteration |
carquet_schema_t |
Schema definition and introspection |
carquet_error_t |
Rich error info (code, message, source location, recovery hint) |
Full signatures live in the header; the manual explains which surface to use when. The source layout and architecture are documented in CONTRIBUTING.md.
Carquet ships with a command-line tool for inspecting Parquet files and generating C reader code. Built and installed by default alongside the library.
Commands:
schema Print file schema
info Print detailed file metadata
head Print first N rows
tail Print last N rows
cat Print rows with slicing/column/row filtering
count Print total row count
columns List column names (one per line)
stat Print column statistics
validate Verify file integrity
sample Print N random rows
export Write rows to stdout as CSV
codegen Generate C reader code
carquet schema data.parquet
carquet head -n 20 data.parquet
carquet stat data.parquet
carquet validate data.parquetcat, count, head, and export accept -p / --filter EXPR to push a row predicate down to the page level — only pages whose column-index min/max can match the predicate are decompressed:
carquet cat -p "price > 100 AND status = 'active'" data.parquet
carquet count --filter "id >= 1000" data.parquet
carquet export --filter "ts IS NOT NULL" -c id,ts data.parquetThe grammar is column OP value [AND column OP value]... with OP ∈ {=, ==, !=, <>, <, <=, >, >=}, plus column IS NULL / column IS NOT NULL. Filtering requires the file to have a page index (write_page_index = true).
Generate a complete, compilable C reader from any Parquet file's schema:
carquet codegen -f data.parquet -o reader.c
# Generated: reader.c
# Compile: clang -o reader reader.c -I.../include -L.../build -lcarquet ...
./reader # reads data.parquet (embedded as default)
./reader other.parquet # override with different fileOptions:
| Flag | Description |
|---|---|
-f, --file FILE |
Parquet file to inspect schema from |
-o, --output FILE |
Output source file (default: stdout) |
--mmap |
Use memory-mapped I/O in generated code |
--skeleton |
Generate empty process_batch for custom logic |
-c, --columns COLS |
Comma-separated column filter |
-b, --batch-size N |
Batch size (default: 1024) |
Carquet files are fully compatible with PyArrow, DuckDB, Spark, and any Parquet reader:
import pyarrow.parquet as pq
table = pq.read_table("carquet_output.parquet") # just works-- DuckDB
SELECT * FROM read_parquet('carquet_output.parquet');Bidirectional interop testing:
cmake -B build -DCARQUET_BUILD_INTEROP=ON && cmake --build build
python3 interop/run_interop.py| Feature | Status |
|---|---|
| Physical types | All 8 (BOOLEAN through FIXED_LEN_BYTE_ARRAY) |
| Logical types | STRING, DATE, TIME, TIMESTAMP, DECIMAL, UUID, JSON, INTERVAL, FLOAT16, VARIANT, GEOMETRY, GEOGRAPHY |
| Encodings | PLAIN, RLE, DICTIONARY, DELTA_BINARY_PACKED, DELTA_LENGTH_BYTE_ARRAY, DELTA_BYTE_ARRAY, BYTE_STREAM_SPLIT (read + write) |
| Data Page versions | V1 (default) and V2 (read + write) |
| Compression | UNCOMPRESSED, SNAPPY, GZIP, LZ4 (Hadoop-framed, codec 5), LZ4_RAW (codec 7), ZSTD |
| Nested schemas | Groups, lists, maps with definition/repetition levels; single-level LIST/MAP auto-shredding on write (carquet_writer_write_list_column) and List reconstruction on read; nested ARROW:schema emission |
| Bloom filters | Read, write, and query (carquet_bloom_filter_check_*); consulted automatically for row-group pruning |
| Page indexes | Column index + offset index (read + write + per-page stats access) |
| Statistics | Min/max/null count per column chunk; exact distinct_count for dictionary columns; Parquet 2.9 SizeStatistics (unencoded byte-array bytes + level histograms) |
| Predicate pushdown | Automatic row-group pruning via statistics + bloom filters (no callback needed); page-level filtering via column index (carquet_batch_reader_set_page_filter) |
| Append | Add row groups to an existing file (carquet_writer_open_append) |
| Custom codecs | Register a custom compress/decompress impl per codec slot (carquet_register_codec) |
| Key-value metadata | Read and write arbitrary footer metadata |
| Per-field metadata | Arrow Field.custom_metadata (variable labels/descriptions) via ARROW:schema (read + write) |
| Per-column options | Per-column encoding, compression, statistics, bloom filter |
| Buffer writer | Write Parquet to in-memory buffer |
| CRC32 | Page-level verification (HW-accelerated on ARM) |
| Memory-mapped I/O | Zero-copy reads for uncompressed PLAIN data |
| Column projection | Read only selected columns |
| I/O coalescing | Pre-buffer multi-column reads in a single I/O |
| Speculative footer | Single-I/O file open for most files |
| OpenMP parallel reads | When available |
| Encryption | Not supported |
# Build with max optimizations
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCARQUET_NATIVE_ARCH=ON -DCARQUET_BUILD_DEV=ON
cmake --build build -j$(nproc)
cd build
./benchmark_carquet # Carquet standalone
python3 ../benchmark/run_benchmark.py # Full comparison (+ PyArrow, + Arrow C++)
# Skip 100M-row (xlarge) configs — they write ~2GB files per codec
# and can take 30+ minutes depending on hardware
python3 ../benchmark/run_benchmark.py --skip-xlarge
# Override ZSTD level (default: 1)
CARQUET_BENCH_ZSTD_LEVEL=3 python3 ../benchmark/run_benchmark.pyOptional Arrow C++ benchmark
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCARQUET_NATIVE_ARCH=ON \
-DCARQUET_BUILD_BENCHMARKS=ON \
-DCARQUET_BUILD_ARROW_CPP_BENCHMARK=ON
cmake --build build -j$(nproc)
# Or point at a custom Arrow install
cmake -B build ... -DCARQUET_ARROW_CPP_ROOT=/path/to/arrow-prefixThe Arrow C++ benchmark uses the low-level parquet::ParquetFileReader API (bypassing Arrow Table materialization overhead) with parallel row group readers. The same-file cross-read mode has both libraries read the exact same Parquet file, eliminating differences in page sizes, encoding, and row group layout. Both benchmarks use identical data, row group sizing, no dictionary, page checksums, mmap reads, BYTE_STREAM_SPLIT for floats.
MIT
