2016-07-20 10 views
8

これは他の質問と重複しているように見えるかもしれませんが、なぜそうでないのか説明してください。Linux(およびOSX)で割り当てられたメモリの量を照会するにはどうすればよいですか?

特定のメモリ制限に達すると、アプリケーションの特定の部分が正常に機能しなくなることを期待しています。残りの物理メモリに基づいて基準を使用することもできましたが、安全ではないでしょう。同じ理由で、私はOSが私を交換し始めるとすぐに、OSのページメモリとして割り当てることを続けるので、現在のプロセスで使用されている物理メモリの量を使用することはできません。もはや成長しない。

この理由から、アプリケーションで割り当てられたメモリの量、つまり仮想メモリのサイズに非常に近い基準を選択しました。

この質問(How to determine CPU and memory consumption from inside a process?)は、私が必要と思った現在のプロセスで使用されている仮想メモリの量を問い合わせる素晴らしい方法を提供します。

Windowsでは、私はGetProcessMemoryInfo()フィールドとPrivateUsageフィールドを使用しています。これはうまくいきます。

Linuxでは、私は動作しなかったいくつかのもの(以下に記載)を試しました。仮想メモリの使用が私にとってうまくいかない理由は、Linux上のNVidiaハードウェアでOpenCLコンテキストを作成するときに起こることが原因です。ドライバは、すべてのRAM、すべてのスワップおよびすべてのビデオメモリを保持するのに十分な大きさの仮想メモリ空​​間の領域を予約します。私は、統一されたアドレス空間とすべてのためにそう思っています。しかし、それはまた、プロセスが膨大な量のメモリを使用して報告することを意味します。たとえば、私のシステムでは、トップはVIRTカラム(12GbのRAM、6Gbのスワップ、2Gbのビデオメモリ、NVidiaドライバによって予約された20Gbを与える)で23.3Gbを報告します。

task_info()virtual_sizeフィールドを使用すると、予想よりも大きな数字(Windowsでは1Gbにも近くないアプリケーションでは数GB)が得られますが、Linuxほど大きくはありません。

ここで大きな疑問があります。私のアプリケーションによって割り当てられるメモリの量はどうすればわかりますか?私は、これはやや漠然とした質問(?手段何を「メモリを割り当てられた」ん)であることを知っているが、私は柔軟だ:

  • 私は、アプリケーションの静的データ、コードセクション、すべてを含めることを好むだろうが、私はすることができますなしに生きる。
  • 私はスタックに割り当てられたメモリを含めることを好むでしょうが、私はなくても使えます。
  • 私は共有ライブラリで使用されているメモリを含めることをお勧めしますが、私はこのライブラリを使わずに暮らすことができます。
  • 私は実際にmmapのものを気にしません、私はその時点で、またはなしで行うことができます。

本当に重要なのは、数が(私は実装依存することを知っている)動的割り当て(新しい、malloc関数、何でも)で成長し、メモリが解放されたときに縮むことです。私はここで

を試してみました

物事は私が試してみましたソリューションのカップルおよび/またはのことを考えているが、それは私のために動作しないでしょう。これはどのようにツー・決定し、CPUとメモリ消費-から-インサイド・プロセスによって提案されたアプローチがある読み取り/ procの/自己/ステータス

から

  1. 。しかし、上記のように、これは私のために動作しない仮想メモリの量を返します。

  2. を読むの/ proc /自己/ STATMから

    ごくわずか最悪:Linuxカーネルのコードを指すhttp://kernelnewbies.kernelnewbies.narkive.com/iG9xCmwB/proc-pid-statm-doesnt-match-with-statusによれば、これらの2つの値の間の唯一の違いは、第二の一方がないことですreserved_vmを仮想メモリの量に引く。私は、reserved_vmにはOpenCLドライバによって予約されているメモリが含まれていると願っていましたが、そうではありません。

  3. 使用mallinfo()uordblksフィールドが

    これは後に(仮想メモリ空​​間内+ 2GBの成長のためにいるので、(私はnew sが不足している推測している)すべての割り当てを含めていないようです記憶が重い仕事をしていてもメモリを保持している)、私はmallinfo()によって返された数字の約0.1Gbの成長しか見ていない。

  4. この値はKB周り336760で開始し、+ 2Gbのことで、仮想メモリ空​​間を増加した仕事のために1019496 KBでピークに達し、その後、

    smaps /の/ proc /自己から[ヒープ]セクションのサイズを読みますそれが降りたことがないので、私は、私は本当にこの数に頼ることができないかわからない...

  5. モニター自分のアプリケーション内のすべてのメモリ割り当てを

    はい、理想的な世界では、私が希望前夜を支配するメモリを割り当てる人。しかし、これはいくつかの異なるアロケータを使用する従来のアプリケーションであり、いくつかのmalloc、いくつかのnew、いくつかのOS固有のルーチンなどがあります。必要なものを実行できるプラグインがいくつかあります。コンパイラなどを使用することができます。これは実際にメモリを制御するのには素晴らしいかもしれませんが、これは私の状況では機能しません。

  6. これが問題を解決するために(と私はそれにフォールバックする必要があるかもしれません)「ハック」方法かもしれないが、私は本当に希望のOpenCLコンテキストの初期化の前と後に

    を仮想メモリのサイズを読みますOpenCLコンテキストが私のコントロールのどこかから初期化される可能性があるので、メモリを照会するより信頼性の高い方法を望んでいますが、他の類似しているがOpenCL以外の特定の問題が陥る可能性があります。

