Jemalloc 原則の概要

Jemalloc は Linux の世界で名声を博し、複数のプラットフォームに移植されています。新星である tcmalloc も同様の性能を持っており、Google もありますが、jemalloc の美しさのせいで利用範囲はまだ若干劣ります。jemalloc についてはインターネット上に多くの解釈があるため、一つずつ説明することはしませんが、分析すべき重要なポイントをいくつか紹介します。

1. アドレスアクセス
malloc と free の最初のパラメータはメモリ アドレスです。そのアドレスが属するメモリ ブロックのベース アドレスを素早く見つけるにはどうすればよいでしょうか? 高頻度のメモリ割り当てでは、これが最優先事項です。jemalloc は、chunk = addr & (~chunksize_mask) という単純なトリックを使用して、アドレス指定が O(1) で実行できるようにします。この式には、チャンクのアドレスが 0xaabb0000 のような形式を満たす必要があり、末尾の 0 の数が chunksize_mask の F の数以上でなければならないという、非常に曖昧な前提があります。
jemalloc は割り当てを行うときに、alloc_size = サイズ + アライメント - PAGE_SIZE を試行し、ヘッダーを削除してチャンク アドレスがこの条件を満たすことを確認します。そうでない場合は、冗長メモリ アドレスをシステムに返します。

2. メモリページの管理
小さなオブジェクトはトリックを使用してチャンクにマッピングできますが、チャンクのアドレス指定に上記のトリックを使用する方法はありません。Jemalloc は 3 層の基数ツリーを使用しているため、検索効率は依然として非常に高いですが、追加、削除、変更、確認の際にロックが必要です。ロックは効率に影響しますが、回数が比較的少ないため大きな影響はありません。割り当て後、jemalloc のグローバル基数ツリーのノードは、最終プロセスが終了するまで解放されないことに注意してください。システムからは毎回 4M に基づいて jemalloc が適用されます。

3. 長さの調整
実際のシナリオでは、割り当てに要求されるバイト サイズはランダムであり、実際のサイズに従って割り当てられると、メモリ ページ欠落割り込みが発生しやすくなるため、バイト アライメントが必要になります。jemalloc では、固定バイト アライメントではなく、次の表のロジックに従います。
シリアルナンバー
サイズ範囲
バイトアライメント
0
[0--16]
8
1
(16、128]
16
2
(128、256]
32
3
(256、512]
64

4. スレッド競争
メモリ割り当て中に、ロックによりスレッドが待機するため、パフォーマンスに大きな影響を与えます。Jemalloc はスレッド競合ロックの発生を回避するために 2 つの手段を使用します。
1. スレッド変数を使用すると、各スレッドが独自のメモリ マネージャーを持ち、割り当てはそのスレッド内で完了するため、他のスレッドと競合する必要がありません。
2. アリーナは配列を割り当て、各スレッドはスレッド番号のマッピングを通じて配列要素に対応します。このようにして、複数のスレッドが要素をめぐって競合する可能性が減ります。
ちょっと驚くべきことに、jemalloc は基本的にアトミック操作を使用せず、ロックはすべてより粒度の高いミューテックスを使用します。この種の粗粒度のロックは、システムでスタックしている場合など、長時間待機する必要がある場合にのみ必要です。アリーナに関する情報はオンラインでたくさん見つかります。

5. 割り当てプロセス
サイズ SIZE のメモリ ブロックが割り当てられるアプリケーション シナリオを想定しています。プロセスは次のとおりです。
1. アリーナまたはキャッシュを選択します。
2. 対応するアライメント長を計算し (セクション 3 を参照)、アライメント長に従ってアリーナ内のビンの添え字を計算します。
3. ビンで、runccur が使用可能な場合は runcur に割り当て、そうでない場合は run から 1 つを選択します。
4. 選択した実行からビットマップを計算し、空き領域を取得して戻ります。



