← VevDB home
Documentation

Comparative benchmark snapshot — 2026-08-27#

Same-machine results from a 16 GB Apple M1 Pro MacBook Pro (10 cores), macOS 15.5. Vev revision: b0f2700d (Optimize small resident durable transactions). The benchmark processes used GraalVM JDK 25.0.1.

Raw measurements and process output are retained in:

  • 2026-08-27-comparative-queries.json
  • 2026-08-27-comparative-transactions.json
  • 2026-08-27-musicbrainz.json

Summary#

  • The incremental resident path removes the full-DB-size cost from small replacements and retractions. On the 2,000-entity fixture, replacement falls from 14.50 to 1.94 ms, explicit retract from 15.23 to 1.93 ms, and the Ro-like transaction from 15.51 to 2.81 ms.
  • On the 50-entity fixture, the Ro-like durable transaction has a 0.82 ms median and 2.46 ms p95. On 2,000 entities it has a 2.81 ms median and 7.05 ms p95. The requested 3–5 ms median target is met without changing the transaction shape or omitting provenance.
  • Vev remains faster than DataScript and Datomic on all seven synthetic queries. Datalevin wins the six join/predicate queries; Vev wins q1.
  • Vev wins all nine durable MusicBrainz queries against Datomic, by 1.52–4.51×, with matching row counts and fingerprints.
  • In small durable transactions, Vev's median beats Datalevin strict WAL and Datomic dev on append, replacement, explicit retract, and Ro-like. On the larger fixture Datalevin is faster, while Vev is near Datomic except for retractEntity.

Deterministic query comparison#

The fixture contains 20,000 entities and 100,000 user datoms. Attribute values use seed 42 and insertion order uses seed 43 for every engine. Each query has a 250 ms warmup and five independent 500 ms measurement windows. The table shows median/p95 milliseconds per completed query.

Current releases are DataScript 1.7.8, Datalevin 0.10.7, and Datomic Peer 1.0.7705.

Query Datomic DataScript Datalevin Vev
q1 1.570 / 1.635 0.348 / 0.353 0.336 / 0.558 0.230 / 0.380
q2 6.282 / 7.225 1.439 / 1.602 0.380 / 0.437 0.622 / 0.757
q2-switch 11.380 / 14.013 3.145 / 3.374 0.318 / 0.366 0.590 / 0.676
q3 3.943 / 4.324 2.223 / 2.402 0.174 / 0.198 0.550 / 0.589
q4 4.776 / 5.786 3.548 / 3.622 0.197 / 0.221 1.084 / 1.194
qpred1 6.418 / 8.629 4.355 / 4.799 1.516 / 1.581 2.010 / 2.071
qpred2 8.132 / 8.548 8.233 / 8.341 1.545 / 2.009 2.034 / 2.075

Vev is 1.51–5.33× faster than DataScript and 3.19–19.29× faster than Datomic on these shapes. Datalevin is 1.31–5.50× faster than Vev on the six wider queries; Vev is 1.46× faster on q1.

The historical dependency track reran DataScript 1.7.4, Datalevin 0.10.5, and Datomic 1.0.7277 with the same deterministic fixture. Its full table is in the raw JSON. Vev's two independent tracks differ by only 1.2% in geometric-mean latency, which is a useful stability check. Relative to the July snapshot, current Vev medians are within 5% on five shapes and about 10% faster on q3 and q4. Historical July numbers should not be compared directly to the new peer rows because the old harness did not seed insertion order and exposed only its median.

Small resident transactions#

Every timed call is synchronous through report return. Vev uses its resident SQLite connection and Datalevin uses strict synchronous WAL; both are durable. Datomic durable rows use Peer 1.0.7705 with the locally available dev transactor 1.0.7277. Each workload has five warmups and 40 measurements. The table shows median/p95 milliseconds.

Durable, 50 resident entities#

Workload Vev incremental Datalevin strict WAL Datomic dev
Append 0.543 / 1.859 1.295 / 1.945 3.444 / 3.934
Replacement 0.712 / 2.227 1.124 / 1.511 4.170 / 4.742
Explicit retract 0.662 / 3.937 1.119 / 1.484 3.711 / 4.328
retractEntity 1.445 / 2.998 1.056 / 1.583 2.811 / 3.096
Ro-like 0.821 / 2.458 1.092 / 1.436 2.629 / 3.128

Durable, 2,000 resident entities#

