VMemKV クローンT2チェックポイントのスパースファイル対応(commit 4a7084c)により、これまで全ての4並列フルベンチ試行を失敗させていたディスク枯渇バグを修正。本ラウンドはその修正後、初めて4シナリオ全てが成功したフルラン。加えて、defragment()を単体スタンドアロンrunで新規に計測(commit 49d9a53)。さらに、checkpoint()関連の3つの重複した実験を、Insertスループットと直接比較する単一の実験(churn_ratio=0.25での定常状態スループット、commit a85250c/1a74065)へ統合し、4コンボ全てで計測完了。当初、8B/1KB In-MemoryおよびLTM/1KBではcheckpoint()がInsertの10〜30倍以上のスループットを維持し余裕で追いつく一方、LTM/64KBではcheckpoint()の定常状態スループット(約4,518 records/sec)がInsertのピーク速度(約11,832 records/sec、32スレッド)を下回り、書き込み側が生成するchurnにcheckpoint()が追いつかない可能性を示していた。原因調査の結果、mmap_t2_memory()が全T2リマップ時に無条件で行っていたMADV_POPULATE_READ(既存コーパス全体を毎回イーガーに温め直す)がLTM/64KBのボトルネックと判明し、これを除去(commit 8dc60f7)。LTM/64KBのcheckpoint()定常状態スループットは約4,518→約13,015 records/secに改善し、Insertのピーク速度を上回るようになった(他3コンボも同等以上を維持)。一方この副作用として、defragment()のPhase 0(T1キー順の全コーパス走査)が、直前のcheckpoint()側mmap_t2_memory()呼び出しによる無条件ページキャッシュ温め直しの恩恵を失い、in_memory/1KB(6.26s→53.23s、ratio=0.25)やLTM/64KB(36.43s→52.08s、ratio=0.25)で大幅に悪化した。defragment()自身の先頭にプリフェッチを配置する対策(単一スレッド版・8スレッド並列版の両方)を検証したが、いずれもプリフェッチなしの状態よりさらに悪化したため断念。checkpoint()の改善(本ラウンドの主目的)を優先し、defragment()側のこの退行は許容する方針とした。 さらに、checkpoint()のpre-stopコピーパス(まだwriterが動いている間の先行コピー)をディスクI/O帯域を活かすため8スレッド並列化(chunk分割 + 各ワーカーが自前のT2MemoryHandleを保持)。capture_watermarkはインクリメンタルではなくバッチの最高オフセットまで一括前倒しに変更(正しさは維持——out-of-place化がより早めに発火するだけ)。post-stopパス(writer停止後の小さな取りこぼし回収)は単一スレッドのまま。効果はディスク帯域律速だったLTM系で顕著:LTM/64KBは約13,015→約24,318 records/sec(約1.87倍、Insertピークの約2倍の余裕を確保)、LTM/1KBは約1,063,000→約1,586,918 records/sec(約1.49倍)。ディスクI/Oが支配的でないIn-Memory系はほぼ横ばい(想定通り)。4コンボ全てで退行なし。 さらに、defragment()をシーケンシャル書き換え方式に再実装(T2のbase領域はMAP_PRIVATEで、生存中に一度もdurabilizeされなかったレコードは物理的に一度も書かれないため、生バイトを順次パースするブラインドスキャンは原理的に成立しない——T1が今保証するオフセットのみをtry_read_base_record()で個別に読む方式に変更)。churn=0のコーパスサイズスイープ(4コンボ×25/50/75/100%、計16点)が全て完走するようになった(旧実装はin_memory/1KB・ltm/1KB・ltm/64KBの複数点でタイムアウト)。フルコーパスでの負荷率(r=defragmentスループット/Insert実効レート、小さいほど余裕): in_memory/8B r=0.019、in_memory/1KB r=0.136、ltm/1KB r=0.319(いずれも余裕あり)。ltm/64KBのみ r=1.69で単一スレッドではInsertに追いつかない(並列化が次の課題)。さらに、並行書き込み下でのcontentionチェックで新たな重大な課題が判明: defragment()自体がltm/1KB・ltm/64KBで60秒の内部タイムアウトに到達し(単独実行なら余裕を持って完走する同じフルコーパスにもかかわらず)、同時書き込みTPSもltm/1KBで-79%、ltm/64KBで-98%(ほぼ書き込みが止まる)と大きく低下した。バックプレッシャー機構は未設計のまま。 さらに、checkpoint()とreorganize()についても、defragment()と同じ形式のInsertスループット比較(サマリータブ表+各タブチャート)を追加。両方ともフルコーパスのデータは既存のスイープを再利用(checkpoint()は定常状態churn_ratio=0.25の別プローブ、defragment()・reorganize()はcorpus-size sweepのratio=100%地点)。結果: reorganize()(T1-only)はどのコンボでもInsertを大幅に上回る(数百万rec/sec)。加えて、3種の保守処理(checkpoint()・defragment()・reorganize())を横断した並行書き込みcontention比較表を新設。ltm/64KBでcheckpoint()も並行実行下では60秒タイムアウトに到達する(単独実行なら数秒で完了)ことが判明——並行TPS問題はdefragment()だけでなくcheckpoint()にも及ぶ。reorganize()は完了が1ミリ秒未満のため、contention計測はノイズが支配的である旨を表中に明記。