Jemalloc は Linux の世界で名声を博し、複数のプラットフォームに移植されています。新星である tcmalloc も同様の性能を持っており、Google もありますが、jemalloc の美しさのせいで利用範囲はまだ若干劣ります。jemalloc についてはインターネット上に多くの解釈があるため、一つ一つ説明しませんが、分析すべき重要なポイントをいくつか紹介します。

1. アドレスアクセス
malloc と free の最初のパラメータはメモリ アドレスです。そのアドレスが属するメモリ ブロックのベース アドレスを素早く見つけるにはどうすればよいでしょうか? 高頻度のメモリ割り当てでは、これが最優先事項です。jemalloc は、chunk = addr & (~chunksize_mask) という単純なトリックを使用して、アドレス指定が O(1) で実行できるようにします。この式には、チャンクのアドレスが 0xaabb0000 のような形式を満たす必要があり、末尾の 0 の数が chunksize_mask の F の数以上でなければならないという、非常に曖昧な前提があります。
jemalloc は割り当てを行うときに、alloc_size = サイズ + アライメント - PAGE_SIZE を試行し、ヘッダーを削除してチャンク アドレスがこの条件を満たすことを確認します。そうでない場合は、冗長メモリ アドレスをシステムに返します。

2. メモリページの管理
小さなオブジェクトはトリックを使用してチャンクにマッピングできますが、チャンクのアドレス指定に上記のトリックを使用する方法はありません。Jemalloc は 3 層の基数ツリーを使用しているため、検索効率は依然として非常に高いですが、追加、削除、変更、確認の際にロックが必要です。ロックは効率に影響しますが、回数が比較的少ないため大きな影響はありません。割り当て後、jemalloc のグローバル基数ツリーのノードは、最終プロセスが終了するまで解放されないことに注意してください。システムからは毎回 4M に基づいて jemalloc が適用されます。

3. 長さの調整
実際のシナリオでは、要求されるバイト サイズはランダムであり、実際のサイズに従って割り当てられると、メモリ ページ欠落割り込みが発生しやすくなるため、バイト アライメントが必要になります。jemalloc では、固定バイト アライメントではなく、次の表のロジックに従います。
シリアルナンバー
サイズ範囲
バイトアライメント
0
[0--16]
8
1
(16、128]
16
2
(128、256]
32
3
(256、512]
64

4. スレッド競争
メモリ割り当て中に、ロックによりスレッドが待機するため、パフォーマンスに大きな影響を与えます。Jemalloc はスレッド競合ロックの発生を回避するために 2 つの手段を使用します。
1. スレッド変数を使用すると、各スレッドが独自のメモリ マネージャーを持ち、割り当てはそのスレッド内で完了するため、他のスレッドと競合する必要がありません。
2. アリーナは配列を割り当て、各スレッドはスレッド番号のマッピングを通じて配列要素に対応します。このようにして、複数のスレッドが要素をめぐって競合する可能性が減ります。
ちょっと驚くべきことに、jemalloc は基本的にアトミック操作を使用せず、ロックはすべてより粒度の高いミューテックスを使用します。この種の粗粒度のロックは、システムでスタックしている場合など、長時間待機する必要がある場合にのみ必要です。アリーナに関する情報はオンラインでたくさん見つかります。

5. 割り当てプロセス
サイズ SIZE のメモリ ブロックが割り当てられるアプリケーション シナリオを想定しています。プロセスは次のとおりです。
1. アリーナまたはキャッシュを選択します。
2. 対応するアライメント長を計算し (セクション 3 を参照)、アライメント長に従ってアリーナ内のビンの添え字を計算します。
3. ビンで、runccur が使用可能な場合は runcur に割り当て、そうでない場合は run から 1 つを選択します。
4. 選択した実行からビットマップを計算し、空き領域を取得して戻ります。



おすすめ

転載: blog.csdn.net/yc7369/article/details/124366827