Skip to content

EQL v3 benchmark suite with v2 regression comparison#23

Open
coderdan wants to merge 18 commits into
mainfrom
eql-v3-benches
Open

EQL v3 benchmark suite with v2 regression comparison#23
coderdan wants to merge 18 commits into
mainfrom
eql-v3-benches

Conversation

@coderdan

@coderdan coderdan commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

What

Parallel benchmark suite for the upcoming EQL v3 release (domain-specific types — eql_v3.text_search, eql_v3.integer_ord, eql_v3.integer_ord_ope, … — replacing the single eql_v2_encrypted composite). The v2 benches and committed results are untouched: they are the regression baseline. v3 results land in results/{query,ingest}/v3/, joined to v2 by identical criterion scenario ids.

Full comparison: report/V3_COMPARISON.md (regression tables, index-engagement audit, ingest deltas, index build times) with PNG+SVG charts in report/v3/ for docs/marketing.

Headlines (1M rows, M1 Max, PG 17)

  • OPE is the fast path: encrypted range + ordered queries at 0.12 ms — ~1.2× plaintext Postgres and ~6× faster than ORE; the OPE index builds in 1 s vs 44 s for ORE at 1M.
  • ORE LIMIT 100 range queries 4× faster than v2 (functional index engages where v2 seq-scanned).
  • The bloom-match GIN engages via native array_ops (v3 ships no GIN opclass — this was the biggest open risk) and is worth 100–400× vs no index.
  • Exact equality 0.12 ms (~1.3× plaintext); GROUP BY at parity or better vs v2.

