Skip to content

Opteryx: rebuild the entry after the engine refactor, add native-format variant, refresh results - #1416

Merged
alexey-milovidov merged 6 commits into
ClickHouse:mainfrom
joocer:opteryx-refresh
Aug 28, 2026
Merged

Opteryx: rebuild the entry after the engine refactor, add native-format variant, refresh results#1416
alexey-milovidov merged 6 commits into
ClickHouse:mainfrom
joocer:opteryx-refresh

Conversation

@joocer

@joocer joocer commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

The previous entry targeted Python 3.11 and no longer ran. Opteryx has changed substantially since: the planning engine is largely as it was, still in Python, while the execution engine has been significantly refactored. It now ships as opteryx-core (previously opteryx), with a different execution API.

  • opteryx/ — rebuilt for opteryx-core on CPython 3.14. install, check and query rewritten; 8 queries adapted to the dialect; renamed to Opteryx (Parquet, partitioned) and tagged C++.
  • opteryx-skene/ — new entry for skene, Opteryx's native format, so it takes the unqualified name (as duckdb does against duckdb-parquet-partitioned). Shares the harness; the load step converts the Parquet corpus, so Load time is that conversion.

Results: 0.9.69, nine machines, three tries per query, 387 results with no nulls. Hot totals run from 25.9 s (skene, c8g.4xlarge) and 38.7 s (Parquet, same box) to 2821 s on t3a.small. The previous 0.26.x runs nulled 17 of 43 on t3a.small, 15 on c6a.large and 12 on c6a.xlarge; all now return numbers. The c8g.* results are the first AArch64 numbers for this entry.

Notes:

  • The 8 query adaptations are syntactic — explicit casts on the EventDate/EventTime comparisons, TRUNC for DATE_TRUNC, b''/r'' regex literals. Both READMEs document them.
  • Historical result files keep "system": "Opteryx"; they were accurate when recorded. c6a.metal and c7a.metal-48xl still appear under it until re-run.
  • Coverage is instances of ≤32 vCPUs — the account is capped at 32 concurrent on-demand vCPUs, so the 192-vCPU metals could not be launched.
  • index.html untouched; the website workflow regenerates it.

joocer added 2 commits August 16, 2026 10:32
…ive-format variant

The previous entry targeted Python 3.11 and no longer ran. Opteryx has
changed substantially since: the planning engine is largely as it was,
still in Python, while the execution engine has been significantly
refactored. It now ships as `opteryx-core` (previously `opteryx`), with a
different execution API.

install: stock CPython 3.14 and opteryx-core. Not the free-threaded
3.14t build -- the free-threaded experiment was abandoned in June 2026
(the parallelism target is native C++ threads under a released GIL) and
opteryx-core stopped publishing cp314t wheels after 0.9.16, so a 3.14t
interpreter falls through to the sdist and tries to build Rust/C++ on
the box. The wheel has no runtime dependencies, so this is a single
binary download. Ends with a version banner so a fallback to a source
build fails loudly there rather than 43 queries later.

check: `version()` is no longer a function -- the version is the system
variable `@@version` -- and the old `python -m opteryx` path caught the
resulting error and still exited 0, a false green that let a broken
install through. Probe `@@version` through the Python API and assert the
shape of the result. This matters because bench_load() calls ./check
unconditionally, after the ~14 GB download.

query: rewritten for the current surface (session.execute_to_morsels);
opteryx.query() / Cursor.arrow() are gone. Times the morsel drain, which
is the execution, and emits the full result as TSV afterwards.

queries.sql: adapt 8 queries to the dialect -- explicit casts on the
EventDate/EventTime comparisons, TRUNC for DATE_TRUNC, and b''/r''
literals in the REGEXP_REPLACE. Syntactic only; the unadapted forms
produce null rows for exactly those 8 rather than wrong numbers.

template.json: rename the system to "Opteryx (Parquet, partitioned)",
following duckdb-parquet-partitioned and chdb-parquet-partitioned, which
frees the unqualified name for the native-format entry. Historical
result files keep "Opteryx": they were accurate when recorded and are
not rewritten. Add the "C++" tag, matching the implementation-language
tag carried by comparable embedded engines.

opteryx-skene/ is that native-format entry. skene is Opteryx's own
columnar format, so it takes the unqualified name, as `duckdb` does
against `duckdb-parquet-partitioned`. install, check, query,
queries.sql, start and stop are shared with the Parquet entry verbatim
-- query needs no change at all, since a skene dataset is addressed by
the same directory resolution and `FROM hits` finds ./hits/*.skene.

What differs is the load. ClickBench distributes Parquet, so the dataset
must be converted before it can be queried, and that conversion is the
load step -- Load time is its wall-clock, as for any entry ingesting
source data into a native store. convert.py is self-contained rather
than reusing the engine repo's dev tooling, which a ClickBench run does
not have; everything it needs (skene, draken, rugo) is in the one wheel.
Conversion runs across processes, which costs layout: row groups do not
span chunk boundaries, so a 12-worker build holds 28 files against 24
for a single worker and measures ~7% slower to query. Row count is
verified per chunk and in total, and a mismatch fails the run.

Written lz4 with read acceleration, the engine's read-first posture.
opteryx-core 0.9.69 on CPython 3.14, three tries per query with the page
cache dropped before each first try, run through the shared driver.

Parquet, eight machines spanning 2 to 16 vCPUs on both architectures:
c6a.large, c6a.xlarge, c6a.2xlarge, c6a.4xlarge, c8g.large, c8g.xlarge,
c8g.2xlarge, t3a.small. skene on c8g.4xlarge.

Every query returns on every machine -- 387 results, no nulls. The
published 0.26.x runs nulled 17 of 43 on t3a.small, 15 on c6a.large and
12 on c6a.xlarge; those all now produce numbers. The smaller instances
are slow rather than failing: the heavy GROUP BYs run out of swap (10 GB
against 2 GB of RAM on t3a.small) using the 16 GB swapfile ClickBench's
cloud-init configures for every system.

The c8g.* machines are the first AArch64 results for this entry, which
0.9.69 made possible by publishing manylinux aarch64 wheels. Measured at
matched sizes, Graviton4 leads the equivalent c6a by 50% at 16 vCPU, 30%
at 8, 25% at 4 and 18% at 2 -- the advantage narrowing as the workload
moves from CPU-bound to memory-bound.

Machines above 32 vCPUs are absent: the account running these is capped
at 32 concurrent on-demand vCPUs, so the 192-vCPU metal instances could
not be launched. Both READMEs say so.
@joocer
joocer deployed to benchmark-approval August 16, 2026 09:33 — with GitHub Actions Active
@alexey-milovidov alexey-milovidov self-assigned this Aug 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Results for opteryx are ready for: c6a.4xlarge.
Results for opteryx-skene are ready for: c6a.4xlarge.
The result files are committed as 0e750fa.
Removed manually added result files: opteryx-skene/results/20260815/c8g.4xlarge.json, opteryx/results/20260815/c6a.2xlarge.json, opteryx/results/20260815/c6a.4xlarge.json, opteryx/results/20260815/c6a.large.json, opteryx/results/20260815/c6a.xlarge.json, opteryx/results/20260815/c8g.2xlarge.json, opteryx/results/20260815/c8g.4xlarge.json, opteryx/results/20260815/c8g.large.json, opteryx/results/20260815/c8g.xlarge.json, opteryx/results/20260815/t3a.small.json.

Logs:

@alexey-milovidov alexey-milovidov added the machine:all PR benchmark on every machine type label Aug 27, 2026
@alexey-milovidov
alexey-milovidov deployed to benchmark-approval August 27, 2026 21:21 — with GitHub Actions Active
…large, c6a.large, c6a.metal, c6a.xlarge, c7a.metal-48xl, c8g.4xlarge, c8g.metal-48xl)
@github-actions

Copy link
Copy Markdown
Contributor

Results for opteryx are ready for: c6a.2xlarge, c6a.4xlarge, c6a.large, c6a.metal, c6a.xlarge, c7a.metal-48xl, c8g.4xlarge, c8g.metal-48xl.
Results for opteryx-skene are ready for: c6a.2xlarge, c6a.4xlarge, c6a.metal, c6a.xlarge, c7a.metal-48xl, c8g.4xlarge, c8g.metal-48xl.
The result files are committed as 8c36b5d.

Logs:

@github-actions

Copy link
Copy Markdown
Contributor

Results for opteryx are ready for: t3a.small.
Results for opteryx-skene are ready for: c6a.large.
The result files are committed as f4c91f1.

Logs:

@github-actions

Copy link
Copy Markdown
Contributor

Results for opteryx-skene are ready for: t3a.small.
The result files are committed as 3673577.

Logs:

@alexey-milovidov
alexey-milovidov merged commit f7b22bc into ClickHouse:main Aug 28, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

machine:all PR benchmark on every machine type

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants