Visitar URL original
paper-icde: ICDE 2027 workspace — IEEEtran skeleton, restored design docs, harness shell by tae898 · Pull Request #5 · humemai/arcadedb-embedded-python · GitHub
Skip to content

paper-icde: ICDE 2027 workspace — IEEEtran skeleton, restored design docs, harness shell - #5

Closed
tae898 wants to merge 73 commits into
mainfrom
icde-2027
Closed

tae898 wants to merge 73 commits into
mainfrom
icde-2027

Conversation

@tae898

@tae898 tae898 commented Jul 19, 2026

Copy link
Copy Markdown

Skeleton PDF builds (latexmk); section stubs follow the audited thesis
(multi-model unification; claims-discipline hedges baked into the TODOs);
references.bib seeded; sparse-vector design docs restored verbatim from
40bc98c as source material.

tae898 and others added 30 commits July 6, 2026 12:32
…docs, harness shell

Skeleton PDF builds (latexmk); section stubs follow the audited thesis
(multi-model unification; claims-discipline hedges baked into the TODOs);
references.bib seeded; sparse-vector design docs restored verbatim from
40bc98c as source material.
…config per engine, GAV as reported one-time cost
runner.py: embedded + client-server topologies (shared cpuset, 75/25 memory
split, dual cgroup samplers with summed accounting), per-cell scale-tiered
watchdog, labeled containers + startup orphan sweep, shuffled cells,
digest-pinned manifests, --backends/--timeout knobs. l1_tabular.py: OLTP +
OLAP suites over a seeded synthetic schema for arcadedb (embedded + HTTP),
duckdb, postgres — idiomatic ingest per engine (COPY, df-insert, sqlscript
batches). Smoke campaign fixed: sqlscript for multi-statement batches,
:p0 named params on the HTTP API, ArcadeDB's required INSERT column list,
per-row command() ingest anti-pattern (3.5h -> 2.9s cell).

Smoke is laptop plumbing-validation only; results stay untracked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ecall@10

- sparse_common.py: SPLADE-shaped generator (faithful port of the engine's
  LSMSparseVectorIndexLargeBenchmark distribution), deterministic per scale
- gen_sparse_gt.py: chunked exact top-K ground truth (scipy CSR)
- l3_sparse.py: adapters for ArcadeDB LSM_SPARSE_VECTOR (embedded + server),
  Qdrant sparse, Milvus sparse (standalone/embedded etcd), Elasticsearch
  sparse_vector; timed build + settle, warm search percentiles, recall@10
- runner.py: l3s lane, micro scale tier, server_cmd/server_volumes support,
  Milvus DEPLOY_MODE=STANDALONE fix
- results: micro/tiny/small smoke rows (laptop, single-rep, non-paper tier)
Fairness parity with ES forcemerge / Milvus flush+load / Qdrant green-wait
(PROTOCOL config policy, override class 2). Measured at 1M: ~2s cost, query
p50 9.5ms -> 7.0ms, recall unchanged (control run showed no warming effect).
Server adapter deliberately no-op: no compaction trigger reachable over
HTTP/SQL — documented asymmetry, lessons-learned material.

The suspected post-compaction hang was NOT an engine bug: attached-container
stdout backpressure in the debug harness (detached reruns: 0/2 hangs, both
benches complete). No upstream issue warranted.
Primitive-array set() + batched commits, the embedded analog of Qdrant/
Milvus binary clients (measured race at 100k: 20.0k vs 11.2k docs/s; both
paths verified identical by count + query). Server adapter keeps
SQL-over-HTTP — that is its native remote surface. 1M validation:
build 87s -> 53s, query metrics unchanged (p50 6.9ms, recall 0.9902).
5/5 cells green, serial, cpuset 0-11, 32g/cell, exact GT recall@10.
Qdrant p50 5.1ms / Milvus 7.4 / ES 12.2 / ArcadeDB-emb 55.6 / ArcadeDB-srv
102.5; recall 1.0/1.0/0.999/0.993/0.994. ArcadeDB embedded reproduces the
engine design doc's own 10M figure (~55ms/query, the 766x-vs-brute basis)
under controlled conditions. Also micro smoke rows from mini (5/5).
…airness bug)

arcadedata/arcadedb defaults to -Xmx2G; embedded got the per-scale heap
(16g at medium) — protocol violation (same JVM-heap policy per tier) that
inflated the server-vs-embedded gap at 10M (102.5ms vs 55.6ms p50) and
explains the peak-memory asymmetry (8.5 vs 18.7 GB summed). server_env now
supports {heap} templating; both ArcadeDB server backends (l1, l3s) get
-Xms/-Xmx at the scale heap. JAVA_OPTS override also means both deployments
run default G1 (image default is ZGC) — deployment axis isolates transport,
not GC. Affected rows to re-measure: l1 arcadedb_server, l3s
arcadedb_sparse_server (all scales).
p50 102.5 -> 86.9ms, build 1506 -> 973s, summed peak 8.5 -> 23.4GB
(server JVM now actually uses the per-scale 16g heap). Supersedes the
heap-starved row from run 20260707T100122Z. Remaining embedded-vs-server
delta (55.6 vs 86.9ms, 1.56x) is genuine transport/marshaling cost — the
clean E4 deployment-axis number.
…ty matrix in PROTOCOL

