Firefox 3には、新しいアロケーターjemalloc
が付属しました。
いくつかの場所で、この新しいアロケーターの方が優れていると聞きました。ただし、Googleの上位の結果では、これ以上の情報は提供されていません。どのように機能するのか興味があります。
jemalloc
は、1つの「Jason Evans」、つまり「je」の発案であるFreeBSDで初めて登場しました。私がかつてpaxos
というオペレーティングシステムを書いていなかったら、私は彼を利己的だとforします:-)
詳細については、 このPDF を参照してください。これは、アルゴリズムの仕組みを詳細に説明したホワイトペーパーです。
主な利点は、複数のアリーナ(割り当てが行われる生メモリのチャンク)を使用することで部分的に達成される、マルチプロセッサおよびマルチスレッドシステムのスケーラビリティです。
シングルスレッドの状況では、複数のアリーナに実際の利点はないため、単一のアリーナが使用されます。
ただし、マルチスレッドの状況では、多くのアリーナが作成され(プロセッサの4倍のアリーナ)、スレッドがラウンドロビン方式でこれらのアリーナに割り当てられます。
これは、複数のスレッドがmalloc
またはfree
を同時に呼び出すことができますが、同じアリーナを共有する場合にのみ競合するため、ロックの競合を減らすことができることを意味します。アリーナの異なる2つのスレッドは互いに影響しません。
さらに、jemalloc
は、キャッシュの局所性を最適化しようとします。これは、RAMからデータを取得する動作が、CPUキャッシュにすでにあるRAM対ディスクからの低速フェッチ)からの高速フェッチの違い。そのため、アプリケーションのワーキングセット全体がキャッシュ内にある可能性が高いため、最初に全体的なメモリ使用量の最小化を試みます。
そして、それが達成できない場合、一緒に割り当てられたメモリは一緒に使用される傾向があるため、割り当てが連続することを保証しようとします。
ホワイトペーパーから、これらの戦略は、シングルスレッド使用の現在の最適なアルゴリズムと同様のパフォーマンスを提供し、マルチスレッド使用の改善を提供するようです。
1つの興味深いソースがあります:Cソース自体: https://dxr.mozilla.org/mozilla-central/source/memory/build/mozjemalloc.cpp ( old =)
初めに、簡単な要約で、大まかに動作する方法を説明します。
// This allocator implementation is designed to provide scalable performance
// for multi-threaded programs on multi-processor systems. The following
// features are included for this purpose:
//
// + Multiple arenas are used if there are multiple CPUs, which reduces lock
// contention and cache sloshing.
//
// + Cache line sharing between arenas is avoided for internal data
// structures.
//
// + Memory is managed in chunks and runs (chunks can be split into runs),
// rather than as individual pages. This provides a constant-time
// mechanism for associating allocations with particular arenas.
//
// Allocation requests are rounded up to the nearest size class, and no record
// of the original request size is maintained. Allocations are broken into
// categories according to size class. Assuming runtime defaults, 4 kB pages
// and a 16 byte quantum on a 32-bit system, the size classes in each category
// are as follows:
//
// |=====================================|
// | Category | Subcategory | Size |
// |=====================================|
// | Small | Tiny | 4 |
// | | | 8 |
// | |----------------+---------|
// | | Quantum-spaced | 16 |
// | | | 32 |
// | | | 48 |
// | | | ... |
// | | | 480 |
// | | | 496 |
// | | | 512 |
// | |----------------+---------|
// | | Sub-page | 1 kB |
// | | | 2 kB |
// |=====================================|
// | Large | 4 kB |
// | | 8 kB |
// | | 12 kB |
// | | ... |
// | | 1012 kB |
// | | 1016 kB |
// | | 1020 kB |
// |=====================================|
// | Huge | 1 MB |
// | | 2 MB |
// | | 3 MB |
// | | ... |
// |=====================================|
//
// NOTE: Due to Mozilla bug 691003, we cannot reserve less than one Word for an
// allocation on Linux or Mac. So on 32-bit *nix, the smallest bucket size is
// 4 bytes, and on 64-bit, the smallest bucket size is 8 bytes.
//
// A different mechanism is used for each category:
//
// Small : Each size class is segregated into its own set of runs. Each run
// maintains a bitmap of which regions are free/allocated.
//
// Large : Each allocation is backed by a dedicated run. Metadata are stored
// in the associated arena chunk header maps.
//
// Huge : Each allocation is backed by a dedicated contiguous set of chunks.
// Metadata are stored in a separate red-black tree.
//
// *****************************************************************************
ただし、より詳細なアルゴリズム分析はありません。
Jemallocがmozillaにもたらしたメリットについては、 http://blog.pavlov.net/2008/03/11/firefox-3-memory-usage/ (mozilla + jemallocの最初のgoogle結果も) ):
[...] jemallocは、長期間実行した後、最小量の断片化を与えたと結論付けました。 [...] Windows Vistaでの自動テストでは、jemallocをオンにすると、メモリ使用量が22%減少しました。
Aerospikeは、2013年にjemallocをプライベートブランチに実装しました。2014年にAerospike 3.3に組み込まれました。 Psi Mankoskiは、Aerospikeの実装について書いただけでなく、 高拡張性 のために、いつ、どのようにjemallocを効果的に使用するかについても書いています。
jemallocは、Aerospikeが最新のマルチスレッド、マルチCPU、マルチコアコンピューターアーキテクチャを活用するのを本当に助けました。アリーナを管理するためにjemallocに組み込まれているいくつかの非常に重要なデバッグ機能もあります。デバッグにより、Psiは、たとえば、本当のメモリリークとメモリフラグメンテーションの結果を区別することができました。 Psiは、スレッドキャッシュとスレッドごとの割り当てが全体的なパフォーマンス(速度)の改善をどのように提供したかについても説明します。