Stacking Variants

各最適化の詳細は Design Document を参照。

  • RocksDB: LSM-Tree のベースライン比較
  • LMDB: B+Tree / mmap ベースの比較対象
  • RocksDB-BlobDB: RocksDB の Blob 分離ストレージ変種(大きな Value 向け)
  • Baseline: vmemkv 最適化なし
  • +BF: + T1 Bloom Filter
  • +Inline: +BF + T1 Inline Value(<8B のValueをT1のみで処理)
  • +Prefault: +Inline + T2 Async Prefaulting(全部盛り、= VMemKVStore)。旧ScanBaseSequentialアブレーションは実測の結果撤去され、その最適化(base領域専用mmap経路)はGet/Scan双方の標準パスへ無条件で統合済み。

Environment

  • Instance: AWS i4i.8xlarge (ap-northeast-1) x4 (4並列独立インスタンス、run_4parallel_bench.sh フルラン) + 単体スタンドアロンインスタンス x2(defragment()計測用、checkpoint()スループット計測用、それぞれ--skip-matrix使用)
  • CPU: Intel Xeon Platinum 8375C @ 2.90GHz (32 cores)
  • RAM: 247.7 GiB
  • RAM (Larger-Than-Memory): cgroup で DRAM を制限し、target_ratio 相当のコーパスを構築後、cgroup内で計測(ストアごとに独立したcgroupスコープ + drop_caches)
  • Disk: Local NVMe SSD, ext4 (Swap Media for LTM。旧XFS+reflink依存は本ラウンドで撤去)
  • Kernel: 6.17.0-1019-aws
  • Git Rev: 4a7084c(メイン4並列)/49d9a53(defragment())/8dc60f7(checkpoint throughput + defragment、madvise fix適用後)

Workloads

  • Insert: 順次挿入(1/4/16/32 スレッド)
  • Get Hit/Miss (Zipf/Uniform): ポイントルックアップ
  • Update / Delete: Zipf 分布での更新・削除
  • Scan (Zipf/Uniform): レンジスキャン(旧レポートにあった reorganize モード分割は撤去済み)
  • YCSB-E: 95% Scan + 5% Insert 混合(32スレッド / 30秒タイムライン)