Embedded adapters (l1, l3s) now pass -Xms{heap} alongside heap_size so both
deployments run identical fixed heaps; rows record heap + mem_cap for
traceability; PROTOCOL gains the full embedded-vs-server parity matrix
(heap/GC/JDK/caps/DDL/ingest/settle) so the E4 axis provably isolates
transport.
…r final

p50 55.58ms (55.63 before pinning: stable), build 583s, peak 24.5GB
(-Xms pre-commit accounting). Deployment axis at 10M, full parity:
embedded 55.6ms vs server 86.9ms p50 = 1.56x transport cost. p99 tail
(~198ms) persists across measurements — characterize under N=5 reps.
…t shards

--tier sweep --workers N: worker threads own contiguous shards (0-5/6-11 at
N=2), pull from the shuffled queue under hard same-backend exclusion (two
cells of one backend can never co-run). RAM guard refuses workers x mem_cap
> 85% host RAM (medium+ stays serial by arithmetic). Paper tier rejects
workers>1 outright. Manifests record workers+shards; rows record their
shard. Verified live at micro: 5 cells interleaved across 2 shards, 5/5 ok.
… suites

graph_common.py: deterministic LDBC-flavored social graph (Person+KNOWS,
Pareto out-degree ~20, 100 cities), portable WHERE-form cypher; distinct
from cypherglot's corpus. l2_graph.py adapters on native bulk paths:
ArcadeDB embedded (Java vertex/edge API), ArcadeDB server (sqlscript/HTTP),
Neo4j 5 (UNWIND over bolt, awaitIndexes, heap-parity env), LadybugDB
real_ladybug 0.15.3 (CSV COPY, embedded). ArcadeDB OLAP runs against a
Graph Analytical View (READY-waited, counted in build). Tiny shapes are
workload-shaped as expected: ladybug wins OLAP, arcadedb-embedded wins
OLTP reads, neo4j pays bolt RTT.
…/medium x 5 backends x 5 reps)

10M mean±std: qdrant p50 5.10±0.20ms / milvus 7.13±0.57 / ES 11.92±0.26 /
arcadedb-emb 60.54±8.23 / arcadedb-srv 87.57±1.88; recall rock-stable
(arcadedb 0.9930±0.0000, ES 0.9984±0.0005). Embedded p99 = 120.7±103.5ms —
the intermittent tail is real and embedded-only (server p99 118.7±4.1
stable); investigate before paper runs. PRELIMINARY tier: dev0 wheel +
:latest images; definitive re-campaign after 26.7.2 pin freeze.
…l/medium)

Medium (1M persons, ~20M edges), N=5: OLTP reads — arcadedb-emb dominates
(point 0.45ms, hop1 0.58, hop2 1.05; RID adjacency), ladybug point 0.15 but
hop2 5.2, neo4j ~5ms floor (bolt RTT). OLAP — ladybug columnar wins big
(58/282/272ms), arcadedb GAV mid (1.0/10.7/11.2s, beats neo4j 2-13x),
neo4j slowest (13.9/22.1/22.4s). Workload-shaped wins as framed.
RED FLAG: arcadedb cypher WRITE p50 371ms emb / 424ms srv vs ladybug 10.6 /
neo4j 8.9 — 40x; suspect opencypher MATCH-in-write not using the unique
index (point reads do). Investigate before paper runs.
Dedup: latest manifest wins per (lane,backend,workload,scale,rep), so
re-measurements supersede without deleting history; paper-tier error-free
rows only. Emits results/summary/<lane>_<workload>_<scale>.md with metric
columns per lane and manifest traceability per row.
…ct retry

The postgres image logs 'ready to accept connections' twice (initdb's
temporary server, then the real one); the regex matched the first, racing
the restart window — 2-3 intermittent connection-refused cells in the L1
N=5 campaign. ready_regex now anchors on 'init process complete' before
the ready line ((?s) full-log match), and the adapter retries connect for
60s as a second layer. Verified live at tiny.
…eep)

