kevy
このページ

kevy-alloc——オプトインのアロケータ:得られるもの、支払うもの

kevy はデフォルトでシステムアロケータ(glibc malloc)を使います。ビルド時に純 Rust の span アロケータ kevy-alloc をプロセス全体のアロケータとして組み込むこともできます:

cargo build --release -p kevy --features kevy-alloc

これはビルド時の選択です——アロケータはすべてのパスの下に敷かれるため、実行時の切り替えはありません。デフォルトビルドには含まれません。

得られるもの

ベンチ参照機(io_uring、8 shard)での実測。計測ハーネスとプロトコルは bench/REPORT.md を参照:

  • フラグメンテーション / RSS:長時間稼働の高チャーン負荷で、常駐メモリはライブデータの約 2.16 倍。glibc の 2.40 倍に対して定常状態のフットプリントが約 10% 小さく、アロケーションのチャーンが激しいほど差は広がります。
  • 容量の余裕:小さく予測しやすいフットプリントは、階層化の容量モデルが予算を立てる対象そのものです。容量が逼迫したデプロイでは、アロケータが「収まる」と「ページングが始まる」の分かれ目になります。
  • ディスク / 永続化 / 安定性:実測でコストゼロ——crash、レプリケーション、ディスクの各ゲートは両ビルドで同一の結果です。

支払うもの

飽和したコレクション書き込み角(ある shard の owner スレッドがパイプライン化された sadd/zadd/hset トラフィックで張り付いた状態)では、このアロケータの fast path は glibc の約 1.7 倍/呼び出しのコストがかかり、次のように現れます:

  • 飽和角で sadd 約 −10~−16%、zadd 約 −13% のスループット(hash 書き込みは例外——小さな hash 値は store 内にインライン格納され、−0.2% しか払いません)。
  • アロケーション密度の低い角(GET/SET/INCR/LPUSH、cluster、RESP 互換)は −2~−6%。飽和していないサーバでは通常、差は測定できません——アイドルの余裕が呼び出しごとのコストを吸収します。

いつ有効にするか

kevy-alloc を有効にすべき場面:

  • メモリ容量が支配的な制約で(キャッシュ機、階層化ウィンドウ、多テナント集約)、約 10% の RSS 削減が実際の余裕になるとき。
  • 読み取り中心か読み書き混合のワークロード——実測されたプロダクション形状(R4a コーパス)は読み取りと集計が支配的で、そこではアロケータは無料です。
  • 長時間稼働のプロセスで、午前 3 時に呼び出されるのはピークスループットではなくフラグメンテーションの増大だというとき。

デフォルトのままにすべき場面:

  • 持続的でパイプライン化された set/zset 書き込みスループットが最重要指標で、owner shard が飽和して稼働しているとき。
  • パフォーマンスベースラインが記録されたのと同じバイナリを使いたいとき。