Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 6 additions & 4 deletions be/benchmark/benchmark_bit_pack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@ void bit_pack(const T* input, uint8_t in_num, int bit_width, uint8_t* output) {
}

static void BM_BitPack(benchmark::State& state) {
int w = state.range(0);
int n = 255;
// Registrations cap these dimensions to the destination types; explicit casts keep the
// benchmark build independent of the compiler's implicit-conversion warning policy.
const auto w = static_cast<int>(state.range(0));
constexpr uint8_t n = 255;

std::default_random_engine e;
std::uniform_int_distribution<int64_t> u;
Expand All @@ -75,8 +77,8 @@ static void BM_BitPack(benchmark::State& state) {
}

static void BM_BitPackOptimized(benchmark::State& state) {
int w = state.range(0);
int n = 255;
const auto w = static_cast<int>(state.range(0));
constexpr uint8_t n = 255;

std::default_random_engine e;
std::uniform_int_distribution<int64_t> u;
Expand Down
2 changes: 1 addition & 1 deletion be/benchmark/benchmark_column_array_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ static ColumnPtr make_string_array_column() {

// Wrap with outer Nullable (no rows are actually null, just the wrapper overhead).
static ColumnPtr wrap_nullable(const ColumnPtr& col) {
return ColumnNullable::create(col->assume_mutable(),
return ColumnNullable::create(col->assert_mutable(),
ColumnUInt8::create(col->size(), 0));
}

Expand Down
2 changes: 1 addition & 1 deletion be/benchmark/benchmark_column_array_view_distance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ BENCHMARK(ArrayView_Distance_Const_Plain_Flat)->Unit(benchmark::kNanosecond);
// ============================================================

static ColumnPtr wrap_nullable_for_dist(const ColumnPtr& col) {
return ColumnNullable::create(col->assume_mutable(), ColumnUInt8::create(col->size(), 0));
return ColumnNullable::create(col->assert_mutable(), ColumnUInt8::create(col->size(), 0));
}

static void Handwritten_Distance_Nullable_Plain(benchmark::State& state) {
Expand Down
2 changes: 1 addition & 1 deletion be/benchmark/benchmark_fastunion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

#include <string>

#include "util/bitmap_value.h"
#include "core/value/bitmap_value.h"

using Roaring64Map = doris::detail::Roaring64Map;

Expand Down
2 changes: 1 addition & 1 deletion be/benchmark/benchmark_hll_merge.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include <benchmark/benchmark.h>

#include "olap/hll.h"
#include "core/value/hll.h"
#include "util/hash_util.hpp"

namespace doris {
Expand Down
18 changes: 2 additions & 16 deletions be/benchmark/benchmark_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,40 +24,28 @@

#include "benchmark_arrow_validation.hpp"
#include "benchmark_bit_pack.hpp"
#include "benchmark_bits.hpp"
#include "benchmark_block_bloom_filter.hpp"
#include "benchmark_column_array_view.hpp"
#include "benchmark_column_array_view_distance.hpp"
#include "benchmark_column_view.hpp"
#include "benchmark_damerau_levenshtein.hpp"
#include "benchmark_fastunion.hpp"
#include "benchmark_fmod.hpp"
#include "benchmark_hll_merge.hpp"
#include "benchmark_hybrid_set.hpp"
#include "benchmark_pdep_unpack.hpp"
#include "benchmark_string.hpp"
#include "benchmark_string_replace.hpp"
#include "benchmark_zone_map_index.hpp"
#include "binary_cast_benchmark.hpp"
#include "common/config.h"
#include "core/block/block.h"
#include "core/column/column_string.h"
#include "core/data_type/data_type.h"
#include "core/data_type/data_type_string.h"
#include "parquet/benchmark_file_scanner_expr.hpp"
#include "parquet/benchmark_parquet_decoder.hpp"
#include "parquet/benchmark_parquet_kernels.hpp"
#include "parquet/benchmark_parquet_reader.hpp"
#include "parquet/benchmark_parquet_selection.hpp"
#include "runtime/exec_env.h"
#include "runtime/memory/mem_tracker_limiter.h"
#include "runtime/memory/thread_mem_tracker_mgr.h"
#include "runtime/thread_context.h"

// benchmark_binary_plain_page_v2.hpp must be included LAST: it transitively pulls AWS SDK
// headers (via storage/cache/page_cache.h) whose symbols shadow types used by the benchmark
// headers above (notably binary_cast_benchmark.hpp). Keeping it last avoids the clash without
// disabling any benchmark. (Do not let clang-format reorder it above the others.)
#include "benchmark_binary_plain_page_v2.hpp"

namespace doris { // change if need

static bool init_benchmark_config(const char* executable) {
Expand Down Expand Up @@ -118,8 +106,6 @@ int main(int argc, char** argv) {
if (!doris::init_benchmark_config(argv[0])) {
return 1;
}
doris::config::enable_bmi2_optimizations = true;

SCOPED_INIT_THREAD_CONTEXT();
doris::ExecEnv::GetInstance()->init_mem_tracker();
doris::thread_context()->thread_mem_tracker_mgr->init();
Expand Down
2 changes: 1 addition & 1 deletion be/benchmark/binary_cast_benchmark.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include <random>
#include <vector>

#include "util/binary_cast.hpp"
#include "core/binary_cast.hpp"

namespace doris {

Expand Down
52 changes: 45 additions & 7 deletions be/benchmark/parquet/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,29 @@ benchmark system described in the design document.

## What exists today

The benchmark binary registers three groups:
The benchmark binary registers five groups:

- `ParquetDecoder`: native page decoder benchmarks using in-memory encoded pages.
- `ParquetKernel`: isolated SIMD-sensitive decode and predicate kernels.
- `ParquetSelection`: isolated selection initialization and predicate compaction paths.
- `ParquetReader`: local-file benchmarks that call the format V2 Parquet reader directly.
- `FileScannerExpr`: expression lifecycle benchmarks for split-local clone, prepare, and open.

The relevant files are:

- `benchmark_parquet_decoder.hpp`: deterministic page construction and decoder registration.
- `benchmark_parquet_selection.hpp`: selection initialization and compaction registration.
- `benchmark_parquet_reader.hpp`: deterministic local Parquet fixtures and reader registration.
- `benchmark_file_scanner_expr.hpp`: runtime-filter expression lifecycle registration.
- `parquet_benchmark_scenarios.h`: scenario definitions and the selected matrix.
- `README.md`: short human-oriented build and invocation examples.
- `be/test/format_v2/parquet/parquet_benchmark_scenarios_test.cpp`: matrix invariants.

Do not describe this suite as end-to-end SQL, `FileScannerV2`, remote I/O, V1/V2 comparison, or a
cross-engine benchmark. The reader benchmark starts at `format::parquet::ParquetReader` and does
not include FE planning, scanner scheduling, `TableReader`, client latency, or Runtime Profile
collection.
collection. `FileScannerExpr` isolates expression lifecycle work and likewise does not execute a
scanner or read a file.

## Build and list cases

Expand All @@ -37,16 +42,25 @@ List all Parquet cases and verify the expected registration counts:

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

be/output/lib/benchmark_test --benchmark_list_tests \
| grep '^FileScannerExpr/'

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

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

be/output/lib/benchmark_test --benchmark_list_tests \
| grep -c '^ParquetSelection/' # currently 25

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

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

When running the binary directly from `be/build_RELEASE/bin`, make sure the JVM and third-party
Expand All @@ -71,11 +85,23 @@ be/output/lib/benchmark_test \
--benchmark_out=parquet-kernel-smoke.json \
--benchmark_out_format=json

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

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

be/output/lib/benchmark_test \
--benchmark_filter='^FileScannerExpr/' \
--benchmark_min_time=0.001s \
--benchmark_out=file-scanner-expr-smoke.json \
--benchmark_out_format=json
```

Reject a smoke run if the process is non-zero, the expected number of JSON results is absent, or
Expand Down Expand Up @@ -128,6 +154,18 @@ rates with both placement patterns, 0% through 100% raw-predicate selectivities,
legacy and fused implementations in the same binary and validates both against an independent
source-level oracle before timing.

`ParquetSelection` contains 25 cases that isolate the selection-vector work used by Parquet
predicate evaluation. It measures identity initialization, one raw-row filter, and two successive
filters. The filter matrix covers 0%, 1%, 10%, 50%, 90%, and 100% selectivity with clustered and
alternating matches. These cases include `SelectionVector::resize()` in the timed region because
initializing a new batch is part of the production predicate path.

`FileScannerExpr` contains eight cases that clone, prepare, and open an already-prepared
`VDirectInPredicate` with 128, 1,024, 8,192, or 65,536 integer set values. Each cardinality registers
`impl_shared` and `impl_rematerialize` in the same binary. Set construction and the original
fragment-level materialization are outside the timed region. The cases model the repeated
split-local expression lifecycle only; they do not include scanner scheduling or file reads.

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

Expand Down Expand Up @@ -302,10 +340,10 @@ be simulated by silently changing the local reader benchmark.

## Current validation record

The current expected registration counts are 228 decoder, 92 kernel, and 167 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.
The current expected registration counts are 228 decoder, 92 kernel, 25 selection, 167 reader, and
8 expression-lifecycle 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
38 changes: 38 additions & 0 deletions be/benchmark/parquet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ List only the Parquet cases:
be/output/lib/benchmark_test --benchmark_list_tests | grep '^Parquet'
```

List the split-local runtime-filter expression lifecycle cases:

```shell
be/output/lib/benchmark_test --benchmark_list_tests | grep '^FileScannerExpr/'
```

## Decoder cases

`ParquetDecoder` measures the native decoder with data generation and encoder setup outside the
Expand Down Expand Up @@ -75,6 +81,20 @@ taskset -c 8 be/output/lib/benchmark_test \
# Repeat fused as B2, then legacy as A2, changing only --benchmark_out.
```

## Selection compaction cases

`ParquetSelection` isolates the selection-vector paths used after raw and expression predicate
evaluation. It covers implicit identity initialization, a filter indexed by source row, and a
second compact filter applied after an earlier predicate has already made the selection sparse.

```shell
be/output/lib/benchmark_test \
--benchmark_filter='^ParquetSelection/(resize_identity|row_filter|cascade_filter)/' \
--benchmark_min_time=1s \
--benchmark_repetitions=10 \
--benchmark_report_aggregates_only=true
```

## Local reader cases

`ParquetReader` measures local open-to-first-block, full scan, predicate scan, complex residual
Expand Down Expand Up @@ -113,3 +133,21 @@ be/output/lib/benchmark_test \
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.

## Runtime-filter expression lifecycle cases

`FileScannerExpr` measures only the repeated deep-clone, prepare, and open work for an already
prepared direct-IN runtime filter. Four cardinalities sweep 128 through 65,536 set values, with
shared-state and forced-rematerialization implementations registered in the same binary. Set
construction and the original fragment-level prepare/open are outside the timed region.

```shell
be/output/lib/benchmark_test \
--benchmark_filter='^FileScannerExpr/direct_in_clone_prepare_open/' \
--benchmark_min_time=1s \
--benchmark_repetitions=10 \
--benchmark_report_aggregates_only=true
```

These cases do not execute `FileScannerV2`, schedule splits, or read Parquet files. They isolate the
expression lifecycle visible in scanner profiles so it can be compared without I/O noise.
Loading
Loading