plot_figures.py shares summarize.py's dedup (latest manifest wins,
paper-tier only); emits latex/figures/*.pdf. First figure: p50 vs corpus
size (100k/1M/10M), log-log, mean±std error bars over N=5, all 5 backends.
tae898 and others added 28 commits July 12, 2026 11:55
Adds bigann_sparse.py — streams the Big-ANN 2023 Sparse track (SPLADE-cocondenser
MS MARCO, exact top-10 MIPS GT) from the shipped CSR files: tiny=base_small(100k),
small=base_1M(1M), medium=base_full(8.84M), 30109-dim, ~127 nnz/doc, 6980 dev
queries. Same DIMENSIONS/K/SCALE_DOCS/gen_docs/gen_queries surface as
sparse_common, so all 7 sparse backends work unchanged. l3_sparse selects it via
BENCH_SPARSE_SOURCE=bigann (GT from the shipped .gt, not the synthetic gt.npy);
runner forwards BENCH_SPARSE_SOURCE/BENCH_SPARSE_DATA into the container.

Replaces the synthetic SPLADE-shaped corpus for recall claims (community-standard
dataset; reviewers expect it). Synthetic path retained as the default for
controlled scaling microbenchmarks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ounded cost)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rking; robust at N=5)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rial)

Single-threaded query cells have negligible core contention, so 3x-parallel
sweep numbers are valid; a later serial pass supersedes via latest-manifest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
7 backends: ArcadeDB LSM_VECTOR (embedded), Chroma, LanceDB, sqlite-vec,
DuckDB-VSS (new icde-bench:dense image), Qdrant + Milvus (server, same pinned
images as sparse). Matched operating point: HNSW M=16/efC=100/efS=100, L2, FP32.
Disclosed deviations: LanceDB IVF_HNSW_SQ (its only HNSW variant, int8 SQ);
sqlite-vec exact scan (recall-1.0 embedded baseline). Scales: small = full 1M
with shipped GT; micro/tiny recompute exact GT by chunked brute force.
Host prep: gen_dense_npy.py (HDF5 -> npy so containers need only numpy).
Embedded smoke at micro: recall 0.9994 (arcadedb), 0.9997 (chroma, duckdb),
1.0 (sqlite-vec), 0.876 (lancedb, SQ+nprobes as disclosed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…p smoke artifacts)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… SNAPSHOT digest)

arcadedb-embedded==26.8.1.dev1 (PyPI, includes 9e5d1db multi-page dim index
+ the ArcadeData#5215 GROUP BY auto-scale) and server image digest 122b4a8b (built
2026-07-12T22:44, post-fix). Unblocks FP32-medium and server-medium sparse
cells on Big-ANN (#72); passing int8 paths write identical segments per
upstream, so existing rows stay comparable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nse, post-fix digest)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…erived __version__

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ldbc_snb.py streams the persons+KNOWS projection of the official LDBC
SNB Interactive v1 pre-generated datasets (sf1/sf10); l2_graph.py grows a
BENCH_GRAPH_SOURCE=ldbc switch (same pattern as the Big-ANN sparse source):
generators rebound to scale-aware CSV streams, query ids sampled from the
real sparse id space, write ids based above max(id). Query templates and
tunables unchanged so synthetic-vs-LDBC differs only in data.
…V proper quoting

LDBC person names contain apostrophes; the server adapter's literal
CREATE VERTEX statements broke on them (embedded uses the Java API and
was immune, Neo4j parameterizes). Ladybug's COPY CSV now uses csv.writer
quoting for the same class of payload.
…ry share

Neo4j pins initial heap; 6g heap inside the 6g (75% of 8g) server cap
left no headroom and stalled startup past the ready timeout.
A mid-campaign 'git checkout -- experiments/' reverted the tracked
runs.jsonl and silently discarded rows appended by the live campaign
(recovered from the per-campaign CSV). Raw results are runtime state,
not source; manifests stay tracked.
executemany over Python lists took ~2h for SIFT1M and dominated the cell's
timeout; every other backend uses its native bulk path. Arrow FixedSizeList
-> FLOAT[dim] relational insert is DuckDB's; index build time now reflects
the engine, not the harness.
On cell timeout, capture the bench container's last progress lines into
timeout_phase_hint so every timeout row answers WHERE the budget expired
(ingest / index build / warmup / query iteration) — first line of the
four-part timeout audit (fired-on-first-execution, cost discrimination,
native-path self-conviction, determinism across reps) adopted from the
cypherglot methodology.
- run_id now includes scale: out-file names can no longer collide across
  campaigns (a stale same-name file resurfaced a prior campaign's metrics
  into a killed deep10m cell's row as a phantom 'ok')
- bench out file merged ONLY on rc==0, and pre-deleted before each cell
- deep10m heap 12g->16g (embedded 10M JVector build OOMed at 12g; 16g
  also fits the 18g server share)
…GB dataset; 25% of 24g OOM-killed the client at load)
@tae898

tae898 commented Jul 19, 2026

Copy link
Copy Markdown
Author

Closing — icde-2027 is a long-lived paper workspace branch, not intended to merge into main.

@tae898 tae898 closed this Jul 19, 2026
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.

1 participant