Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f5b5bf8
[Improvement](agg) Add a knob to control local exchange (#62438)
Gabriel39 Apr 14, 2026
a8b9382
[feature](iceberg) Support nested column schema change (#65329)
hubgeter Jul 23, 2026
c4abd71
[test](regression) Complete Iceberg/Paimon schema time travel P0 cove…
Gabriel39 Jul 23, 2026
9f0ddfb
[improvement](parquet) Lazily materialize complex residual columns (#…
Gabriel39 Jul 24, 2026
82cbc08
[improvement](parquet) Vectorize File Scanner V2 decode hot paths (#6…
Gabriel39 Jul 24, 2026
d6ebbce
[fix](file) Revert split residual predicate ownership (#65998)
Gabriel39 Jul 24, 2026
0a9e11f
[test](regression) Add external correctness P0 coverage (#66002)
Gabriel39 Jul 24, 2026
570eaa1
[regression](test) expand Iceberg and Paimon partition evolution cove…
Gabriel39 Jul 24, 2026
693e92d
[feature](file scanner) Support JNI and WAL in V2
Gabriel39 Jul 24, 2026
4762994
[fix](file scanner) Distinguish Paimon JNI splits
Gabriel39 Jul 24, 2026
5073bbe
[test](regression) Expand Iceberg write evolution coverage
Gabriel39 Jul 24, 2026
457c9a8
[test](regression) Complete Iceberg write P0 matrix
Gabriel39 Jul 24, 2026
b534a8a
fix(lakehouse): isolate historical relation schemas
Gabriel39 Jul 24, 2026
a5c3b49
fix(style): order logical file scan declarations
Gabriel39 Jul 24, 2026
b92acc4
Fix lakehouse historical schema regression cases
Gabriel39 Jul 24, 2026
96432c8
Fix FE checkstyle ordering
Gabriel39 Jul 24, 2026
c00617c
fix(iceberg): keep branch writes on latest schema
Gabriel39 Jul 24, 2026
2334c58
fix(lakehouse): resolve branch schema regression failures
Gabriel39 Jul 25, 2026
b6577c0
[chore](regression) Sanitize internal issue references
Gabriel39 Jul 25, 2026
a4dd2d6
[fix](lakehouse) Preserve struct comment detection on branch-4.1
Gabriel39 Jul 25, 2026
e760d2c
[fix](test) Adapt lakehouse tests to branch-4.1 APIs
Gabriel39 Jul 25, 2026
76c0355
[branch-4.1](pick) Drop unmerged extra PRs
Gabriel39 Jul 25, 2026
d58e564
[branch-4.1](fix) Preserve Iceberg identity split pruning
Gabriel39 Jul 25, 2026
088793d
[test](regression) Expand Iceberg write evolution coverage (#66021)
Gabriel39 Jul 25, 2026
3e91c49
[improvement](parquet) Optimize typed dictionary range filtering (#66…
Gabriel39 Jul 26, 2026
d523a7a
[Feature](file scanner) Support JNI and WAL in V2 (#66008)
Gabriel39 Jul 26, 2026
72b4817
[improvement](parquet) Make V2 column initialization lazy (#66073)
morningman Jul 27, 2026
6ef4c7c
[fix](parquet) Coalesce adjacent condition cache ranges
Gabriel39 Jul 26, 2026
7a0afa8
[improvement](parquet) Optimize sparse runtime filter scans
Gabriel39 Jul 27, 2026
c390512
[improvement](parquet) Reduce dictionary filter control overhead
Gabriel39 Jul 27, 2026
5b12011
[branch-4.1](fix) Reserve master file format IDs
Gabriel39 Jul 27, 2026
17bf037
[branch-4.1](fix) Restore Paimon test prerequisite
Gabriel39 Jul 27, 2026
8b3306c
[branch-4.1](fix) Restore Iceberg comment compatibility
Gabriel39 Jul 28, 2026
9fa9a1a
[branch-4.1](fix) Preserve Iceberg column comments
Gabriel39 Jul 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions be/benchmark/benchmark_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "core/data_type/data_type.h"
#include "core/data_type/data_type_string.h"
#include "parquet/benchmark_parquet_decoder.hpp"
#include "parquet/benchmark_parquet_kernels.hpp"
#include "parquet/benchmark_parquet_reader.hpp"
#include "runtime/exec_env.h"
#include "runtime/memory/mem_tracker_limiter.h"
Expand Down
64 changes: 43 additions & 21 deletions be/benchmark/parquet/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ benchmark system described in the design document.

## What exists today

The benchmark binary registers two groups:
The benchmark binary registers three groups:

- `ParquetDecoder`: native page decoder benchmarks using in-memory encoded pages.
- `ParquetKernel`: isolated SIMD-sensitive decode and predicate kernels.
- `ParquetReader`: local-file benchmarks that call the format V2 Parquet reader directly.

The relevant files are:
Expand Down Expand Up @@ -36,13 +37,16 @@ List all Parquet cases and verify the expected registration counts:

```shell
be/output/lib/benchmark_test --benchmark_list_tests \
| grep -E '^Parquet(Decoder|Reader)/'
| grep -E '^Parquet(Decoder|Kernel|Reader)/'

be/output/lib/benchmark_test --benchmark_list_tests \
| grep -c '^ParquetDecoder/' # currently 152
| grep -c '^ParquetDecoder/' # currently 228

be/output/lib/benchmark_test --benchmark_list_tests \
| grep -c '^ParquetReader/' # currently 137
| grep -c '^ParquetKernel/' # currently 80

be/output/lib/benchmark_test --benchmark_list_tests \
| grep -c '^ParquetReader/' # currently 152
```

When running the binary directly from `be/build_RELEASE/bin`, make sure the JVM and third-party
Expand All @@ -61,6 +65,12 @@ be/output/lib/benchmark_test \
--benchmark_out=parquet-decoder-smoke.json \
--benchmark_out_format=json

be/output/lib/benchmark_test \
--benchmark_filter='^ParquetKernel/' \
--benchmark_min_time=0.001s \
--benchmark_out=parquet-kernel-smoke.json \
--benchmark_out_format=json

be/output/lib/benchmark_test \
--benchmark_filter='^ParquetReader/' \
--benchmark_min_time=0.001s \
Expand Down Expand Up @@ -98,8 +108,8 @@ cache to manufacture a cold run.

## Current scenario matrix

`ParquetDecoder` contains 19 encoding/type pairs. Each pair is run at 1%, 10%, 50%, and 100%
selection with clustered and alternating selection ranges, for 152 registered cases.
`ParquetDecoder` contains 19 encoding/type pairs. Each pair is run at 0%, 1%, 10%, 50%, 90%, and
100% selection with clustered and alternating selection ranges, for 228 registered cases.

| Encoding | Physical types |
|---|---|
Expand All @@ -110,10 +120,16 @@ selection with clustered and alternating selection ranges, for 152 registered ca
| DELTA_LENGTH_BYTE_ARRAY | BYTE_ARRAY |
| DELTA_BYTE_ARRAY | BYTE_ARRAY |

`ParquetKernel` contains 80 cases across five SIMD-sensitive stages: BYTE_STREAM_SPLIT,
DELTA_PREFIX_SUM, DICTIONARY_GATHER, NULLABLE_EXPAND, and RAW_PREDICATE. It covers the applicable
four- and eight-byte types, three dictionary working-set sizes, 0% through 90% null rates with both
placement patterns, and 0% through 100% raw-predicate selectivities.

`ParquetReader` deliberately uses a single-variable matrix rather than a Cartesian product. After
deduplication it contains 137 cases covering:
deduplication it contains 152 cases covering:

- operations: open-to-first-block, full scan, predicate scan, limit 1, and limit 1000;
- operations: open-to-first-block, full scan, predicate scan, complex residual scan, limit 1, and
limit 1000;
- file encodings: PLAIN, dictionary, BYTE_STREAM_SPLIT, and DELTA_BINARY_PACKED;
- null ratios: 0%, 1%, 10%, 50%, and 90%;
- null shapes: clustered and alternating;
Expand Down Expand Up @@ -146,10 +162,12 @@ generator, random seed, or manifest involved.
and intentionally produces many one-row physical ranges.

Page generation, selection construction, decoder creation, dictionary setup, and `set_data` are
outside the timed decode call. The sinks consume decoder callbacks and prevent compiler removal,
but they do not build a Doris `Column`. Consequently these cases isolate decoder traversal and
selection cost; they do not measure definition-level decoding, nullable reconstruction, type
conversion, or full column materialization.
outside the timed decode call. Before timing, every decoder case verifies the consumed value count
and a checksum of all selected values against the deterministic source generator. The timed sinks
then consume decoder callbacks and prevent compiler removal, but they do not build a Doris
`Column`. Consequently these cases isolate decoder traversal and selection cost; they do not
measure definition-level decoding, nullable reconstruction, type conversion, or full column
materialization.

## How reader Parquet files are generated

Expand All @@ -167,6 +185,9 @@ Fixture contents and writer settings are:
- every non-null value is `row % 100`;
- the predicate is `value < selectivity_percent`, so the threshold maps directly to the intended
non-null selectivity;
- the complex residual scan evaluates a production expression tree whose first child is
`c0 < selectivity_percent` and whose always-true second child is `c2 = c3`, exposing whether
later-only columns are decoded eagerly;
- alternating nulls use a 101-row period and `(row * 37) % 101`, avoiding direct correlation with
the 100-value predicate period;
- clustered nulls use contiguous null prefixes inside each 1,024-row cluster;
Expand Down Expand Up @@ -234,13 +255,14 @@ The current matrix is not comprehensive. Preserve this distinction in PR descrip
1. Add the design's `matrix.yaml`, deterministic corpus generator, `manifest.json`, checksum, and
standalone corpus verifier. The current runtime-generated files cannot be shared unchanged with
V1, StarRocks, or DuckDB.
2. Add correctness oracles. Benchmarks must validate consumed counts and representative checksums
outside the timed region before their performance samples are trusted.
2. Add full reader correctness oracles. Decoder cases validate consumed counts and selected-value
checksums outside the timed region, and kernel cases compare representative output. Reader cases
still need value checksums in addition to their output-row counters.
3. Add reader-level INT64, FLOAT, DOUBLE, BYTE_ARRAY/string, FIXED_LEN_BYTE_ARRAY, DATE,
TIMESTAMP, and DECIMAL cases. Today only nullable INT32 reaches the complete reader path.
4. Extend decoder coverage with 0% and 90% selection, definition levels/null reconstruction,
dictionary conversion, and real Doris `Column` materialization. The current decoder sink does
not cover those costs or report decoded bytes per second.
4. Extend decoder coverage with definition levels/null reconstruction, dictionary conversion, and
real Doris `Column` materialization. The current decoder sink does not cover those costs or
report decoded bytes per second.
5. Add the representative nullable sparse corpus requested by the design: 32 INT64 columns, 128
row groups, and enough rows to exercise many pages. The current 16K-row/four-row-group fixture
is a smoke-sized workload.
Expand Down Expand Up @@ -277,10 +299,10 @@ be simulated by silently changing the local reader benchmark.

## Current validation record

At commit `16e05dd5c71`, a Release build completed and the matrix unit test passed 4/4. A 1 ms smoke
run executed 152 decoder and 137 reader cases with zero benchmark errors. This is an execution
record only. It is not a reviewed performance baseline because repetitions, host isolation,
warmups, cache control, `perf` data, variance, and before/after comparison were not collected.
The current expected registration counts are 228 decoder, 80 kernel, and 152 reader cases. A smoke
run is an execution record only, not a reviewed performance baseline, because repetitions, host
isolation, warmups, cache control, `perf` data, variance, and before/after comparison are not
collected.

## Rules for extending the suite

Expand Down
34 changes: 32 additions & 2 deletions be/benchmark/parquet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,41 @@ timed region. It covers PLAIN, dictionary, byte-stream-split, and DELTA encoding
supported fixed-width and binary physical types. Sparse selections are provided as both one
clustered range and many alternating ranges.

The decoder selection axis includes 0%, 1%, 10%, 50%, 90%, and 100% so boundary and
high-selectivity behavior are visible.

```shell
be/output/lib/benchmark_test \
--benchmark_filter='^ParquetDecoder/plain/int64/sel_10/alternating$' \
--benchmark_min_time=0.1s
```

## SIMD kernel cases

`ParquetKernel` isolates the five SIMD-sensitive stages from reader setup and virtual consumer
overhead: byte-stream-split transpose, delta prefix sum, numeric dictionary gather, nullable
expansion, and raw predicate evaluation. It covers the applicable 4-byte and 8-byte integer and
floating-point physical types, raw-predicate selectivities from 0% through 100%, and nullable
rates from 0% through 90% with clustered and alternating placement. Dictionary gather uses 32-,
4,096-, and 262,144-entry working sets to separate cache-resident and cache-miss-dominated
behavior.

```shell
be/output/lib/benchmark_test \
--benchmark_filter='^ParquetKernel/(dictionary_gather|nullable_expand)/' \
--benchmark_min_time=0.1s
```

## Local reader cases

`ParquetReader` measures local open-to-first-block, full scan, predicate scan, and LIMIT-shaped
reads. The matrix covers:
`ParquetReader` measures local open-to-first-block, full scan, predicate scan, complex residual
scan, and LIMIT-shaped reads. The matrix covers:

- PLAIN, dictionary, byte-stream-split, and DELTA binary-packed files;
- NULL ratios of 0%, 1%, 10%, 50%, and 90%, with clustered and alternating placement;
- predicate selectivities of 0%, 1%, 10%, 50%, 90%, and 100%;
- predicate-only and predicate-plus-lazy-projected reads;
- ordered complex residuals whose later columns are reachable only after an earlier residual;
- schemas with 4, 32, 128, and 512 columns, with the predicate first or last.

Fixtures are created lazily under the system temporary directory in
Expand All @@ -58,6 +78,16 @@ be/output/lib/benchmark_test \
--benchmark_out_format=json
```

The complex-residual case uses a production compound `AND` tree. Its first child,
`c0 < selectivity_percent`, preserves the requested selectivity; its second child, `c2 = c3`,
references two new columns and accepts every row that reaches it:

```shell
be/output/lib/benchmark_test \
--benchmark_filter='^ParquetReader/complex_residual_scan/plain/null_10/alternating/sel_10/' \
--benchmark_min_time=1s
```

Every result reports throughput plus `raw_rows`, `selected_rows`, `fixture_bytes`, `ns/raw_row`,
and (when at least one row survives) `ns/selected_row`. Keep CPU frequency, build type, compiler,
machine placement, and benchmark filters fixed when comparing two commits.
Loading
Loading