From f84332fcdfb7f03e696758758e9321f77985eb27 Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Tue, 15 Sep 2026 21:07:40 +0100 Subject: [PATCH 1/3] bench(pco): scalar access baseline for CodSpeed Four cases of scalar reads out of a PCO array: a single read, and 1,024 clustered, nullable clustered, and scattered reads. Establishes a CodSpeed baseline so the probe work in encodings/pco can show its effect on merge. Co-Authored-By: Claude Fable 5.1 Signed-off-by: Joe Isaacs --- Cargo.lock | 1 + encodings/pco/Cargo.toml | 4 ++ encodings/pco/benches/scalar.rs | 79 +++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 encodings/pco/benches/scalar.rs diff --git a/Cargo.lock b/Cargo.lock index a2dd783356b..275db7ef8ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11411,6 +11411,7 @@ dependencies = [ name = "vortex-pco" version = "0.1.0" dependencies = [ + "codspeed-divan-compat", "pco", "prost 0.14.4", "rstest", diff --git a/encodings/pco/Cargo.toml b/encodings/pco/Cargo.toml index 1683d4875e9..749464c865c 100644 --- a/encodings/pco/Cargo.toml +++ b/encodings/pco/Cargo.toml @@ -26,7 +26,11 @@ vortex-mask = { workspace = true } vortex-session = { workspace = true } [dev-dependencies] +divan = { workspace = true } rstest = { workspace = true } vortex-array = { workspace = true, features = ["_test-harness"] } vortex-arrow = { workspace = true } +[[bench]] +name = "scalar" +harness = false diff --git a/encodings/pco/benches/scalar.rs b/encodings/pco/benches/scalar.rs new file mode 100644 index 00000000000..c8e4254ce79 --- /dev/null +++ b/encodings/pco/benches/scalar.rs @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: Copyright the Vortex contributors + +//! Scalar reads out of a PCO array. Cases are `(access_count, nullable, scattered)`; clustered +//! indices stay inside one page so a retained decode can be reused, scattered ones cross pages. + +use std::hint::black_box; +use std::sync::LazyLock; + +use divan::Bencher; +use vortex_array::ArrayRef; +use vortex_array::IntoArray; +use vortex_array::VortexSessionExecute; +use vortex_array::arrays::PrimitiveArray; +use vortex_array::validity::Validity; +use vortex_error::VortexExpect; +use vortex_pco::Pco; +use vortex_session::VortexSession; + +fn main() { + divan::main(); +} + +const LEN: usize = 16_384; +const CASES: &[(usize, bool, bool)] = &[ + (1, false, false), + (1024, false, false), + (1024, true, false), + (1024, false, true), +]; + +static SESSION: LazyLock = LazyLock::new(vortex_array::array_session); + +fn pco(nullable: bool) -> ArrayRef { + let validity = if nullable { + Validity::from_iter((0..LEN).map(|i| i % 11 != 0)) + } else { + Validity::NonNullable + }; + let input = PrimitiveArray::new( + (0..LEN) + .map(|i| u32::try_from(i / 16).vortex_expect("fixture values fit u32")) + .collect::>(), + validity, + ); + let mut ctx = SESSION.create_execution_ctx(); + Pco::from_primitive(input.as_view(), 8, 1024, &mut ctx) + .vortex_expect("PCO compression") + .into_array() +} + +fn indices(count: usize, scattered: bool) -> Vec { + let span = if scattered { LEN } else { 256 }; + let base = if scattered { 0 } else { 4096 }; + let mut seed = 42u64; + (0..count) + .map(|_| { + seed = seed.wrapping_mul(6364136223846793005).wrapping_add(1); + base + ((seed >> 32) as usize % span) + }) + .collect() +} + +#[divan::bench(args = CASES)] +fn scalar_access(bencher: Bencher, (count, nullable, scattered): (usize, bool, bool)) { + let array = pco(nullable); + let indices = indices(count, scattered); + bencher + .with_inputs(|| SESSION.create_execution_ctx()) + .bench_refs(|ctx| { + for &index in &indices { + black_box( + array + .execute_scalar(black_box(index), ctx) + .vortex_expect("scalar access"), + ); + } + }); +} From e08f432b8e348d8f54441c165a81c10eaf979c4b Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Tue, 15 Sep 2026 21:15:39 +0100 Subject: [PATCH 2/3] bench(pco): collect scalars into a pre-sized Vec dropped outside timing Co-Authored-By: Claude Fable 5.1 Signed-off-by: Joe Isaacs --- encodings/pco/benches/scalar.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/encodings/pco/benches/scalar.rs b/encodings/pco/benches/scalar.rs index c8e4254ce79..692a9132069 100644 --- a/encodings/pco/benches/scalar.rs +++ b/encodings/pco/benches/scalar.rs @@ -4,7 +4,6 @@ //! Scalar reads out of a PCO array. Cases are `(access_count, nullable, scattered)`; clustered //! indices stay inside one page so a retained decode can be reused, scattered ones cross pages. -use std::hint::black_box; use std::sync::LazyLock; use divan::Bencher; @@ -66,14 +65,10 @@ fn scalar_access(bencher: Bencher, (count, nullable, scattered): (usize, bool, b let array = pco(nullable); let indices = indices(count, scattered); bencher - .with_inputs(|| SESSION.create_execution_ctx()) - .bench_refs(|ctx| { + .with_inputs(|| (SESSION.create_execution_ctx(), Vec::with_capacity(count))) + .bench_refs(|(ctx, scalars)| { for &index in &indices { - black_box( - array - .execute_scalar(black_box(index), ctx) - .vortex_expect("scalar access"), - ); + scalars.push(array.execute_scalar(index, ctx).vortex_expect("scalar access")); } }); } From 7403cf413d465a1c02d8a4147d4e293eb95bebad Mon Sep 17 00:00:00 2001 From: Joe Isaacs Date: Tue, 15 Sep 2026 22:18:46 +0100 Subject: [PATCH 3/3] bench(pco): rustfmt Co-Authored-By: Claude Fable 5.1 Signed-off-by: Joe Isaacs --- encodings/pco/benches/scalar.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/encodings/pco/benches/scalar.rs b/encodings/pco/benches/scalar.rs index 692a9132069..eff55fceb8c 100644 --- a/encodings/pco/benches/scalar.rs +++ b/encodings/pco/benches/scalar.rs @@ -68,7 +68,11 @@ fn scalar_access(bencher: Bencher, (count, nullable, scattered): (usize, bool, b .with_inputs(|| (SESSION.create_execution_ctx(), Vec::with_capacity(count))) .bench_refs(|(ctx, scalars)| { for &index in &indices { - scalars.push(array.execute_scalar(index, ctx).vortex_expect("scalar access")); + scalars.push( + array + .execute_scalar(index, ctx) + .vortex_expect("scalar access"), + ); } }); }