Findings for the EQL team (pre-release)

  1. String ingest −87%: text_search (the only eq+match text domain) requires the ORE term, capping string ingest at ORE-generation speed (~1.3k rec/s vs 9.6k on v2's unique+match). An hm+bf-only text domain would restore it.
  2. ORE ordered scans +43% vs v2 — consistent with the plpgsql ore_block_256 opclass comparator; OPE is the escape hatch.
  3. Diffuse +12–44% on JSON extractor scenarios (contains, field_order, field_eq) — per-row v3 extractor cost.
  4. The +17,658% JSON field_eq/extractor outlier is a diagnosed bench artifact (every-row needle × sqlx generic-plan flip → full 1M-row GIN bitmap before LIMIT), documented in the report — not a v3 defect.

Methodology / caveats

  • v3 payloads via eql-bindings::from_v2 over the pinned cipherstash-client 0.34.1-alpha.9 (the supported migration path); conversion is inside the measured ingest path (int ingest: ±2% vs v2, so conversion+CHECK cost ≈ 0).
  • No v3 scalar query wire shape exists — query params are stored-shape payloads; server-side timings unaffected.
  • OPE op terms are synthetic (fixed-width order-preserving hex; order-parity asserted at bench startup) until a client emits CLLW-OPE (CIP-3348) — plan shapes faithful, ciphertext size approximate.
  • Tiers 10k/100k/1M (10M deferred). mise run setup-db-v3 builds the bundle from a local eql_v3 checkout until eql-3.x is released; the Cargo git dep should move to the release tag then.

Running

mise run setup-db-v3
mise run bench:v3:query:all 1000000
mise run bench:v3:ingest
mise run report:v3-compare

https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav

coderdan added 6 commits July 4, 2026 10:15
Adds a parallel v3 bench suite targeting the upcoming EQL v3 release
(domain-specific types replacing the eql_v2_encrypted composite). The v2
benches and their committed results are untouched — they are the
regression baseline; v3 results land in results/{query,ingest}/v3/.

Harness (src/v3.rs): v3 payloads come from eql-bindings::from_v2 over the
pinned cipherstash-client's v2.3 output (the supported migration path).
No v3 scalar query wire shape exists, so all query parameters are
stored-shape payloads; the OPE benches synthesize the `op` term
(fixed-width order-preserving hex) until a client emits CLLW-OPE.

Benches: exact/match/ore/group_by/json/combo mapped onto v3 domains with
scenario ids preserved for the report join, plus new ope (ORE-vs-OPE
ordering), scalar_smoke (date/timestamp/numeric/bigint/double/boolean),
and plaintext baselines for the overhead-vs-native story.

Report (report_v3_compare.py, mise run report:v3-compare): regression
table with semantics-changed annotations, index-engagement audit, ingest
comparison, index build times, and PNG+SVG charts.

Headlines at 1M rows: OPE range/ordered queries at 0.12ms (~1.2x
plaintext, 6x faster than ORE; index builds 1s vs 44s); ORE LIMIT-100
ranges 4x faster than v2; bloom GIN engages via native array_ops.
Findings for the EQL team: text_search requires the ORE term (string
ingest capped at ~1.3k rec/s, -87% vs v2 — an hm+bf-only domain would
restore it); ORE ordered scans +43% vs v2 (plpgsql opclass comparator);
diffuse +12-44% on JSON extractor costs. Full detail and diagnosed bench
artifacts in report/V3_COMPARISON.md.

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
The report / report:slow / report:ingest tasks scan only the v2 baseline
directories (results/query, results/ingest) — v3 results live in v3/
subdirectories and were invisible to them. Add --v3 flags to both
terminal reporters and v3 sibling tasks:

  report:v3          all v3 scenarios, slowest first
  report:v3:slow     v3 scenarios over N ms (default 100)
  report:v3:ingest   v3 ingest throughput

report:v3-compare now prints the v2/v3 side-by-side join on the CLI
(medians + delta + flag per scenario/tier, plus v3-only scenarios); the
Markdown+charts generator moves to report:build:v3-compare, matching the
report / report:build split the v2 tasks already use.

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
Adds v3-regressions-report.md: scenario-by-scenario analysis of the
flagged v2->v3 regressions, with the exact queries both versions ran,
function-level attribution (track_functions), and validated fixes.

Key findings, each empirically validated on the live bench DB:

- The ORE ordered-scan regression (+43%) is NOT the opclass comparator
  (per-query comparator time is identical across versions). It is the
  term-extraction helpers (jsonb_array_to_bytea_array,
  jsonb_array_to_ore_block_256) being rewritten from v2's plpgsql to
  LANGUAGE sql: in the opclass call path they cannot inline and pay the
  per-call SQL-function executor (3.5x per-call cost, identical logic).
  A local logic-identical plpgsql swap (A->B->A) eliminated the entire
  regression; end-to-end criterion reruns with the patch:
  ORE/range_lt_ordered_10 0.736 -> 0.553 ms, COMBO/bloom_ore_order_limit
  22.70 -> 13.97 ms (16% faster than v2). Controls unmoved.
- JSON/field_eq/functional (+19%) is entirely the eql_v3.jsonb_entry
  domain CHECK calling a non-inlinable LANGUAGE sql validator (18us per
  needle cast); v2's CHECK was an inline expression. Third instance of
  the same pattern.
- btree-vs-hash accounts for only ~0.004 ms of the EXACT/eql_hash delta
  (direct A/B); the btree choice stands for build-time reasons.

Ends with an Issues section (4 items, incl. the team's k="q" query
payload variant) ready to lift into Linear. All experiment state was
reverted after measurement; committed bench results are untouched
(SVGs re-rendered by the report build, build-times log gains the v2
repopulation entries - note v2 ORE 1M index build 42s vs v3 44s,
corroborating comparator parity).

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
…s approach)

Reviewing James's PR #22 (stacked on #21/#20, a parallel v3 bench
implementation) surfaced two adoptable facts: cipherstash-client 0.38.1
emits the scalar OPE-CLLW `op` term via Index::new_ope() (CIP-3280), and
eql-bindings is published on crates.io. Adopt both into this branch
rather than merging the parallel machinery (which duplicates ours under
different table/task names and has no results):

- Bump cipherstash-client + stack-profile to =0.38.1 (v2 wire format
  unchanged); switch eql-bindings from the git branch dep to crates.io
  =0.4.2.
- encrypt_int_ope_v3 + benches/ope_v3.rs now use Index::new_ope() for
  REAL op terms end-to-end; the synthetic-op machinery is removed from
  src/v3.rs (to_v3_stored_with_synth_ope, ingest_v3_synth_ope,
  i32_order_key, SYNTH_OPE_HEX_WIDTH). The startup order-parity gate now
  verifies real crypto ordering.
- OPE tiers re-ingested with real ciphertexts (33-byte op terms, ~2x the
  synthetic width) and all OPE query benches re-run: medians unchanged
  (0.118-0.124 ms flat at every tier) — the headline OPE numbers hold
  with real crypto.
