64

メモリの割り当てと割り当て解除が頻繁に行われる、寿命の長いアプリケーションがあります。malloc解放されたメモリをシステムに返す実装はありますか?

この点で、次の動作は何ですか。

  • ptmalloc 1、2 (glibc のデフォルト) または 3
  • dlmalloc
  • tcmalloc (Google スレッドの malloc)
  • solaris 10-11 のデフォルトの malloc および mtmalloc
  • FreeBSD 8 デフォルトの malloc (jemalloc)
  • 買いだめマロック?

アップデート

malloc日中と夜間でメモリ消費量が大きく異なるアプリケーションがある場合 (例)、解放されたメモリをシステムに戻すよう強制できますか?

そのような戻りがなければ、解放されたメモリは何度もスワップアウトされますが、そのようなメモリにはゴミしか含まれていません。

4

8 に答える 8

39

ptmalloc2次の分析は、(アルゴリズムに基づいて) glibc にのみ適用されます。解放されたメモリをシステムに戻すのに役立つと思われる特定のオプションがあります。

  1. mallopt() ( で定義malloc.h) は、オプション パラメータの 1 つを使用してトリムしきい値を設定するオプションを提供しますM_TRIM_THRESHOLD。これは、データ セグメントの先頭で許容される空きメモリの最小量 (バイト単位) を示します。量がこのしきい値を下回ると、glibc が呼び出さbrk()れてメモリがカーネルに戻されます。

    Linuxのデフォルト値はM_TRIM_THRESHOLD128K に設定されており、より小さい値を設定するとスペースを節約できる場合があります。

    MALLOC_TRIM_THRESHOLD_ソースをまったく変更せずに、環境変数にトリムしきい値を設定することで、同じ動作を実現できます。

    ただし、 を使用して実行された予備テスト プログラムM_TRIM_THRESHOLDは、 によって割り当てられたメモリmallocがシステムに返される場合でも、 によって最初に要求された実際のメモリ チャンク (アリーナ) の残りの部分brk()が保持される傾向があることを示しています。

  2. malloc_trim(pad)( で定義)を呼び出すことで、メモリ アリーナをトリミングし、未使用のメモリをシステムに戻すことができますmalloc.h。この関数は、データ セグメントのサイズを変更し、最後に少なくともpadバイトを残し、解放できるバイトが 1 ページに満たない場合は失敗します。セグメント サイズは常に 1 ページの倍数であり、i386 では 4,096 バイトです。

    この変更された using の動作の実装はfree()malloc_trimmalloc フック機能を使用して行うことができます。これにより、コア glibc ライブラリのソース コードを変更する必要がなくなります。

  3. madvise()の自由な実装内でのシステム コールの使用glibc

于 2010-10-05T02:35:58.277 に答える
17

ほとんどの実装では、(OS に適したサイズの) 「ブロック」全体が解放されて返される可能性がある (比較的まれな) ケースを特定することはありませんが、もちろん例外があります。たとえば、OpenBSDのウィキペディアのページから引用します。

を呼び出すとfree、メモリが解放され、munmap を使用してプロセス アドレス空間からマップ解除されます。このシステムは、OpenBSD のシステム コールの一部として実装されているアドレス空間レイアウトのランダム化とギャップ ページ機能を利用してセキュリティを向上させ、mmap 解放後の使用バグを検出するように設計されています。これは、大規模なメモリ割り当てが解放された後に完全にマップ解除されるためです。 、さらに使用すると、セグメンテーション違反が発生し、プログラムが終了します。

ただし、ほとんどのシステムは OpenBSD ほどセキュリティ重視ではありません。

これを知っているので、一時的に大量のメモリを必要とすることが知られている長期実行システムをコーディングしているとき、私は常にforkプロセスを試みます: 親は子からの結果を待つだけです [[通常、パイプ上で]]、子は計算(メモリ割り当てを含む)を行い、[[パイプ上で]]結果を返し、終了します。このようにして、私の長期実行プロセスは、メモリ要求の時折の「スパイク」の間の長い時間の間に無駄にメモリを占有することはありません. 他の代替戦略には、そのような特別な要件に対応するカスタム メモリ アロケータへの切り替えが含まれます (Java や Python などの仮想マシンを基盤とする言語は通常そうではありませんが、C++ ではかなり簡単です)。

于 2010-02-07T00:26:20.357 に答える
7

アプリで同様の問題が発生しました。いくつかの調査の後、割り当てられたオブジェクトが小さい場合 (私の場合は 120 バイト未満)、何らかの理由で glibc がシステムにメモリを返さないことに気付きました。
このコードを見てください:

#include <list>
#include <malloc.h>

template<size_t s> class x{char x[s];};

int main(int argc,char** argv){
    typedef x<100> X;

    std::list<X> lx;
    for(size_t i = 0; i < 500000;++i){
        lx.push_back(X());
    }

    lx.clear();
    malloc_stats();

    return 0;
}

プログラム出力:

Arena 0:
system bytes     =   64069632
in use bytes     =          0
Total (incl. mmap):
system bytes     =   64069632
in use bytes     =          0
max mmap regions =          0
max mmap bytes   =          0

約 64 MB がシステムに戻されません。typedef を次のように変更すると、 typedef x<110> X;プログラムの出力は次のようになります。

Arena 0:
system bytes     =     135168
in use bytes     =          0
Total (incl. mmap):
system bytes     =     135168
in use bytes     =          0
max mmap regions =          0
max mmap bytes   =          0

ほとんどすべてのメモリが解放されました。malloc_trim(0)また、どちらの場合でもメモリをシステムに解放することに気付きました。上記のコード
に追加した後の出力は次のとおりです。malloc_trim

Arena 0:
system bytes     =       4096
in use bytes     =          0
Total (incl. mmap):
system bytes     =       4096
in use bytes     =          0
max mmap regions =          0
max mmap bytes   =          0
于 2013-12-15T18:44:59.670 に答える
6

OPと同じ問題に取り組んでいます。これまでのところ、tcmalloc で可能のようです。私は2つの解決策を見つけました:

  1. tcmalloc をリンクしてプログラムをコンパイルし、次のように起動します。

    env TCMALLOC_RELEASE=100 ./my_pthread_soft
    

    ドキュメントには、

    妥当なレートは [0,10] の範囲です。

    しかし、私には 10 では十分ではないようです (つまり、変化が見られません)。

  2. 解放されたすべてのメモリを解放するのが興味深いコードのどこかを見つけて、次のコードを追加します。

    #include "google/malloc_extension_c.h" // C include
    #include "google/malloc_extension.h"   // C++ include
    
    /* ... */
    
    MallocExtension_ReleaseFreeMemory();
    

私の場合、2 番目の解決策は非常に効果的でした。最初のものは素晴らしいですが、あまり成功していません。たとえば、適切な数を見つけるのは複雑です。

于 2010-03-10T15:10:12.297 に答える
4

あなたがリストしたもののうち、Hoardだけがシステムにメモリを返します...しかし、実際にそれができるかどうかは、プログラムの割り当て動作に大きく依存します。

于 2010-02-07T00:27:18.440 に答える
3

簡単な答え:mallocサブシステムに強制的にメモリを OS に返すには、 を使用しますmalloc_trim()。それ以外の場合、メモリを返す動作は実装に依存します。

于 2013-05-23T18:25:19.320 に答える