2026-09-11 AWS Benchmark Report (LeanStore synced)
2026091111 data with LeanStore cells re-measured under per-operation group-commit durability (sync-wait) and merged in. LeanStore Delete/1KB re-measured after a clone pre-sync fix (the first timed fdatasync had flushed the whole just-copied clone image inside the window); inmem read-ablation trim and headline error-bar passes retained.
Stacking Variants
各最適化の詳細は Design Document を参照。
- RocksDB: LSM-Tree のベースライン比較
- LMDB: B+Tree / mmap ベースの比較対象
- RocksDB-BlobDB: RocksDB の Blob 分離ストレージ変種(大きな Value 向け)
- LeanStore: B+Tree / pointer-swizzling ベースの比較対象 (64KB値は格納不可のため除外)
- Baseline: vmemkv 最適化なし
- +BF: + T1 Bloom Filter
- +Inline: +BF + T1 Inline Value + adaptive read policy (trifecta, production config)
- +PinRandom: +Inline のread policyをrandom-access mappingへピン留め (trifecta ablation)
- +PinSeq: +Inline のread policyをsequential mappingへピン留め (trifecta ablation)
Environment
AWS i4i.8xlarge (32 vCPU, local NVMe), spot instances, Ubuntu 24.04, Release -O3.
Workloads
- Insert: 順次挿入(1/4/16/32 スレッド)
- Get Hit/Miss (Zipf/Uniform): ポイントルックアップ
- Update / Delete: Zipf 分布での更新・削除
- Scan (Zipf/Uniform): レンジスキャン
- YCSB-E: 95% Scan + 5% Insert 混合(32スレッド / 30秒タイムライン)
Workload Winners & Relative Speedup
Best VMemKV variant vs. whichever rival (RocksDB, LMDB, RocksDB-BlobDB) is FASTEST at that cell, at 32 threads (max concurrency tested) -- not the best-of-any-thread-count-or-rival figure, since both axes are known to shrink (sometimes invert) the ratio if picked favorably. The rival actually being compared against is named in small text under each badge.
| Workload | 8B In-Memory | 1KB In-Memory | 1KB LTM | 64KB LTM |
|---|---|---|---|---|
| Insert |
✅ WIN (1.42x)
vmemkv (+Inline)
vs RocksDB-BlobDB
|
✅ WIN (1.44x)
vmemkv (+Inline)
vs RocksDB-BlobDB
|
✅ WIN (1.31x)
vmemkv (+Inline)
vs RocksDB
|
✅ WIN (2.00x)
vmemkv (Baseline)
vs RocksDB-BlobDB
|
| Update (Zipf) |
✅ WIN (1.49x)
vmemkv (Baseline)
vs RocksDB
|
✅ WIN (1.52x)
vmemkv (+BF)
vs RocksDB-BlobDB
|
✅ WIN (1.84x)
vmemkv (+Inline)
vs RocksDB
|
✅ WIN (2.52x)
vmemkv (+BF)
vs LMDB
|
| Delete |
✅ WIN (1.72x)
vmemkv (Baseline)
vs RocksDB-BlobDB
|
✅ WIN (1.78x)
vmemkv (Baseline)
vs RocksDB
|
✅ WIN (1.79x)
vmemkv (+PinSeq)
vs RocksDB
|
✅ WIN (3.88x)
vmemkv (+Inline)
vs RocksDB-BlobDB
|
| Get (Miss) |
✅ WIN (2.30x)
vmemkv (+BF)
vs RocksDB-BlobDB
|
✅ WIN (2.44x)
vmemkv (+BF)
vs LMDB
|
✅ WIN (2.37x)
vmemkv (+BF)
vs LMDB
|
✅ WIN (2.22x)
vmemkv (+BF)
vs LMDB
|
| Get (Hit, Zipf) |
✅ WIN (1.34x)
vmemkv (+Inline)
vs LMDB
|
✅ WIN (1.21x)
vmemkv (Baseline)
vs LMDB
|
❌ LOSE (0.67x)
vmemkv (+Inline)
vs RocksDB-BlobDB
|
✅ WIN (1.23x)
vmemkv (+Inline)
vs RocksDB
|
| Get (Hit, Uniform) |
WIN (1.06x)
vmemkv (+Inline)
vs LMDB
|
✅ WIN (1.18x)
vmemkv (Baseline)
vs LMDB
|
❌ LOSE (0.84x)
vmemkv (+Inline)
vs RocksDB-BlobDB
|
≈ EVEN (0.98x)
vmemkv (+BF)
vs RocksDB-BlobDB
|
| Scan (Zipf) |
LOSE (0.85x)
vmemkv (+Inline)
vs LMDB
|
≈ EVEN (1.03x)
vmemkv (Baseline)
vs LMDB
|
✅ WIN (1.21x)
vmemkv (Baseline)
vs RocksDB
|
LOSE (0.91x)
vmemkv (+BF)
vs LMDB
|
| Scan (Uniform) |
LOSE (0.89x)
vmemkv (+Inline)
vs LMDB
|
WIN (1.09x)
vmemkv (+Inline)
vs LMDB
|
✅ WIN (1.43x)
vmemkv (Baseline)
vs RocksDB
|
≈ EVEN (1.03x)
vmemkv (+PinSeq)
vs RocksDB-BlobDB
|
Background Jobs: reorganize() / checkpoint() / defragment()
Fixed reference point (1KB values, 10,000,000 records; in-memory unconstrained, LTM cgroup-constrained to the same memory budget as the rest of the suite) -- not swept across the CRUD matrix's 4 scenario/value-size combos. Duration is a single call in isolation; the three degradation columns are the percentage drop in concurrent Insert/Update/Scan QPS while that one call runs, measured over a matched-duration window on both sides (see run_background_jobs_probe.sh). reorganize() forces every shard through a synchronous merge in one call -- a manual escape hatch (pre-backup flush, capacity planning), not what happens during ordinary operation. The last rows summarize the organic per-shard split alternative that actually runs day to day (averaged across every split observed in that run; see the detail section further down for the full breakdown and charts).
| Job / Scenario | Duration (1 call) | Insert QPS degradation | Update QPS degradation | Scan QPS degradation |
|---|---|---|---|---|
| reorganize() (forced, all shards) / in-memory | 1.084s | 55% | -13% | 6% |
| reorganize() (forced, all shards) / LTM | 2.008s | 56% | -6% | 36% |
| checkpoint() / in-memory | 2.172s T1 merge 1323ms · WAL rotate 42ms · msync 590ms | 48% | -5% | 11% |
| checkpoint() / LTM | 3.053s T1 merge 3047ms · WAL rotate 0ms · msync 0ms | 53% | -33% | 33% |
| defragment() (forced, one cycle) / in-memory | 0.002s | 51% | 29% | 38% |
| defragment() (forced, one cycle) / LTM | 0.000s | 53% | 10% | 0% |
| per-shard split (organic) / in-memory | 211ms avg of 8 splits | 76% | n/a | n/a |
| per-shard split (organic) / LTM | 224ms avg of 4 splits | 87% | n/a | n/a |
Organic Per-Shard Splits
Writer-visible pause per automatic per-shard split during 90s sustained inserts.
Writer-visible pause duration
Insert Workload
Update (Zipf) Workload
Delete (Zipf) Workload
Get Miss (Zipf) Workload
Get Hit (Zipf) Workload
Get Hit (Uniform) Workload
Scan (Zipf) Workload
Scan (Uniform) Workload
YCSB-E — Scan + Insert 混合スループット(30秒タイムライン)
YCSB-E ワークロード: 95% Scan(100件レンジスキャン)+ 5% Insert を 32スレッドで 30秒間実行。
藍色の点線: 自然発生のT1 Reorganize(Adaptive Soft Limitによる自動トリガー、全バリアント共通)。
強制トリガーはバリアントごとに独立集計(全バリアント共通の1本の線には集約しない): t=5秒予定のreorganize()(細かい点線)、t=10秒・t=25秒予定のcheckpoint()(粗い点線)を、そのバリアント自身の色+マーカー形状(スキャンQPS線をホバーした際の点と同じ形。凡例のポイント形状も対応)で描画。
実際に発火する秒(線の位置)は予定秒とは限らない(将棋倒しに対するガード無し、書き込み負荷次第で数十秒遅延することがある)。8B In-Memoryのように挿入スループットが極端に高いワークロードでは、t=5秒予定のreorganize()自体が20秒以上かかり、後続のcheckpoint()トリガー(t=10s/25s)がこの30秒間に一度も発火しないまま終わることもある(この場合、線は1本しか出ない)。カーソルを線に合わせると、その秒に発火したバリアント・種類・予定秒・実発火秒・所要時間を表示。
Scan QPS タイムライン
32 threads / 30 secondsInsert Workload
Update (Zipf) Workload
Delete (Zipf) Workload
Get Miss (Zipf) Workload
Get Hit (Zipf) Workload
Get Hit (Uniform) Workload
Scan (Zipf) Workload
Scan (Uniform) Workload
YCSB-E — Scan + Insert 混合スループット(30秒タイムライン)
YCSB-E ワークロード: 95% Scan(100件レンジスキャン)+ 5% Insert を 32スレッドで 30秒間実行。
藍色の点線: 自然発生のT1 Reorganize(Adaptive Soft Limitによる自動トリガー、全バリアント共通)。
強制トリガーはバリアントごとに独立集計(全バリアント共通の1本の線には集約しない): t=5秒予定のreorganize()(細かい点線)、t=10秒・t=25秒予定のcheckpoint()(粗い点線)を、そのバリアント自身の色+マーカー形状(スキャンQPS線をホバーした際の点と同じ形。凡例のポイント形状も対応)で描画。
実際に発火する秒(線の位置)は予定秒とは限らない(将棋倒しに対するガード無し、書き込み負荷次第で数十秒遅延することがある)。8B In-Memoryのように挿入スループットが極端に高いワークロードでは、t=5秒予定のreorganize()自体が20秒以上かかり、後続のcheckpoint()トリガー(t=10s/25s)がこの30秒間に一度も発火しないまま終わることもある(この場合、線は1本しか出ない)。カーソルを線に合わせると、その秒に発火したバリアント・種類・予定秒・実発火秒・所要時間を表示。
Scan QPS タイムライン
32 threads / 30 secondsInsert Workload
Update (Zipf) Workload
Delete (Zipf) Workload
Get Miss (Zipf) Workload
Get Hit (Zipf) Workload
Get Hit (Uniform) Workload
Scan (Zipf) Workload
Scan (Uniform) Workload
YCSB-E — Scan + Insert 混合スループット(30秒タイムライン)
YCSB-E ワークロード: 95% Scan(100件レンジスキャン)+ 5% Insert を 32スレッドで 30秒間実行。
藍色の点線: 自然発生のT1 Reorganize(Adaptive Soft Limitによる自動トリガー、全バリアント共通)。
強制トリガーはバリアントごとに独立集計(全バリアント共通の1本の線には集約しない): t=5秒予定のreorganize()(細かい点線)、t=10秒・t=25秒予定のcheckpoint()(粗い点線)を、そのバリアント自身の色+マーカー形状(スキャンQPS線をホバーした際の点と同じ形。凡例のポイント形状も対応)で描画。
実際に発火する秒(線の位置)は予定秒とは限らない(将棋倒しに対するガード無し、書き込み負荷次第で数十秒遅延することがある)。8B In-Memoryのように挿入スループットが極端に高いワークロードでは、t=5秒予定のreorganize()自体が20秒以上かかり、後続のcheckpoint()トリガー(t=10s/25s)がこの30秒間に一度も発火しないまま終わることもある(この場合、線は1本しか出ない)。カーソルを線に合わせると、その秒に発火したバリアント・種類・予定秒・実発火秒・所要時間を表示。
Scan QPS タイムライン
32 threads / 30 secondsInsert Workload
Update (Zipf) Workload
Delete (Zipf) Workload
Get Miss (Zipf) Workload
Get Hit (Zipf) Workload
Get Hit (Uniform) Workload
Scan (Zipf) Workload
Scan (Uniform) Workload
YCSB-E — Scan + Insert 混合スループット(30秒タイムライン)
YCSB-E ワークロード: 95% Scan(100件レンジスキャン)+ 5% Insert を 32スレッドで 30秒間実行。
藍色の点線: 自然発生のT1 Reorganize(Adaptive Soft Limitによる自動トリガー、全バリアント共通)。
強制トリガーはバリアントごとに独立集計(全バリアント共通の1本の線には集約しない): t=5秒予定のreorganize()(細かい点線)、t=10秒・t=25秒予定のcheckpoint()(粗い点線)を、そのバリアント自身の色+マーカー形状(スキャンQPS線をホバーした際の点と同じ形。凡例のポイント形状も対応)で描画。
実際に発火する秒(線の位置)は予定秒とは限らない(将棋倒しに対するガード無し、書き込み負荷次第で数十秒遅延することがある)。8B In-Memoryのように挿入スループットが極端に高いワークロードでは、t=5秒予定のreorganize()自体が20秒以上かかり、後続のcheckpoint()トリガー(t=10s/25s)がこの30秒間に一度も発火しないまま終わることもある(この場合、線は1本しか出ない)。カーソルを線に合わせると、その秒に発火したバリアント・種類・予定秒・実発火秒・所要時間を表示。