- All v3 ingest benches re-run under 0.38.1: ORE int and string at
  parity with the alpha.9 numbers (client bump doesn't shift existing
  comparisons), and a NEW headline: real OPE ingest runs 10,933 rec/s at
  10k — 5.3x ORE int ingest (2,076 rec/s), since OPE term generation is
  far cheaper client-side than ORE block generation.
- Synthetic-op caveats removed across README, reports, task descriptions.

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
…ipeline

Replace the parallel IngestOptions::ingest_v3(f, "<target>") method with
James's versioning-as-configuration shape from PR #21: the builder gains
.convert_to_v3(TargetDomain) and the single ingest() branches on the
stored eql_target. One batch loop instead of a duplicated one, and the
target is a typed TargetDomain resolved at the builder call site (bad
domain names fail at build time, not mid-ingest). TargetDomain is
re-exported from dbbenches::v3 so binaries don't depend on eql-bindings
directly; to_v3_stored_target() is the pre-parsed hot-loop conversion.

The V3_CONVERT_ONLY decomposition flag moves into the Some(target)
branch unchanged. The custom multi-column binaries (encrypt_combo_v3,
encrypt_scalar_smoke_v3) keep calling to_v3_stored directly - they never
used IngestOptions.

Smoked both branches at 100 records each: v2 (None), integer_ord,
integer_ord_ope (real op, 33-byte terms), text_search - all insert
cleanly. This supersedes the ingest side of PRs #21/#22, which can now
be closed (#20's 0.38.1 bump is merged and adopted here).

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
…ere)

# Conflicts:
#	Cargo.toml
#	src/lib.rs
…ssions

Bench DB patched to the eql_v3 release-tip SQL surface (surgical
apply of the two merged fixes; object-state verified identical to a
fresh tip install, incl. search_path pin states) and the affected
families (ore, combo, json) re-run at 10k/100k/1M.

Flagged regressions: 14 -> 3. At 1M: ORE ordered scan 0.736 -> 0.548ms
(+6.8% vs v2, within the stored-needle overhead tracked as CIP-3383),
COMBO bloom+ORE-order 22.70 -> 14.21ms (14.6% FASTER than v2),
JSON field_eq at parity, JSON field_order 23.7% faster than v2. The
remaining flags are the bloom GIN's array_ops delta at two tiers and
the 10k ordered-scan residual - all small-absolute, all tracked.

The upgrade exercise itself surfaced a release-process gap (no safe
patch/minor upgrade path for installed EQL; uninstall is destructive
for v3 domain columns) - discussed separately for the issue list.

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
coderdan added 8 commits July 4, 2026 15:38
…0M groundwork

- report_flat_latency.py: theme-aware light/dark SVG pair for the
  cipherstash/stack README Performance section (Asset 3 spec). Palette
  matches the stack architecture diagrams; fixed 2-accent brand palette
  gets CVD relief via distinct markers, dashed ink line, and direct
  labels. Tiers auto-detected so the chart and callout upgrade from
  10k->1M to 10k->10M when the 10M results land. Plaintext band uses
  the two btree-indexed baselines only (the unindexed json baseline's
  growth is a baseline artifact, not a fair reference).
- Full clean query sweep: every family re-run at 10k/100k/1M on the
  release-tip EQL surface under client 0.38.1. Final state: 3 flags,
  all <= 72us absolute, all tracked (stored-needle cost at small
  tiers, CIP-3383; bloom GIN array_ops delta at 10k). _decrypt
  variants are now informational-only in the regression gate (they
  measure ZeroKMS round-trips + client version, not EQL).
- 10M tier groundwork for the chart tables (string/integer/ope/json
  encrypted + plaintext baselines): schema, index DDL.

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
…lete)

10M ingest + benches for exact/ore/ope/json/plaintext. The chart now
carries the spec's full claim with real EQL v3 data: "Latency stays
flat from 10k -> 10M rows" - equality 0.14ms, JSON field equality
0.11ms, ORE range+ORDER BY 0.53ms, OPE 0.115ms, all flat across three
orders of magnitude, plaintext band 0.09-0.10ms.

