🌊

# 「T=16で負ける」から「mimallocに並ぶ」まで:hz3 Lane16 の一日

に公開

TL;DR

  • T=16 / R=90 で mimalloc に負ける → Remote最適化へ
  • Lane16 PageRemoteで改善は出たが T=2でハング
  • 原因は CAS 失敗時に tail->next を上書きして循環リスト化
  • 修正後、T=16 / R=90 で +9.6%、mimalloc と互角〜優位に
  • さらに 3.5x退行の犯人が hot path の atomic と判明

———

1. 問題の発端

T=16 になると hz3 が mimalloc に負ける。

T=8では勝つ → T=16で負ける
→ L1キャッシュ競合・命令数増加が怪しい

結果:

  • 命令数差 + キャッシュミス増
  • hot path ではなく remote/owner stash が主戦場

———

2. Lane16(PageRemote)の導入

mimalloc の勝ち筋(page-local, delayed collect)を
hz3 でも“別レーン”として実装。

  • hot path は維持
  • boundary は 2箇所だけ
  • HZ3_LANE_T16_R90_PAGE_REMOTE で opt-in

———

3. T=2でハング発生

原因: CAS 失敗時に tail->next を毎回上書き → リストが壊れる

修正前(バグ)

do {
hz3_obj_set_next(tail, old_head); // 毎回上書き
} while (!CAS(...));

修正後

void* old_head = atomic_load(...);
for (;;) {
hz3_obj_set_next(tail, old_head);
if (CAS_strong(...)) break;
}

→ T>1のハングが解消

———

4. 性能改善(A/B)

T=16 / R=90 / RUNS=5

Baseline: 69.5M
Lane16: 76.1M
改善: +9.6%

さらに warmup + taskset で再計測すると
mimallocと互角〜+5〜7%優位まで到達。

———

5. “別の大問題”が判明

論文時点(e165faccc)は hz3 234M
HEADでは 65M(3.5x退行)

原因は hot path の atomic_fetch_add:

static _Atomic uint32_t g_hz3_malloc_first = 0;
if (atomic_fetch_add_explicit(&g_hz3_malloc_first, 1, ...) == 0) { ... }

→ 毎回 atomic RMW が発生していた

対処

  • HZ3_MALLOC_FIRST_LOG を導入(デフォルト OFF)
  • hot path から atomic を除去

———

Discussion