mcpField
C
custom-allocators

custom-allocators

github.com/mohitmishra786開発269371 回インストール18 週間前に更新
リポジトリ

custom-allocators について

メモリーアロケーターの設計や調整を行う開発者向けの実践スキルです。アロケーターの種類に加え、jemalloc、mimalloc、tcmalloc、C のプールや arena、Rust GlobalAlloc、断片化指標、ベンチマークを扱います。

主な機能

  1. 01アロケーターの種類と選択基準
  2. 02jemalloc、mimalloc、tcmalloc の調整
  3. 03C のプールと arena の例
  4. 04Rust GlobalAlloc のガイダンス
  5. 05断片化指標とベンチマーク

活用シーン

  1. 01サーバーワークロード向けのアロケーター調整
  2. 02リクエスト単位の arena や C プールの実装
  3. 03Rust のカスタムグローバルアロケーター作成
  4. 04断片化と割り当て性能の調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill custom-allocators

インストール後、Claude Code で/custom-allocatorsを入力して読み込まれたか確認します。

詳細

カスタムアロケーター

目的

メモリアロケーターの設計とチューニングについて、エージェント向けに解説します。プール/スラブ/アリーナ/バディの分類、jemalloc の内部実装と MALLOC_CONF、mimalloc の設計、tcmalloc のスレッドキャッシュ、C でのシンプルなプールアロケーターの実装、Rust の GlobalAlloc トレイト、断片化の指標、ベンチマークを扱います。

使用する場面

  • レイテンシーに敏感なワークロードや組み込みワークロードで malloc を置き換える場合
  • サーバーのヒープ動作に合わせて jemalloc/mimalloc をチューニングする場合
  • リクエスト単位やフレーム単位のライフタイムに合わせてアリーナ割り当てを実装する場合
  • no_std やパフォーマンスのために Rust のカスタムグローバルアロケーターを書く場合
  • ヒープの断片化(内部/外部)を診断する場合
  • アロケーターのスループットとレイテンシーをベンチマークする場合

ワークフロー

1. アロケーターの分類
Allocator types
├── Pool/fixed-size — O(1) alloc/free, fixed block sizes
├── Slab — kernel-style, cache-friendly size classes
├── Arena/bump — fast alloc, bulk free (reset arena)
├── Buddy — power-of-two blocks, low fragmentation for large allocs
└── General (malloc) — jemalloc, mimalloc, tcmalloc
2. C でのシンプルなプールアロケーター
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct pool_block {
    struct pool_block *next;
} pool_block_t;

typedef struct {
    void   *memory;
    size_t  block_size;
    size_t  num_blocks;
    pool_block_t *free_list;
} pool_t;

int pool_init(pool_t *p, size_t block_size, size_t num_blocks) {
    p->block_size = block_size < sizeof(pool_block_t) ?
        sizeof(pool_block_t) : block_size;
    p->num_blocks = num_blocks;
    p->memory = aligned_alloc(64, p->block_size * num_blocks);
    if (!p->memory) return -1;
    p->free_list = NULL;
    for (size_t i = 0; i < num_blocks; i++) {
        pool_block_t *blk = (pool_block_t *)((char *)p->memory + i * p->block_size);
        blk->next = p->free_list;
        p->free_list = blk;
    }
    return 0;
}

void *pool_alloc(pool_t *p) {
    if (!p->free_list) return NULL;
    pool_block_t *blk = p->free_list;
    p->free_list = blk->next;
    return blk;
}

void pool_free(pool_t *p, void *ptr) {
    pool_block_t *blk = (pool_block_t *)ptr;
    blk->next = p->free_list;
    p->free_list = blk;
}
3. アリーナアロケーター
typedef struct {
    char  *base;
    size_t capacity;
    size_t offset;
} arena_t;

void *arena_alloc(arena_t *a, size_t size, size_t align) {
    uintptr_t cur = (uintptr_t)(a->base + a->offset);
    uintptr_t aligned = (cur + align - 1) & ~(align - 1);
    size_t padding = aligned - cur;
    if (a->offset + padding + size > a->capacity)
        return NULL;
    a->offset += padding + size;
    return (void *)aligned;
}

void arena_reset(arena_t *a) { a->offset = 0; }

サーバーではリクエストごとにアリーナを使用します。レスポンスの後にリセットすれば、オブジェクトごとに解放する必要はありません。

4. jemalloc のチューニング
# Use jemalloc as system allocator
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 ./myapp

# Runtime tuning
export MALLOC_CONF="background_thread:true,dirty_decay_ms:1000,muzzy_decay_ms:1000"

# Profiling build
# ./configure --enable-prof
export MALLOC_CONF="prof:true,prof_active:true,lg_prof_sample:19"

jemalloc の概念:

  • サイズクラス — 割り当てサイズを丸めた値
  • tcache — 使用頻度の高いサイズ向けのスレッドごとのキャッシュ
  • アリーナ — スレッド間の競合を軽減
# Statistics
export MALLOC_CONF="stats_print:true"
# prints on exit, or:
mallctl("epoch", ...); mallctl("stats.allocated", ...);
5. mimalloc
# Use mimalloc
LD_PRELOAD=/usr/lib/libmimalloc.so ./myapp

# Environment options
export MIMALLOC_SHOW_STATS=1
export MIMALLOC_PAGE_RESET=1

mimalloc の階層:セグメント → ページ → ブロック。一般に、jemalloc よりメタデータのオーバーヘッドが小さくなります。

# Statistics at exit
MIMALLOC_SHOW_STATS=1 ./myapp
6. tcmalloc のスレッドキャッシュ
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libtcmalloc.so.4 ./myapp

# Environment
export TCMALLOC_SAMPLE_PARAMETER=524288  # sampling profiler

小さなオブジェクトにはスレッドごとのキャッシュを使用し、大きな割り当てには中央ヒープを使用します。

7. Rust の GlobalAlloc
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicUsize, Ordering};

struct TrackingAllocator;

static ALLOCATED: AtomicUsize = AtomicUsize::new(0);

unsafe impl GlobalAlloc for TrackingAllocator {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        let ptr = System.alloc(layout);
        if !ptr.is_null() {
            ALLOCATED.fetch_add(layout.size(), Ordering::Relaxed);
        }
        ptr
    }
    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        System.dealloc(ptr, layout);
        ALLOCATED.fetch_sub(layout.size(), Ordering::Relaxed);
    }
}

#[global_allocator]
static GLOBAL: TrackingAllocator = TrackingAllocator;

alloc クレートを使う #![no_std] では、System を使わずに GlobalAlloc を実装します。

8. 断片化の指標
種類定義検出方法
内部割り当てブロックが要求サイズより大きいアロケーターの統計情報、サイズクラスによる丸め
外部空きメモリが要求に利用できないmallinfo/malloc_info、RSS とヒープの比較
# glibc malloc_info
malloc_info(0, stdout);

# jemalloc
jeprof --show_bytes ./myapp jeprof.heap
9. ベンチマーク
# mimalloc bench (if built from source)
cd mimalloc && mkdir build && cd build
cmake .. && make
./mimalloc-bench

# Custom microbenchmark pattern
perf stat -e cycles,instructions ./allocator_bench --threads 8 --size 64

比較項目:シングルスレッドでの割り当て/解放、マルチスレッドでの競合、サイズが混在する分布。

よくある問題

症状原因対処方法
プールの割り当てが NULL を返す空きリストが枯渇しているプールサイズを増やす。メモリーリークを確認する
jemalloc の RSS が下がらないダーティーページの解放が遅いdirty_decay_ms を下げる。madvise を使う
アリーナで OOM が発生するフェーズ間でリセットしていないarena_reset を使うか、アリーナを連結する
Rust アロケーターの動作が未定義になるdealloc で誤った Layout を指定している割り当て時にサイズ/アラインメントを保存する
mimalloc でパフォーマンスが低下するワークロードとの適合性が低いベンチマークを実施する。jemalloc を試す
外部断片化が大きいサイズが混在した割り当てが長期間存続するライフタイムごとに分ける。プールを使う

関連スキル

  • skills/allocators/numa-programming — NUMA を考慮した割り当て
  • skills/rust/rust-no-std — 組み込み Rust でのカスタムアロケーター
  • skills/profilers/heaptrack — 割り当てのホットスポットをプロファイリング
  • skills/profilers/valgrind — ヒープのメモリーリーク検出
  • skills/low-level-programming/cpu-cache-opt — アロケーターのアラインメントとフォルスシェアリング
  • skills/kernel/kernel-internals — SLUB/バディ方式のカーネルアロケーター

コメント