10M highlights vs the committed v2 baseline: ORE LIMIT-100 ranges
75-79% faster; field_order 32% faster; ordered scan at parity (+3.6%);
field_eq at parity. Index builds at 10M: OPE seconds vs ORE 474s
(integer) / 896s total for string's three indexes. New flags to triage:
eql_cast +25.8% at 10M (+0.03ms absolute; stored-needle + wider
text_search rows) and JSON contains/functional 3.36ms vs v2's 0.85ms
(semantics-changed recipe; GIN posting-list growth at 10M - worth an
upstream look before quoting containment numbers at scale).

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
report:build was v2-only (non-recursive results/{query,ingest} layout;
left untouched as the generator of the committed v2 report). Add a
--v3 mode to report_benchmarks.py: reads the v3/ result subdirs, uses
the v3 ingest inventory (int, int_ope, string, category,
ste_vec_small with the _v3 filename suffix), titles the report
"(EQL v3)", and writes everything into report/v3/full/ so the ~45
chart PNGs can't collide with the committed v2 report's files.

New task: mise run report:build:v3. Generated output committed:
per-family pages incl. the v3-only OPE family, all four tiers for the
chart scenarios.

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
…t comparisons

Restructure per review: the main report should carry the v3 numbers
with the comparisons folded in, giving the full picture in one place.

- report/BENCHMARK_REPORT.md: EQL v3 ingest + per-family query pages,
  plus two new sections — "Comparison vs EQL 2.3" (flagged deltas
  table, summary counts, v3_vs_v2 charts; full 115-pair table stays in
  V3_COMPARISON.md) and "Comparison vs plaintext PostgreSQL"
  (encrypted-vs-plaintext ratios per scenario x tier + overhead
  charts). Sections are built from report_v3_compare's loaders so the
  two reports cannot drift.
- report_benchmarks.py: v3 is now the DEFAULT mode; --v2 rebuilds the
  archived EQL 2.3 report.
- The committed v2 report moved wholesale to report/v2/ (links intact);
  report/v3/full/ removed (superseded by the main report).
- mise: report:build = the main (v3) report; report:build:v2 replaces
  report:build:v3. README links updated.

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
1. Ingest report sections/charts in v3 mode are now named by the EQL v3
   domain type they write (eql_v3.text_eq, eql_v3.integer_ord_ope, ...)
   instead of bench shorthand ("Category", "Int Ope") — the question the
   ingest report answers is "how does each type perform for ingest".
2. GROUP BY at 10M: category_encrypted_v3 + category_plaintext 10M
   tables added and populated; group_by bench run at 10M fills the two
   missing plaintext-comparison cells (encrypted ~2.7x plaintext at
   10M). First-run v2 deltas (+13-16%) are single datapoints — a
   stability re-run is in flight before treating them as real.
3. Noise re-checks on the four flagged pairs: eql_cast@100k (+1.1%),
   eql_bloom@10k (+7.6%), and ore-ordered@10k (+6.1%) all drop below
   the threshold on fresh runs — small-tier flags oscillate +-5-8%
   around small true deltas. eql_cast@10M persists at +14.8% (was
   +25.8%): ~16us residual, consistent with wider text_search rows +
   the stored-shape query-needle freight (CIP-3383).
4. Terminology: "stored-needle" -> "stored-shape query needle"
   throughout the regression report (the needle is the passed query
   term; only its wire shape is the stored one).

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
Second group_by run at 10M reproduces the first within 2%
(887/901 ms vs 902/918 ms) — the +11-16% delta vs the May-measured v2
baseline is consistent, not run noise. A same-day v2 re-measurement is
in flight to rule out cross-session environment drift before the
delta is treated as a real v3 cost; verdict to follow.

Reports rebuilt with the run-2 numbers and current flag state
(3 flags: eql_cast@10M +14.8%, GROUP BY 10M x2).

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
…asurement)

Repopulated the v2 category/string tables at 10M and re-ran v2's
group_by and exact benches under today's conditions (committed baseline
files captured and restored). Verdict: the May-measured baseline drifts
+-8-19% from same-day v2 at the 10M tier, and against SAME-DAY v2 the
three remaining flags disappear — eql_cast -3.3% (v3 faster), top_n
GROUP BY -0.7%, low-cardinality GROUP BY +6.4% (under threshold).

v3 is regression-clean vs same-day v2, apart from documented
semantics-changed items (eql_hash's hash->btree trade measures +36% vs
a fresh same-day hash index, as expected) and the sub-threshold
small-tier deltas tracked by CIP-3383. Comparison notes + methodology
updated so the flags render with their adjudication inline.

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
The same-day v2 re-measurement repopulated category/string v2 tables at
10M; their index builds (148s / 342s) logged here alongside the v3
build times.