Overall Notes & Annotations

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.57x) vmemkv (+Inline) vs RocksDB-BlobDB
✅ WIN (1.58x) vmemkv (+BF) vs RocksDB-BlobDB
✅ WIN (1.52x) vmemkv (+Inline) vs RocksDB
✅ WIN (2.51x) vmemkv (+BF) vs RocksDB-BlobDB
Update (Zipf)
✅ WIN (1.44x) vmemkv (+Inline) vs RocksDB
✅ WIN (1.57x) vmemkv (+Inline) vs RocksDB-BlobDB
✅ WIN (2.16x) vmemkv (+Inline) vs RocksDB-BlobDB
✅ WIN (2.53x) vmemkv (Baseline) vs LMDB
Delete
✅ WIN (1.57x) vmemkv (+BF) vs RocksDB-BlobDB
✅ WIN (1.69x) vmemkv (+BF) vs RocksDB
✅ WIN (1.66x) vmemkv (+Inline) vs RocksDB
✅ WIN (3.53x) vmemkv (+BF) vs RocksDB-BlobDB
Get (Miss)
✅ WIN (2.70x) vmemkv (+BF) vs RocksDB-BlobDB
✅ WIN (2.88x) vmemkv (+BF) vs LMDB
✅ WIN (2.74x) vmemkv (+BF) vs LMDB
✅ WIN (3.15x) vmemkv (+Inline) vs RocksDB
Get (Hit, Zipf)
✅ WIN (1.42x) vmemkv (Baseline) vs LMDB
✅ WIN (1.24x) vmemkv (Baseline) vs LMDB
❌ LOSE (0.54x) vmemkv (+Inline) vs RocksDB-BlobDB
✅ WIN (1.26x) vmemkv (+Inline) vs RocksDB
Get (Hit, Uniform)
WIN (1.10x) vmemkv (Baseline) vs LMDB
✅ WIN (1.20x) vmemkv (Baseline) vs LMDB
❌ LOSE (0.85x) vmemkv (+Inline) vs RocksDB-BlobDB
≈ EVEN (0.99x) vmemkv (Baseline) vs RocksDB-BlobDB
Scan (Zipf)
❌ LOSE (0.82x) vmemkv (+Inline) vs LMDB
≈ EVEN (1.04x) vmemkv (+Inline) vs LMDB
WIN (1.12x) vmemkv (+BF) vs RocksDB
WIN (1.08x) vmemkv (+Inline) vs LMDB
Scan (Uniform)
❌ LOSE (0.83x) vmemkv (+Inline) vs LMDB
WIN (1.10x) vmemkv (+Inline) vs LMDB
✅ WIN (1.49x) vmemkv (+BF) vs RocksDB
≈ EVEN (0.97x) vmemkv (Baseline) vs RocksDB-BlobDB

Insert vs. Reorganize() Throughput

