メモリプールオブジェクトに、メモリptrとサイズNの大きなチャンクへのポインタを取るコンストラクタがあるとします。私がさまざまなサイズのランダムな割り当てと割り当て解除を行うと、私はそのような状態でメモリを取得できません多くの空きがあるにもかかわらず、Mバイトオブジェクトをメモリに連続して割り当てます。同時に、私は消費者にぶら下がりのポインタを引き起こすので、私はメモリを圧縮することができません。この場合、断片化はどのように解決されますか?メモリプールでフラグメンテーションを扱う?
答えて
私は2セントを追加したかったのは、標準的なヒープアロケータを実装しているように、あなたの説明から、他の人が指摘したことがないからです。私たちがmalloc()またはoperator newを呼び出すたびに、私たち全員がすでに使用しているもの)。
ヒープはまさにそのようなオブジェクトであり、仮想メモリマネージャーに行き、大量のメモリ(「プール」と呼ばれるもの)を要求します。次に、さまざまなサイズのチャンクを割り当てて解放する最も効率的な方法を扱うためのさまざまなアルゴリズムが用意されています。さらに、多くの人々が長年にわたりこれらのアルゴリズムを修正し最適化してきました。長い間Windowsには、手動で有効にしなければならなかった低フラグメンテーションヒープ(LFH)というオプションが付属していました。 Vistaで始まるLFHはデフォルトですべてのヒープに使用されます。
ヒープは完全ではなく、正しく使用されないとパフォーマンスが低下する可能性があります。 OSベンダーは、ヒープを使用するすべてのシナリオを予期することはできないため、ヒープマネージャーは「平均的な」使用に最適化する必要があります。しかし、通常のヒープ(つまり、多くのオブジェクト、異なるサイズなど)の要件に似た要件がある場合は、ヒープを使用し、再実装しないことを検討する必要があります。これは、実装がどのOSすでにあなたに提供しています。
メモリ割り当てでは、単にヒープを使用しないだけでパフォーマンスを得ることができるのは、特定のアプリケーションにとって重要ではない他の側面(割り当てオーバーヘッド、割り当て寿命など)をあきらめることです。
例えば、私たちのアプリケーションでは、1KB未満の多くの割り当てが必要でしたが、これらの割り当ては非常に短い時間(ミリ秒)の間しか使用されませんでした。アプリケーションを最適化するために、私はBoost Poolライブラリを使用しましたが、私の「アロケータ」には実際には16バイトから1024までの4つの特定のサイズを割り当てるためのブーストプールオブジェクトのコレクションが含まれていました。これは、これらのオブジェクトのほとんど無料(O(1)の複雑さ)割り当て/自由を提供しましたが、キャッチは、a)メモリ使用量は常に大きく、我々は単一のオブジェクトが割り当てられていなくても落ちることはありません。それが使用するメモリを解放します(少なくともそれを使用しているモードでは)ので、これは非常に長く続くことのないオブジェクトに対してのみ使用します。
通常のメモリ割り当てのどの面でアプリをあきらめていますか?
優秀な説明ありがとう。 – user805547
システムによっては、いくつかの方法があります。
最初に断片化を避けるようにしてください.2の累乗でブロックを割り当てると、このような断片化の原因となる可能性は低くなります。それ以外にもいくつかの方法がありますが、メモリを要求するプロセスを強制終了したり、メモリを割り当てることができるまでブロックしたりする以外の方法はありません。割り当て領域としてNULLを返します。
もう1つの方法は、データのポインタ(例:int **)へのポインタを渡すことです。次に、プログラムの下でメモリを並べ替えることができます(スレッドセーフです)。新しいブロックを割り当てて、古いブロックからデータを保持できるように、割り当てを圧縮します(システムがこの状態になると、オーバーヘッドは重くなります。終わり)。
メモリを「ビニング」する方法もあります。たとえば、512ページ以下の割り当て、1ページ以下の1024ページの割り当てなど、1ページだけを連続ページにするなどです。これにより、どちらのビンを使用するのか、そして最悪の場合は、次に高いビンから分割するか、下のビンからマージして、複数のページにわたる断片化の可能性を減らします。
- 割り当てのリストとして動作するプールを作成すると、必要に応じて拡張および破棄できます。断片化を減らすことができます。
- 、および/または割り当て転送(または移動)サポートを実装して、アクティブな割り当てをコンパクトにすることができます。プールは型を転送する方法を必ずしも知っているとは限らないため、オブジェクト/所有者があなたを支援する必要があります。プールがコレクションタイプで使用される場合は、圧縮/転送を実行する方がはるかに簡単です。
頻繁に割り当てるオブジェクトにobject poolsを実装すると、メモリアロケータを変更することなく断片化が大幅に軽減されます。
これに対処する方法がたくさんあるので、実際に何をしようとしているのかをより正確に知ることは役に立ちます。
しかし、最初の質問は:これは実際に起こっているのか、それとも理論的な懸念ですか?
通常、物理メモリよりも多くの仮想メモリアドレススペースを使用できるため、物理メモリが断片化しても、連続した仮想メモリがたくさんあります。 (実際のところ、物理メモリは不連続ですが、あなたのコードではそれが見えません)。
メモリの断片化の恐れがあり、結果として人々がカスタムメモリアロケータを書くことがありますハンドルと可動メモリと圧縮を備えたスキームを作成する)。私はこれらが実際にはめったに必要ではないと思うし、パフォーマンスを改善してmallocを使うことに戻すこともある。
- 1. Nettyでフラグメンテーションを扱う
- 2. フラグメンテーション
- 3. TCPフラグメンテーション
- 4. NodeJS IPフラグメンテーション
- 5. メモリプールとバッファC++
- 6. IPフラグメンテーションと再アセンブリ
- 7. FreeRTOSのメモリプールuC/OS IIのように
- 8. フラグメンテーションで別のレイアウトを表示
- 9. メモリプールを実装する
- 10. setCustomAnimationコールバック前後のフラグメンテーション
- 11. フラグメントとフラグメンテーションのあるTabHost
- 12. AndroidのフラグメンテーションAlertDialogの問題?
- 13. Golangでメモリプールを実装する方法
- 14. Cメモリプールのメモリブロックのデフラグ
- 15. メモリプール返されたメモリアラインメント
- 16. 文字列定数メモリプールC#で
- 17. どのようにフラグメンテーションのリストビューを作成しますか?
- 18. std :: set <T>をメモリプールに接続
- 19. ポリゴンのアルゴリズムでポリゴンを扱うポリゴンを扱うポリゴン
- 20. マルチパートレスポンスを扱う
- 21. オンラインコースを扱う
- 22. マップを扱う
- 23. ブーストヘッダーファイルを扱う
- 24. リカバリでSIGSEGVを扱う?
- 25. RailsコンソールでTime.nowを扱う
- 26. CSVでカンマを扱う
- 27. パンダでNaNを扱う
- 28. Androidでデータベースを扱う
- 29. Pythonで行列を扱う
- 30. Axiosレスポンスでデータを扱う
オペレーティングシステムまたはその一部を実装しようとしていますか?通常の割り振りではフラグメンテーションが処理されるため、通常の割り振りよりメモリプールが優先される唯一の理由があります。 – Dani