Claude-Session: https://claude.ai/code/session_01StQnoycoFXMDdSpQ6zKDav
@freshtonic

Copy link
Copy Markdown
Contributor

Cross-checked this suite against the current state of the EQL v3 stack (post eql-3.0.0-alpha.2 + protect-ffi 0.27 + the stack #547 re-baseline). This PR is where the entire v3 benchmark surface lives, so gaps here = gaps in v3 benchmarking overall. What's outstanding, split by when it can be addressed:

Actionable now (this PR or immediately after merge):

  1. Released-bundle provenance — the methodology notes setup-db-v3 builds from a local eql_v3 checkout "until eql-3.x is released". eql-3.0.0-alpha.2 is now released (2026-07-04), so setup can move to the release artifact (the stack repo made the same swap in feat(stack,cli): EQL v3 Supabase adapter (encryptedSupabaseV3) + v3 install path stack#547).
  2. eql_v3_internal split verification — alpha.2 moved the raw-jsonb SEM extractors (hmac_256/bloom_filter/ore_block_256/ope_cllw) into eql_v3_internal; the per-domain eq_term/ord_term/match_term/ord_ope_term wrappers stayed in eql_v3. The EXPLAIN audits here appear to use the wrappers (which survive unchanged), but worth one pass to confirm no index script or query shape calls a moved extractor — in the stack repo this broke 10 call sites silently until the live suite ran.
  3. 10M tier — deferred here at 10k/100k/1M, but the v2 baseline (bench: refresh full query + ingest suite (10k–10M) against EQL 2.3 #14) ran to 10M, so the regression comparison is missing its top tier.

Post-merge follow-ups worth tracking (upstream-gated):

  1. text_search restructure re-run — the −87% string-ingest finding (finding 1) is the empirical case for the in-flight upstream change making text_search equality+match-only (Linear CIP-3401). When it lands, the string-ingest tiers need re-running to confirm recovery — the tightest feedback loop between this suite and EQL design.
  2. v3 scalar query wire shape — query params here are stored-shape payloads (correctly noted in the caveats; no scalar query envelope exists — same interim as the stack's Supabase adapter, protect-ffi throws EQL_V3_QUERY_UNSUPPORTED). When the term-only scalar query envelope ships (Linear CIP-3402), param-size/parse costs change and the query benches warrant a re-run.
  3. Nice-to-have: a "Supabase profile" variant — no operator classes, functional-index-only, mirroring what managed Postgres actually permits. The OPE headline (natively bytea-sortable, 1s index build) already implies the answer there, but it's currently inferred rather than measured.

None of these block this PR — items 1–2 could ride along if convenient, 3–6 are follow-ups. The suite itself is the missing piece: everything above hangs off it landing.

… + field_gt

Addresses PR #23 review (James's items #1 and #2):

- setup-db-v3 now installs the pinned eql-3.0.0-alpha.3 release bundle
  instead of building from a local eql_v3 checkout. alpha.3 moved the
  per-domain types eql_v3.* -> public.* and removed jsonb_query, so the
  whole v3 surface is migrated to public.<type> (schema_v3.sql, sql/indexes,
  *_v3 benches, encrypt binaries, src/v3.rs); eql_v3.* FUNCTIONS
  (eq_term/ord_term/match_term/ord_ope_term/ore_cllw/jsonb_*) are unchanged.
- Verified no bench/index/schema calls a moved eql_v3_internal extractor
  (hmac_256/bloom_filter/ore_block_256/ope_cllw) directly — item #2.

JSON bench now queries through the named EQL JSON functions rather than raw
jsonb @>/-> operators:
- contains/extractor: eql_v3.jsonb_contains(value, $1) on GIN(eql_v3.jsonb_array(value))
- field access: eql_v3.jsonb_path_query_first(value, sel) feeding eql_v3.eq_term / eql_v3.ore_cllw
- new scenario json/field_gt/functional: the encrypted `x->'y' > 10` range
  query -- `>` on public.jsonb_entry inlines to ore_cllw compare, reusing
  field_order_idx (no new index).

Re-ingested + re-ran the JSON tiers 10k-1M-10M against alpha.3 in an isolated
DB and regenerated report/V3_COMPARISON.md + report/BENCHMARK_REPORT.md.
contains/functional @10m improves 3.36ms -> 1.05ms (jsonb_array recipe).
Non-JSON v3 numbers remain the alpha.2-equivalent baseline pending a full
re-baseline (flagged by a "Re-baseline status" banner in the report).
@coderdan

coderdan commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough cross-check, James — pushed as 80b5972. #1 and #2 done; #3–6 handled/tracked as below.

#1 — released bundle. setup-db-v3 now installs the pinned release (EQL_V3_VERSION, default eql-3.0.0-alpha.3) instead of building from a local checkout. Important heads-up: alpha.3 (2026-07-08) moved the per-domain types eql_v3.* → public.* and dropped the jsonb_query type, so this was a full migration of the schema/index/bench/binary SQL to public.<type> — not just a download swap. The eql_v3.* functions are unchanged.

#2eql_v3_internal split. Confirmed clean against a fresh alpha.3 install: nothing here calls a moved extractor (hmac_256/bloom_filter/ore_block_256/ope_cllw) directly — all through the public eql_v3.* wrappers. (Nice bonus: alpha.3 inlined the jsonb_entry CHECK, citing cipherstash/benches#23 — that's the fix for the +19% field_eq regression we reported.)

JSON bench. Two changes beyond the migration:

  • Rewrote it to query through the named EQL JSON functionseql_v3.jsonb_contains (GIN over eql_v3.jsonb_array(value)), eql_v3.jsonb_path_query_first(value, sel) feeding eql_v3.eq_term/eql_v3.ore_cllw — instead of casting to raw jsonb and using native @>/->.
  • Added json/field_gt/functional, the encrypted equivalent of x -> 'y' > 10: WHERE jsonb_path_query_first(value, sel) > $1::jsonb::public.jsonb_entry — the > on public.jsonb_entry inlines to an ORE-CLLW compare, so it reuses the ore_cllw functional index (Index Scan at all tiers incl. 10M).

#3 — 10M tier. The JSON tiers are now re-ingested + re-run against alpha.3 at 10k/100k/1M/10M and both reports (V3_COMPARISON.md, BENCHMARK_REPORT.md) are regenerated. Notably contains/functional @10m improved 3.36ms → 1.05ms under the jsonb_array recipe. The non-JSON v3 scenarios are still the alpha.2-equivalent baseline — a full alpha.3 re-baseline of those is the tracked follow-up, flagged by a "Re-baseline status" banner in the report so the absolute numbers aren't misread.

#4–6 — ack'd as upstream-gated. FYI the local checkout already has the scalar query-operand terms in flight (CIP-3432), which is the #5 (EQL_V3_QUERY_UNSUPPORTED / scalar query wire shape) trigger; we'll re-run the query benches when that ships.

coderdan added 2 commits July 9, 2026 10:13
…ded allowlist

The V3_COMPARISON.md 'v3-only scenarios' section used a hardcoded prefix
allowlist (OPE/, SMOKE_V3/, PLAINTEXT/, _noindex/) that predated the new
JSON field_gt scenario, so field_gt showed only in the index-engagement
audit and its medians were absent. Derive v3-only the same way the CLI
table already does — any v3 scenario whose prefix never matched a v2
counterpart — so new v3-only scenarios appear automatically. Regenerates
report/V3_COMPARISON.md (field_gt medians now listed).
- Re-ran all five v3 ingest benches (int, int_ope, category, JSON ste_vec,
  string) against the eql-3.0.0-alpha.3 release in an isolated DB and
  refreshed results/ingest/v3/*. Numbers match the alpha.2-era run within
  noise (int 10k ~2154 rec/s, JSON ~4461, string ~1037) — the type-schema
  move eql_v3.* -> public.* and the alpha.3 CHECKs add negligible ingest cost.
- report_benchmarks.py now labels v3 domains public.<type> (was eql_v3.<type>),
  fixing the stale type names in BENCHMARK_REPORT.md and the per-bench pages.
- Regenerated report/BENCHMARK_REPORT.md + report/V3_COMPARISON.md.

Non-JSON *query* pages still show eql_v3.* in their captured SQL text — those
metadata are alpha.2-era and update on the deferred full re-baseline (flagged
by the report's Re-baseline status banner).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants