C# と C++ : Memory Allocation (6)

ここでは標準のメモリアロケータのカスタマイズ性について考えてみます.
まず C++ では実装自由度が大きいかわりに,環境全体のメモリアロケータを実行時に置き換えるための共通の枠組みは基本的に存在しません.一般的にはコンパイル時にソースコードレベルでの対応を行います.

  • マクロ置換 (Visual C++ の DEBUG_NEW による new の置換など)
  • new operator のオーバーロード (GDI+ for C++)
  • Bridge パターンによるアロケータの差し替え

また C/C++ のライブラリはしばしばメモリ確保/解放処理を一元化するための独自の仕組みを持ちます.例えば ZIP ライブラリとして有名な zlib は,zalloc, zfree という関数ポインタがこの役目を果たしますし,C++ 版の GDI+ はクラスの new 演算子とデストラクタによって独自のメモリ管理を行っています.長い年月を経て,多くの C/C++ のライブラリがお互いに互換性を持たないメモリ管理スキームをそれぞれ発達させてしまっています.もしライブラリを 10 個持ち寄れば,あなたは 10 通りの異なるメモリ管理のシンタックスを使い分けることになるかもしれません.
一方 C# では,およそメモリの割付作業は全てダイレクトに CLR に丸投げされています.またメモリの回収処理も CLR が独自に行います.メモリ管理が CLR レベルで共通化されたことで,従来のようなメモリに関するライブラリごとの約束事といったものは不要になりました.例外は P/Invoke や COM 相互運用といった場面で,ここでは再び相手ごとに適切な方法で適切なメモリ管理を行う必要があります.

Customizing the Microsoft® .NET Framework Common Language Runtime (Pro Developer)

Customizing the Microsoft® .NET Framework Common Language Runtime (Pro Developer)


『Customizing the Microsoft.NET Framework Common Language Runtime』によれば,CLR 2.0 はいくつかの重要な基本動作をユーザコードで置き換えることを許しています.もっとも,さすがにマネージドヒープ上に個々のオブジェクトを配置するような部分に関しては介入の余地はないようです.以下の 3 つの interface によって,ユーザは自由に自分の実装を CLR に組み込み,マネージドヒープのサイズを決定したり GC タイミングに関する影響を与たりすることが可能です.またこれは,もし置き換えられるならば環境全体のメモリポリシーが変更されることを意味します.

  • IHostMemoryManager
    • IHostMemoryManager::VirtualAlloc
    • IHostMemoryManager::VirtualFree
    • IHostMemoryManager::VirtualQuery
    • IHostMemoryManager::VirtualProtect
    • IHostMemoryManager::CreateMalloc
    • IHostMemoryManager::GetMemoryLoad
    • IHostMemoryManager::RegisterMemoryNorificationCallback
    • IHostMemoryManager::NeedsVirtualAddressSpace
    • IHostMemoryManager::AcquiredVirtualAddressSpace
    • IHostMemoryManager::ReleasedVirtualAddressSpace
  • IHostMalloc
    • IHostMalloc::Alloc
    • IHostMalloc::DebugAlloc
    • IHostMalloc::Free
  • IHostGCManager
    • IHostGCManager::SuspensionEnding
    • IHostGCManager::SuspensionStarting
    • IHostGCManager::ThreadIsBlockingForSuspension

(訂正:SetGCStartupLimits 等は ICLRGCManager のメソッドでした)

同書によれば,SQL Server 2005 はこれらの拡張性を利用してアンマネージドプロセスの占めるメモリだけでなく SQLCLR のメモリ使用量も考慮に入れた総メモリ使用量が設定値以下に納めることを実現しているそうです.