Skip to content
Merged
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
4 changes: 2 additions & 2 deletions benchmarks/experiments/CAMPAIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,15 +213,15 @@ Rules every campaign keeps:
| 69 | One served lane gets a sensitivity arm for ArcadeDB at the image's own JVM defaults (75% heap, generational ZGC, no `-Xms`; ArcadeData/arcadedb#9167), printed beside the main arm: documents OLTP, served, the 2M-part cell, 3 repetitions | ArcadeDB served only | built (the user, DECISIONS #159): `runner.BACKENDS["arcadedb_imgdefaults_server"]` declared once in `runner.ARM_RUNS`; every served cell records `server_jvm_*` and the arm refuses to run unless the JVM reports those defaults; `fairness_check` F3b and F10 (`test_f10_restricted_arm.py`); `test_jvm_defaults_arm.py` | ArcadeData/arcadedb#9167 |
| 70 | The TimescaleDB time-series arm runs `ANALYZE p` after its `(host, ts DESC)` index, inside its ingest timer, as the plain PostgreSQL arm does | TimescaleDB, the time-series lane only | **owed at the re-pin, done on repin-prep-2 (2026-10-06, the user's decision), now on main**: `l4_tsbs.py`. October's TimescaleDB l4 ingest rows (417314c18) were measured WITHOUT the ANALYZE and stay as measured | `test_ingest_prose.py`; `test_l4_analyze.py` |
| 71 | The served graph arm over Bolt in place of HTTP | ArcadeDB served, the graph arm only | **decided against (DECISIONS #162 item 2)**: with the lean HTTP client (row 72) one bound read costs 121 us over HTTP against 171 to 194 us over Bolt, and upstream's question on which protocol a Python client should use (ArcadeData/arcadedb#9165) is unanswered; the branch `levers-served-bolt` (`21a6ffd47e`) stays unmerged and off by default | `.notes` repros/levers-audit-20261006/LEVERS.md |
| 72 | Every ArcadeDB SERVED arm that talks HTTP uses one persistent `http.client` connection per host (`lean_http.py`) in place of `requests.Session` | every ArcadeDB served arm that posts to the server; no comparator client moves | built (the maintainer's decision, DECISIONS #162 item 1); rows record `arcadedb_http_client` (the headline client and the lean sensitivity twin are described under row 82); `test_lean_http.py`, `test_lean_http_live.py`, `test_e4_client_axis.py`. **Owed at the re-pin:** the e4 stage re-runs, and the page prose around the table (its caption and the "wire format" paragraph) is rewritten from the new columns. October's served rows (417314c18) carry no `arcadedb_http_client` | `.notes` repros/levers-audit-20261006/LEVERS.md |
| 72 | Every ArcadeDB SERVED arm that talks HTTP uses one persistent `http.client` connection per host (`lean_http.py`) in place of `requests.Session` | every ArcadeDB served arm that posts to the server; no comparator client moves | built (the maintainer's decision, DECISIONS #162 item 1); rows record `arcadedb_http_client` (the headline client is described under row 82); `test_lean_http.py`, `test_lean_http_live.py`, `test_e4_client_axis.py`. **Owed at the re-pin:** the e4 stage re-runs, and the page prose around the table (its caption and the "wire format" paragraph) is rewritten from the new columns. October's served rows (417314c18) carry no `arcadedb_http_client` | `.notes` repros/levers-audit-20261006/LEVERS.md |
| 73 | JPype is pinned to 1.7.1 in the benchmark images and recorded per row; reason and the measurement: `.notes/bench/repros/jpype-master-check-20261006/`. The wheel declares `jpype1>=1.5.0` with no upper bound, so an image rebuilt on the day of a JPype release would change the instrument in the middle of a run | every embedded ArcadeDB arm and the host-side Python-cost stage | **built (on main), owed at the re-pin**: `bench_common.JPYPE_PIN` and `Dockerfile.bench`'s `ARG JPYPE_VERSION=1.7.1`; every generated stage that runs an ArcadeDB arm reads JPype back out of `dbbench:arcadedb` and aborts if it differs; rows record `jpype_version`; `test_jpype_pin.py`. Moving the pin is a deliberate edit of `JPYPE_PIN` and the Dockerfile default between campaigns, never an image rebuild | jpype#1379 |
| 74 | The wheel the 26.10.1 measurement runs on carries the call-overhead change of bindings PR #214 (`fabbda7ab7`) and the columnar insert (row 63) | ArcadeDB embedded arms only | built and verified (2026-10-06): the stages bake a wheel built from this tree (commit `8989cbb0e8`) over the official 26.10.1 jars, sha256 `83a2a40369a411622696aed77361fd3b1c3d23b675d0a784b38b0b022c13c41b` (`PAIR VERIFIED d36b4ca3a`). It is NOT the file PyPI holds for the bindings 26.10.1 release; the page's note on what the Python package costs should name the change when it lands | #214's own A/B (laptop, relative only) |
| 75 | The served ArcadeDB arms that bulk-load through `POST /api/v1/batch` run with `-Darcadedb.server.httpBodyContentMaxSize=68719476736` (64 GiB) in place of 26.10.1's default of 100 MiB | ArcadeDB served only: the graph arm (l2, restart lane) and the cross-model arm (e2) | built and verified on the laptop (2026-10-07), on main: `runner.py` (`HTTP_BODY_MAX_OPT`), `override_registry.py` (`arcadedb_http_body_limit`), PROTOCOL.md section 7, `test_overrides.py`. Mini picks it up at its next `git pull`, which is the user's to time | the 26.10.1 sf10 served graph cell failed rep 1; `.notes/bench/repros/served-body-limit-20261006/` |
| 76 | **`pgvector==0.5.0` and `neo4j-rust-ext==6.3.1.0` go into the `client` image (DECISIONS #173, #174).** In `build_images.sh`, the `[client]=` line: `neo4j==6.3.1` becomes `neo4j==6.3.1 neo4j-rust-ext==6.3.1.0` and `pgvector==0.5.0` is appended; register both in the COMPARATORS.md pin table. The harness side is on main and waits for the image: `l3d_dense.PgVector.connect` and `e2_hybrid.PgAgeE2.__init__` import `pgvector.psycopg` lazily (a cell on an image without the package fails at connect with ImportError, by design), and `neo4j-rust-ext` is a one-`.so` overlay that needs no code. The same PR moved `PostgresTPC` (and `postgres_tuned`) to autocommit for single statements, the pgvector dense and cross-model product loads to binary COPY, and the six QuestDB reads to `binary=True` (PROTOCOL.md section 7) | the `client` image: comparators only; no ArcadeDB arm, no tier 1 stage | **code built, image rebuild pending; lands at the tier 1 to tier 2 boundary of the 26.10.1 measurement (qP10 rebuilds the client image at its start)**, between qP09's ALL-DONE and qP10's first cell, never inside a running stage: rebuild, `verify_pair`, `queue_lint`, then check inside the image that `neo4j.RUST_AVAILABLE` is True and `import pgvector.psycopg` works before the first cell; the image digest change is expected and recorded | Row 76 is the rebuild; the code half is the PR that added it. Rows stamped by #173 (`neo4j_rust_ext`, `redis_hiredis`, `es_json_serializer`) land in the same rebuild |
| 77 | ArcadeDB's query heap budget (`arcadedb.queryMaxHeapRAM`, default half the JVM heap) raised for the cells the default refuses: the l1tpc tpch10 olap `top_parts` GROUP BY in both ArcadeDB arms (DECISIONS #175, ArcadeData/arcadedb#9402) | ArcadeDB embedded and served, the documents lane, ONLY in the repair stage | **mechanism written, default OFF (humemai/arcadedb-embedded-python#260); the repair stage is generated after qP09 and run before the tier 1 to tier 2 boundary.** `BENCH_ARCADE_QUERY_MAX_HEAP_RAM_MB` adds the JVM option to the embedded arm and to the served arm's JAVA_OPTS and stamps `arcadedb_query_max_heap_ram_mb` and a source on the row; `override: arcadedb_query_ram`. Which rows are the headline (the default rows with the refusal shown, or the raised rows as an escape hatch like row 21's cap and row 75's body limit) is decided at landing. | not an instrument change: unset, nothing differs |
| 78 | The comparator client paths are recorded per row (issue #261; DECISIONS #173, #174): `neo4j_rust_ext`, `redis_hiredis`, `es_json_serializer`, and `pg_client_path` (`autocommit`, `copy_binary`, `binary_cursor`); `qdrant_transport` (#172) was already stamped | comparators only: no ArcadeDB arm | built (DECISIONS #173, #174) | issue #261 |
| 81 | The sparse lane warms up before its timed pass and the runner holds the CPU idle state for each timed cell (DECISIONS #177). Text on the page too: CPU idle states are not controlled on the host, and single-client times under a millisecond include the cores' wake-up latency (PAGE-SPEC section 0a, `setup.cpu_idle_note`) | the sparse lane (warm-up); every lane's rows (hold) | **built (humemai/arcadedb-embedded-python#278).** `bench_common.SPARSE_WARMUP_DEFAULT` untimed searches per engine, 1,000, one full round as the study behind the warm-up used, drawn from queries DISJOINT from the timed set so a query or result cache cannot flatter an engine: the dataset's extra queries when it holds them, else a fixed-seed sample of documents used as queries; the row stamps `sparse_warmup_queries` as run and `sparse_warmup_source` = `extra_queries` or `document_sample`. The hold is `/dev/cpu_dma_latency` at `BENCH_CPU_DMA_LATENCY_US` for the length of each timed cell: 10 microseconds in the 2026-11 pass, because the tree default `bench_common.CPU_DMA_LATENCY_DEFAULT_US` (0, no sleep state deeper than polling) kept every core in a busy-wait loop and made the host hot and slow (PROTOCOL.md section 7 has the A/B); it needs write access to the device on the host, and a hold that cannot be taken never fails the cell: rows stamp `cpu_dma_latency_us`, `cpu_dma_latency_held`, and `cpu_dma_latency_error` when it failed. `BENCH_SPARSE_WARMUP=N` and `BENCH_CPU_DMA_LATENCY_US=N` set the count and the target (PROTOCOL.md section 7); neither can be turned off. `override: sparse_warmup`, `override: cpu_dma_latency`; `test_idle_and_warmup.py`, `test_instrument_method.py` | part of the instrument |
| 82 | The served ArcadeDB headline is the vendor's own `arcadedb-driver` 0.2.0 (sync, httpx; `lean_http.OfficialSession`, stamp `arcadedb-driver 0.2.0 (sync, httpx)` with `arcadedb_http_client_role` = `headline`), and the lean HTTP client (`lean_http.LeanSession`) is the labelled sensitivity row | every ArcadeDB SERVED arm that talks HTTP through `lean_http.Session()`; no comparator client moves | **built (humemai/arcadedb-embedded-python#282, the instrument's client row).** The sensitivity row is the same cell run again as a twin job (`runner.ARCADEDB_HTTP_ARMS`, run_id ending `_clientlean`, `arcadedb_http_client_role` = `sensitivity`; the runner sets `BENCH_ARCADEDB_HTTP_CLIENT=lean` for it). `lean` is the client the 26.10.1 pass and the published October rows used, so the sensitivity row stays comparable with them; rows measured with the two clients are never mixed in one column. The driver carries `/query` and `/command` calls; the `GET /server` probe, the `/batch` bulk load, transactions, NDJSON streams and bodies with a field the driver has no argument for stay on the lean client. The PostgreSQL wire has no adapter in this harness, so its sensitivity row is not built. The `client` image gains `arcadedb-driver==0.2.0` at its next rebuild (`build_images.sh`, COMPARATORS.md pin table). Measured on the official 26.10.1 image (d36b4ca3a), 7 interleaved rounds: the bound Cypher point read costs the client 55.5 us of CPU per call with `lean` against 11.6 for a bare-socket variant that was tried and retired, identical answer digests; the 100-row read is engine-bound and moves less | part of the instrument |
| 82 | The served ArcadeDB headline is the benchmark's own minimal HTTP client (`lean_http.LeanSession`, stamp `lean_http (http.client, keep-alive)`); the page and the paper name it and say that the other engines are measured through their vendors' own Python clients | every ArcadeDB SERVED arm that talks HTTP through `lean_http.Session()`; no comparator client moves | **built (humemai/arcadedb-embedded-python#282, the instrument's client row; the headline selection is DECISIONS #268 and #285).** Each served cell runs as a second job on this client (`runner.ARCADEDB_HTTP_ARMS`, run_id ending `_clientlean`, `arcadedb_http_client_role` = `sensitivity` as stamped; the runner sets `BENCH_ARCADEDB_HTTP_CLIENT=lean` for it). `make_paper_tables.load_canonical` keeps the rows of this client and sets the other client's rows aside before any dedupe, table, gate or claim, so `runs_paper.csv`, the paper tables and the page hold these rows only; `export_web.py` refuses a frozen row or an overlay file that names another client, and `page_check.py` fails a page that names the vendor's driver. An arm with no job on this client (`arcadedb_imgdefaults_server`, and the PQ server arm) has no published cell; the docs transaction table says so for the first. This is the client the 26.10.1 pass and the published October rows used, so those rows stay comparable; rows measured with two clients are never mixed in one column. The `/query` and `/command` calls, the `GET /server` probe, the `/batch` bulk load, transactions and NDJSON streams all go through this client in these jobs. The PostgreSQL wire has no adapter in this harness. Measured on the official 26.10.1 image (d36b4ca3a), 7 interleaved rounds: the bound Cypher point read costs the client 55.5 us of CPU per call with `lean` against 11.6 for a bare-socket variant that was tried and retired, identical answer digests; the 100-row read is engine-bound and moves less | part of the instrument |
| 84 | The dense lane's id index for the delete (humemai/arcadedb-embedded-python#291, DECISIONS #178 index parity): ArcadeDB, pgvector, Neo4j, Memgraph, FalkorDB, DuckDB, and LanceDB get an index on the vector id before or right after the load, the other engines already delete through their own key | the dense lane (l3d), every arm | **built.** Every dense row stamps `dense_id_index` (the statement, or `key`); `override: dense_id_index`; `test_dense_id_index.py`. The index build is inside `ingest_s`. The /next page says ArcadeDB's delete ran without an id index in rows that lack the stamp (`_dense_id_index_note`, list line `dense_id_index`; `test_next_measurement_wording.py` holds the wording) | part of the instrument |
| 85 | Streamed results for the served ArcadeDB time-series arms, `BENCH_ARCADEDB_TS_NDJSON=1`, default OFF: both served arms ask the query endpoint for NDJSON and read the records line by line, as the PostgreSQL and MongoDB arms read rows as their server sends them | the time-series lane (l4), `arcadedb_ts_doc_server` and `arcadedb_ts_native_server` only | **mechanism written, default OFF; MEASURED 2026-10-09 and NOT USED at 26.11.1:** at ts100 the switch helped the documents arm (0.853 [0.713, 0.928]) and hurt the native arm (1.087 [1.083, 1.088]), identical rows, so it stays off and the page promises nothing; it needs a reader that parses as data arrives and a ts1000 re-measure first. Unset, nothing differs (`test_ts_ndjson.py`); set, rows stamp `arcadedb_ts_result_format` = `ndjson`; `override: ts_ndjson` | not an instrument change: unset, nothing differs |
| 87 | Two failures of the 26.10.1 pass that were not results (humemai/arcadedb-embedded-python#344, the failure triage of 2026-10-20): (1) `chroma_dense` never ran, because the override registry `overrides.py` shadowed chromadb's dependency `overrides` on `/work` (`ImportError: cannot import name 'overrides'`); the registry is now `override_registry.py`. (2) Memgraph's storage access timeout (default 1 s) refused the deep10m vector index build in both dense arms; the dense arms now run `--storage-access-timeout-sec=172800`, longer than any cell cap | Chroma dense (every scale) and Memgraph dense (both precisions); no other arm moves (the rename changes no measurement) | **built on branch issue/344-chroma-memgraph, not on main**: `override_registry.py` and every import, `runner.MEMGRAPH_STORAGE_ACCESS_TIMEOUT_S`, the read-back `memgraph_storage_access_timeout_s`, PROTOCOL.md section 7, COMPARATORS.md. Mini picks it up at the `git pull` of the stage after the merge, which is the user's to time; a repair stage reruns Chroma dense and Memgraph dense deep10m | `.notes/bench/repros/failure-triage-20261020` |
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/experiments/COMPARATORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Pins follow DECISIONS #87 (the latest self-hosted stable release at campaign tim
| Neo4j driver (Neo4j AND Memgraph arms) | `neo4j==6.4.1` | client package |
| Neo4j driver Rust extension (the vendor's documented accelerator, DECISIONS #173) | `neo4j-rust-ext==6.4.1.0` | client package |
| pgvector Python adapter (binary COPY, DECISIONS #174) | `pgvector==0.5.1` | client package |
| ArcadeDB official Python driver (sync, httpx; the served ArcadeDB arms' headline client, CAMPAIGN section 7 row 72) | `arcadedb-driver==0.2.0` | client package |
| ArcadeDB Python client package installed in the client image (measured by the harness, not a published client; the served ArcadeDB headline is the benchmark's own `lean_http.py`, CAMPAIGN section 7 row 82) | `arcadedb-driver==0.2.0` | client package |

**Held below the newest, and why.**

Expand Down
Loading
Loading