これはほとんどすべてのものです。まだ試していないことがもう1つありますが、これはOSXでしか機能しませんが、Why does mstats and malloc_zone_statistics not show recovered memory after free?に記載されている方法を使用することです。malloc_get_all_zones()malloc_zone_statistics()を使用しますが、これはmallinfo()と同じ問題だと思いますすべての配分を考慮する。

誰でも、Linuxの特定のプロセス(とは別の方法であってもOSX)のメモリ使用量をクエリする方法を提案できますか?

+0

mallinfo()with(arena + hblkhd + uordblks) –

+0

@brianbeuning:http://man7.org/linux/man-pages/man3/mallinfo.3.htmlによると、 'arena'は' uordblks' + 'fordblks'ので、あなたの提案はいくつかのメモリを2回カウントアップするだろう... –

答えて

0

ここに私が使用して終了するものです。

  • のみのiノード0からの範囲(すなわちなどがない機器、ノーマッピングされたファイル、)
  • が含まれています。私は/ procの/セルフ/マップをスキャンし、すべてのアドレスのサイズを合計することであるが、私の基準を満たす範囲
  • のみの少なくとも一つは、読み出し書き込み可能または実行
  • のみ私は、プロセス間共有メモリを持つかもしれないiノード0から共有メモリのインスタンスを見ていない私の実験では、プライベートメモリ
    • が含まれている範囲を含みます。 ..?ここで

私の解決策のためのコードです:

size_t getValue() 
{ 
    FILE* file = fopen("/proc/self/maps", "r"); 
    if (!file) 
    { 
     assert(0); 
     return 0; 
    } 

    size_t value = 0; 

    char line[1024]; 
    while (fgets(line, 1024, file) != NULL) 
    { 
     ptrdiff_t start_address, end_address; 
     char perms[4]; 
     ptrdiff_t offset; 
     int dev_major, dev_minor; 
     unsigned long int inode; 
     const int nb_scanned = sscanf(
      line, "%16tx-%16tx %c%c%c%c %16tx %02x:%02x %lu", 
      &start_address, &end_address, 
      &perms[0], &perms[1], &perms[2], &perms[3], 
      &offset, &dev_major, &dev_minor, &inode 
      ); 
     if (10 != nb_scanned) 
     { 
      assert(0); 
      continue; 
     } 

     if ((inode == 0) && 
      (perms[0] != '-' || perms[1] != '-' || perms[2] != '-') && 
      (perms[3] == 'p')) 
     { 
      assert(dev_major == 0); 
      assert(dev_minor == 0); 
      value += (end_address - start_address); 
     } 
    } 

    fclose(file); 

    return value; 
} 

これはメモリを照会、/ procの/自己/マップ内のすべてのラインを介してループしているので、その方法は、「使用するよりもかなり遅いです現在のプロセスで現在使用されている仮想メモリ "からHow to determine CPU and memory consumption from inside a process?

しかし、それは私が必要とするものにもっと近い答えを提供します。

1

あなたはgetrusage()によって返された情報を試してみて、使用することができます。

#include <sys/time.h> 
#include <sys/resource.h> 

int getrusage(int who, struct rusage *usage); 

struct rusage { 
    struct timeval ru_utime; /* user CPU time used */ 
    struct timeval ru_stime; /* system CPU time used */ 
    long ru_maxrss;  /* maximum resident set size */ 
    long ru_ixrss;   /* integral shared memory size */ 
    long ru_idrss;   /* integral unshared data size */ 
    long ru_isrss;   /* integral unshared stack size */ 
    long ru_minflt;  /* page reclaims (soft page faults) */ 
    long ru_majflt;  /* page faults (hard page faults) */ 
    long ru_nswap;   /* swaps */ 
    long ru_inblock;  /* block input operations */ 
    long ru_oublock;  /* block output operations */ 
    long ru_msgsnd;  /* IPC messages sent */ 
    long ru_msgrcv;  /* IPC messages received */ 
    long ru_nsignals;  /* signals received */ 
    long ru_nvcsw;   /* voluntary context switches */ 
    long ru_nivcsw;  /* involuntary context switches */ 
}; 

メモリ情報があなたの目的に合わない場合は、ページフォルト数を観察すると、あなたが検出しようとするものですモニタメモリのストレスを、助けることができます。

+0

提案をありがとう。私はそれを試しました( 'ru_ixrss'、' ru_idrss'と 'ru_isrss')。そしてすべてのフィールドは0です。manページによれば、「すべてのフィールドが完了しているわけではなく、維持されていないフィールドはカーネルによってゼロに設定されています。 「Linux 2.4では、ru_utime、ru_stime、ru_minflt、およびru_majfltのフィールドだけが維持されます.Linux 2.6以降、ru_nvcswおよびru_nivcswも維持されます。 –

1

上記セクション(5)のLinux用共有ライブラリインターポーザを試しましたか?アプリケーションがmalloc関数を静的にリンクしていない限り、プログラムとカーネルmallocの間に新しい関数を挿入することができます。私はメモリ使用量に関する統計情報を収集するためにこの手法を何度も使用してきました。

プログラムを実行する前にLD_PRELOADを設定する必要がありますが、ソースまたはバイナリの変更は必要ありません。多くの場合、理想的な答えです。ここで

は、mallocのインターポーザの例である:

http://www.drdobbs.com/building-library-interposers-for-fun-and/184404926

あなたはおそらくものcallocと自由を行うことになるでしょう。新しい呼び出しはmallocの呼び出しとして終了するので、C++も同様に扱われます。

OS Xは同様の機能を持つようですが、試していません。

http://tlrobinson.net/blog/2007/12/overriding-library-functions-in-mac-os-x-the-easy-way-dyld_insert_libraries/

--Matt

関連する問題