Workload Vev incremental Datalevin strict WAL Datomic dev
Append 1.439 / 4.381 1.083 / 1.875 2.627 / 3.838
Replacement 1.939 / 5.695 1.077 / 1.858 2.179 / 2.476
Explicit retract 1.926 / 5.937 0.674 / 0.965 2.127 / 2.554
retractEntity 15.657 / 18.322 0.815 / 0.992 2.037 / 2.424
Ro-like 2.809 / 7.045 0.673 / 0.827 2.923 / 4.130

DataScript and Datomic in-memory references are included in the JSON but not mixed into the durable ranking. For the Ro-like shape their small/large medians are 0.051/0.029 ms for DataScript and 0.165/0.076 ms for Datomic.

Vev and Datomic reports include the automatic transaction-instant datom, while DataScript and Datalevin reports do not. Consequently the effective report sizes for append/replacement/retract/retractEntity/Ro-like are 2/3/2/3/6 in Vev, 1/2/1/3/5 in DataScript and Datalevin, and 2/3/2/4/6 in Datomic. No provenance was removed or special-cased.

Incremental path and phase profile#

Forced full rebuild and incremental mode start every workload from the same database size. The median speedup is modest on the 50-entity fixture and large once rebuilding all resident datoms matters:

Workload 50 entities full → incremental Speedup 2,000 entities full → incremental Speedup
Append 0.593 → 0.543 ms 1.09× 1.555 → 1.439 ms 1.08×
Replacement 1.030 → 0.712 ms 1.45× 14.499 → 1.939 ms 7.48×
Explicit retract 1.061 → 0.662 ms 1.60× 15.233 → 1.926 ms 7.91×
retractEntity 1.828 → 1.445 ms 1.27× 29.117 → 15.657 ms 1.86×
Ro-like 1.356 → 0.821 ms 1.65× 15.505 → 2.809 ms 5.52×

The phase profile confirms the original root cause. On the large fixture, full construction of db-after consumes 14.10 ms for replacement, 14.98 ms for explicit retract, and 15.16 ms for Ro-like. Incremental construction reduces those phases to 0.60, 0.80, and 1.12 ms respectively.

For large incremental replacement, the remaining profiled time is 32% SQLite commit, 27% db-after, 21% planning, and 13% derived bookkeeping. For Ro-like it is 35% db-after, 28% commit, 20% planning, and 9% derived bookkeeping. The p95 spread is mostly in durable I/O and is materially wider than the median, especially for Vev.

Large retractEntity is now the clear outlier: 15.66 ms median, with resolution accounting for 85.7% of profiled time. Its entity-expansion scan is the next general optimization target; it is no longer a db-after rebuild problem.

Durable MusicBrainz queries#

This uses the Datomic 1968–1973 sample, five warmups, and seven measurements. Vev prepares each query once. Datomic Peer and transactor are both 1.0.7277 for this established fixture. All row counts and result fingerprints match.

Workload Datomic Vev Datomic / Vev
Title by artist 1.791 0.613 2.92×
Title, album, and year 4.536 2.542 1.78×
Pre-1970 title, album, and year 3.632 1.563 2.32×
Track release rule 4.035 1.848 2.18×
Track search information 7.329 4.123 1.78×
Collaboration 3.001 0.919 3.27×
Collaboration network depth 2 3.627 0.805 4.51×
Nested collaboration 2.968 1.512 1.96×
Bill Withers collaborations 1.807 1.186 1.52×

Architecture and consequences#

The result comes from the general small non-schema incremental path. It applies the transaction's effective datoms to immutable current/index snapshots and retains the canonical log for history/as-of. Schema-affecting and ineligible transactions continue through full construction. Durable publication still appends the canonical SQLite rows, updates derived root/novelty bookkeeping, and commits before returning the report.

This benchmark refresh changes no public API, transaction semantics, storage format, durability setting, or report ownership. Its code changes are confined to deterministic fixtures, comparison adapters, orchestration, and result artifacts. The current performance commit itself also requires no storage migration; reopen and separate-connection visibility continue to use the canonical log and committed generation.

Reproduction#

scripts/build_native_library.sh

DATALEVIN_BENCH=/path/to/datalevin/benchmarks/datascript-bench \
  bench/run_comparative_benchmarks.py --track both --runs 1

bench/run_transaction_comparison.py \
  --datomic-uri-prefix datomic:dev://localhost:4334/vev-resident-

DATOMIC_HOME=/path/to/datomic-pro-1.0.7277 \
  scripts/compare_musicbrainz_workshop.sh \
    --prepared-vev --warmup-runs 5 --measure-runs 7 --skip-kvist