reorganize() (T1-only, never touches T2) rebuilds the whole T1 structure every call -- cost tracks corpus size, not churn, same character as defragment(). Full-corpus throughput (records/sec, the T1-only corpus-size sweep's own ratio=100% point) compared against the sustained Insert rate that grew that corpus. Same comparison also plotted per-tab. Isolated (no concurrent writers).

Scenario/Value Insert (32 threads) reorganize() full-corpus Verdict
8B_In-Memory141,478/s6,231,325/s✅ Keeps up (0.02x)
1KB_In-Memory112,199/s1,992,647/s✅ Keeps up (0.06x)
1KB_LTM108,825/s2,392,582/s✅ Keeps up (0.05x)
64KB_LTM11,832/s796,175/s✅ Keeps up (0.01x)

Insert vs. Defragment() Throughput

defragment() relocates the entire live corpus every cycle (cost tracks corpus size, not churn), so unlike checkpoint() there is no single churn-scoped "steady-state" number -- the operationally relevant question is whether a full-corpus cycle (records/sec, the corpus-size sweep's own ratio=100% point below) completes faster than the sustained Insert rate that grew that corpus. Same comparison also plotted per-tab (Insert's 1/4/16/32-thread line vs. a flat defragment() full-corpus throughput reference line). Isolated (no concurrent writers) -- see the Maintenance Operations contention table at the bottom of this tab for how much this degrades under concurrent load.

Scenario/Value Insert (32 threads) defragment() full-corpus Verdict
8B_In-Memory141,478/s6,452,154/s✅ Keeps up (0.02x)
1KB_In-Memory112,199/s365,030/s✅ Keeps up (0.31x)
1KB_LTM108,825/s154,560/s✅ Keeps up (0.70x)
64KB_LTM11,832/s4,784/s❌ Falls behind (2.47x)

Insert vs. Checkpoint() Throughput

checkpoint() only durabilizes the tail since the last cycle (cost tracks churn, not corpus size), so the operationally relevant question is whether its steady-state throughput (records/sec, measured at churn_ratio=0.25 to isolate the marginal per-record cost from checkpoint()'s fixed per-call setup overhead -- see run_checkpoint_throughput_probe.sh) can keep up with the sustained Insert rate generating that churn. Same comparison also plotted per-tab (Insert's 1/4/16/32-thread line vs. a flat checkpoint() throughput reference line).

Scenario/Value Insert (32 threads) checkpoint() steady-state Verdict
8B_In-Memory141,478/s4,659,170/s✅ Keeps up (0.03x)
1KB_In-Memory112,199/s2,765,162/s✅ Keeps up (0.04x)
1KB_LTM108,825/s1,586,843/s✅ Keeps up (0.07x)
64KB_LTM11,832/s24,318/s✅ Keeps up (0.49x)

Defragment Corpus-Size Scaling

defragment() duration against an already-checkpoint()ed corpus (a realistic pre-defragment state): a corpus-size sweep at churn_ratio=0 across all 4 scenario/value-size combos. defragment() relocates every live record regardless of which ones changed, so its cost tracks corpus size, not churn ratio -- confirmed once via a dedicated in_memory/1KB churn-ratio sweep (durations stayed flat across churn_ratio 0-1.0 at a fixed corpus size), not re-swept every round since that finding doesn't change from run to run. (Concurrent-write contention for defragment() is covered by the Maintenance Operations table at the bottom of this tab, alongside checkpoint() and reorganize().)

Corpus-Size Sweep (churn=0)

Scenario/ValueCorpus RatioCorpus (keys)defragment()
in_memory_1KB25%2,000,0005.60s
in_memory_1KB50%4,000,00012.33s
in_memory_1KB75%6,000,00016.70s
in_memory_1KB100%8,000,00021.92s
in_memory_8B25%5,000,0000.77s
in_memory_8B50%10,000,0001.51s
in_memory_8B75%15,000,0002.28s
in_memory_8B100%20,000,0003.10s
ltm_1KB25%2,064,8889.69s
ltm_1KB50%4,129,77621.84s
ltm_1KB75%6,194,66429.34s
ltm_1KB100%8,259,55253.44s
ltm_64KB25%32,7606.88s
ltm_64KB50%65,52016.18s
ltm_64KB75%98,28020.09s
ltm_64KB100%131,04027.39s

Maintenance Operations: Concurrent-Write Contention

All three maintenance operations (checkpoint(), defragment(), reorganize()) side by side: how much does write throughput degrade while each runs concurrently (32 writer threads, full corpus), and how long does the operation itself take under that contention versus in isolation (see the Insert-vs-throughput tables above for the isolated numbers alone). reorganize()'s own duration is often under a millisecond even at full corpus size (T1-only, in-memory) -- flagged inline where its concurrent-TPS figure is likely dominated by measurement noise rather than a real effect.

checkpoint()

Scenario/ValueIsolated Write TPSConcurrent Write TPSSlowdownOperation Duration
in_memory_8B100,738/s72,230/s28%5.02s
in_memory_1KB49,375/s19,027/s61%2.89s
ltm_1KB31,380/s6,417/s80%5.68s
ltm_64KB7,810/s3,806/s51%≥60s (timeout)

defragment()

Scenario/ValueIsolated Write TPSConcurrent Write TPSSlowdownOperation Duration
in_memory_8B119,679/s107,735/s10%4.13s
in_memory_1KB49,601/s17,683/s64%35.99s
ltm_1KB49,340/s10,557/s79%≥60s (timeout)
ltm_64KB8,097/s168/s98%≥60s (timeout)

reorganize()

Scenario/ValueIsolated Write TPSConcurrent Write TPSSlowdownOperation Duration
in_memory_8B123,954/s141,595/s-14%0.00s (single-call duration -- Isolated/Concurrent TPS above are averaged over many repeated calls spanning ≥1s, not this one call)
in_memory_1KB49,664/s34,078/s31%0.00s (single-call duration -- Isolated/Concurrent TPS above are averaged over many repeated calls spanning ≥1s, not this one call)
ltm_1KB49,666/s17,845/s64%0.00s (single-call duration -- Isolated/Concurrent TPS above are averaged over many repeated calls spanning ≥1s, not this one call)
ltm_64KB7,998/s6,717/s16%0.00s (single-call duration -- Isolated/Concurrent TPS above are averaged over many repeated calls spanning ≥1s, not this one call)

Insert Workload

実験概要: ユニークキーを空のストアに順次挿入する際の書き込みスループット。

Update (Zipf) Workload

実験概要: Zipf 分布での既存キーに対する更新スループット(ステートフルな上書き)。

Delete (Zipf) Workload

実験概要: T1 Tombstone 付与による並行削除スループット。

Get Miss (Zipf) Workload

実験概要: 存在しないキーへの読み取り。Bloom Filter の偽陽性回避効果を評価。

Get Hit (Zipf) Workload

実験概要: Zipf 分布(ホットキー偏重)での既存キーに対するポイントルックアップ。get_impl() の base_mmap 高速パス(本ラウンドの主要変更)が最も効くケース。

Get Hit (Uniform) Workload

実験概要: 一様分布での既存キーに対するポイントルックアップ。同上。

Scan (Zipf) Workload

実験概要: Zipf 分布で選ばれたレンジのスキャン。現行 bench_kv は reorganize 状態を単一の Scan ベンチマークとして測定する形に統合済み(旧レポートの Scan_WithReorg / Scan_T1T2Reorg モード分割は撤去済み)。

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 seconds

reorganize() Duration vs. Corpus Size (T1-only)

単発のreorganize()呼び出し1回の所要時間を、コーパスサイズ(件数)を横軸にスイープ計測。 reorganize() は T1(インメモリインデックス)のみを対象とし、T2には一切触れない。 ▲マーカーはタイムアウトを示す。

Reorganize Duration

single-shot, threads:1

Insert Throughput vs. Checkpoint() Steady-State Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。緑色破線 = checkpoint() の定常状態スループット(churn_ratio=0.25での記録数/所要時間。スレッド数に依存しない一定値なので水平線)。緑の線が藍色の線を下回る = 書き込み側が生成するchurnにcheckpoint()の処理速度が追いつかない可能性を示す。

Throughput Comparison

records/sec

Insert Throughput vs. Defragment() Full-Corpus Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。橙色破線 = defragment() のフルコーパススループット(コーパスサイズスイープの ratio=100% 地点。スレッド数に依存しない一定値なので水平線)。橙の線が藍色の線を下回る = 書き込み側の生成レートに defragment() の処理速度が追いつかない可能性を示す。単独実行(並行書き込みなし)での比較 —— 並行実行下での劣化は Defragment Scaling & Contention セクション参照。

Throughput Comparison

records/sec

Insert Throughput vs. Reorganize() Full-Corpus Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。紫色破線 = reorganize()(T1-only)のフルコーパススループット(T1-only コーパスサイズスイープの ratio=100% 地点。スレッド数に依存しない一定値なので水平線)。単独実行(並行書き込みなし)での比較。

Throughput Comparison

records/sec

Insert Workload

実験概要: ユニークキーを空のストアに順次挿入する際の書き込みスループット。

Update (Zipf) Workload

実験概要: Zipf 分布での既存キーに対する更新スループット(ステートフルな上書き)。

Delete (Zipf) Workload

実験概要: T1 Tombstone 付与による並行削除スループット。

Get Miss (Zipf) Workload

実験概要: 存在しないキーへの読み取り。Bloom Filter の偽陽性回避効果を評価。

Get Hit (Zipf) Workload

実験概要: Zipf 分布(ホットキー偏重)での既存キーに対するポイントルックアップ。get_impl() の base_mmap 高速パス(本ラウンドの主要変更)が最も効くケース。

Get Hit (Uniform) Workload

実験概要: 一様分布での既存キーに対するポイントルックアップ。同上。

Scan (Zipf) Workload

実験概要: Zipf 分布で選ばれたレンジのスキャン。現行 bench_kv は reorganize 状態を単一の Scan ベンチマークとして測定する形に統合済み(旧レポートの Scan_WithReorg / Scan_T1T2Reorg モード分割は撤去済み)。

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 seconds

reorganize() Duration vs. Corpus Size (T1-only)

単発のreorganize()呼び出し1回の所要時間を、コーパスサイズ(件数)を横軸にスイープ計測。 reorganize() は T1(インメモリインデックス)のみを対象とし、T2には一切触れない。 ▲マーカーはタイムアウトを示す。

Reorganize Duration

single-shot, threads:1

Insert Throughput vs. Checkpoint() Steady-State Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。緑色破線 = checkpoint() の定常状態スループット(churn_ratio=0.25での記録数/所要時間。スレッド数に依存しない一定値なので水平線)。緑の線が藍色の線を下回る = 書き込み側が生成するchurnにcheckpoint()の処理速度が追いつかない可能性を示す。

Throughput Comparison

records/sec

Insert Throughput vs. Defragment() Full-Corpus Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。橙色破線 = defragment() のフルコーパススループット(コーパスサイズスイープの ratio=100% 地点。スレッド数に依存しない一定値なので水平線)。橙の線が藍色の線を下回る = 書き込み側の生成レートに defragment() の処理速度が追いつかない可能性を示す。単独実行(並行書き込みなし)での比較 —— 並行実行下での劣化は Defragment Scaling & Contention セクション参照。

Throughput Comparison

records/sec

Insert Throughput vs. Reorganize() Full-Corpus Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。紫色破線 = reorganize()(T1-only)のフルコーパススループット(T1-only コーパスサイズスイープの ratio=100% 地点。スレッド数に依存しない一定値なので水平線)。単独実行(並行書き込みなし)での比較。

Throughput Comparison

records/sec

Insert Workload

実験概要: ユニークキーを空のストアに順次挿入する際の書き込みスループット。

Update (Zipf) Workload

実験概要: Zipf 分布での既存キーに対する更新スループット(ステートフルな上書き)。

Delete (Zipf) Workload

実験概要: T1 Tombstone 付与による並行削除スループット。

Get Miss (Zipf) Workload

実験概要: 存在しないキーへの読み取り。Bloom Filter の偽陽性回避効果を評価。

Get Hit (Zipf) Workload

実験概要: Zipf 分布(ホットキー偏重)での既存キーに対するポイントルックアップ。get_impl() の base_mmap 高速パス(本ラウンドの主要変更)が最も効くケース。

Get Hit (Uniform) Workload

実験概要: 一様分布での既存キーに対するポイントルックアップ。同上。

Scan (Zipf) Workload

実験概要: Zipf 分布で選ばれたレンジのスキャン。現行 bench_kv は reorganize 状態を単一の Scan ベンチマークとして測定する形に統合済み(旧レポートの Scan_WithReorg / Scan_T1T2Reorg モード分割は撤去済み)。

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 seconds

reorganize() Duration vs. Corpus Size (T1-only)

単発のreorganize()呼び出し1回の所要時間を、コーパスサイズ(件数)を横軸にスイープ計測。 reorganize() は T1(インメモリインデックス)のみを対象とし、T2には一切触れない。 ▲マーカーはタイムアウトを示す。

Reorganize Duration

single-shot, threads:1

Insert Throughput vs. Checkpoint() Steady-State Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。緑色破線 = checkpoint() の定常状態スループット(churn_ratio=0.25での記録数/所要時間。スレッド数に依存しない一定値なので水平線)。緑の線が藍色の線を下回る = 書き込み側が生成するchurnにcheckpoint()の処理速度が追いつかない可能性を示す。

Throughput Comparison

records/sec

Insert Throughput vs. Defragment() Full-Corpus Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。橙色破線 = defragment() のフルコーパススループット(コーパスサイズスイープの ratio=100% 地点。スレッド数に依存しない一定値なので水平線)。橙の線が藍色の線を下回る = 書き込み側の生成レートに defragment() の処理速度が追いつかない可能性を示す。単独実行(並行書き込みなし)での比較 —— 並行実行下での劣化は Defragment Scaling & Contention セクション参照。

Throughput Comparison

records/sec

Insert Throughput vs. Reorganize() Full-Corpus Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。紫色破線 = reorganize()(T1-only)のフルコーパススループット(T1-only コーパスサイズスイープの ratio=100% 地点。スレッド数に依存しない一定値なので水平線)。単独実行(並行書き込みなし)での比較。

Throughput Comparison

records/sec

Insert Workload

実験概要: ユニークキーを空のストアに順次挿入する際の書き込みスループット。

Update (Zipf) Workload

実験概要: Zipf 分布での既存キーに対する更新スループット(ステートフルな上書き)。

Delete (Zipf) Workload

実験概要: T1 Tombstone 付与による並行削除スループット。

Get Miss (Zipf) Workload

実験概要: 存在しないキーへの読み取り。Bloom Filter の偽陽性回避効果を評価。

Get Hit (Zipf) Workload

実験概要: Zipf 分布(ホットキー偏重)での既存キーに対するポイントルックアップ。get_impl() の base_mmap 高速パス(本ラウンドの主要変更)が最も効くケース。

Get Hit (Uniform) Workload

実験概要: 一様分布での既存キーに対するポイントルックアップ。同上。

Scan (Zipf) Workload

実験概要: Zipf 分布で選ばれたレンジのスキャン。現行 bench_kv は reorganize 状態を単一の Scan ベンチマークとして測定する形に統合済み(旧レポートの Scan_WithReorg / Scan_T1T2Reorg モード分割は撤去済み)。

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 seconds

reorganize() Duration vs. Corpus Size (T1-only)

単発のreorganize()呼び出し1回の所要時間を、コーパスサイズ(件数)を横軸にスイープ計測。 reorganize() は T1(インメモリインデックス)のみを対象とし、T2には一切触れない。 ▲マーカーはタイムアウトを示す。

Reorganize Duration

single-shot, threads:1

Insert Throughput vs. Checkpoint() Steady-State Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。緑色破線 = checkpoint() の定常状態スループット(churn_ratio=0.25での記録数/所要時間。スレッド数に依存しない一定値なので水平線)。緑の線が藍色の線を下回る = 書き込み側が生成するchurnにcheckpoint()の処理速度が追いつかない可能性を示す。

Throughput Comparison

records/sec

Insert Throughput vs. Defragment() Full-Corpus Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。橙色破線 = defragment() のフルコーパススループット(コーパスサイズスイープの ratio=100% 地点。スレッド数に依存しない一定値なので水平線)。橙の線が藍色の線を下回る = 書き込み側の生成レートに defragment() の処理速度が追いつかない可能性を示す。単独実行(並行書き込みなし)での比較 —— 並行実行下での劣化は Defragment Scaling & Contention セクション参照。

Throughput Comparison

records/sec

Insert Throughput vs. Reorganize() Full-Corpus Throughput

藍色 = Insert スループット(1/4/16/32スレッド)。紫色破線 = reorganize()(T1-only)のフルコーパススループット(T1-only コーパスサイズスイープの ratio=100% 地点。スレッド数に依存しない一定値なので水平線)。単独実行(並行書き込みなし)での比較。

Throughput Comparison

records/sec