Linux アプリケーションプロファイリング 質問する

Linux アプリケーションプロファイリング 質問する

Linux マシン上のアプリケーションのパフォーマンスを記録するにはどうすればよいですか? IDE はありません。

理想的には、プロセスに接続して以下の定期的なスナップショットを記録するアプリケーションが必要です。

  • メモリ使用量
  • スレッド数
  • CPU使用率

ベストアンサー1

理想的には、プロセスに接続して以下の定期的なスナップショットを記録するアプリケーションが必要です。

  • メモリ使用量
  • スレッド数
  • CPU使用率

実は、プロセスに関するこの種の情報を収集するために、Linux ではプロファイラーは必要ありません。

  1. バッチ モードで使用できますtop。強制終了されるか、N 回の反復が完了するまでバッチ モードで実行されます。

    top -b -p `pidof a.out`
    

    または

    top -b -p `pidof a.out` -n 100
    

    そして次のようになります:

    $ top -b -p `pidof a.out`
    
    top - 10:31:50 up 12 days, 19:08,  5 users,  load average: 0.02, 0.01, 0.02
    Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
    Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
    Mem:  16330584k total,  2335024k used, 13995560k free,   241348k buffers
    Swap:  4194296k total,        0k used,  4194296k free,  1631880k cached
    
      PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    24402 SK        20   0 98.7m 1056  860 S 43.9  0.0   0:11.87 a.out
    
    
    top - 10:31:53 up 12 days, 19:08,  5 users,  load average: 0.02, 0.01, 0.02
    Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
    Cpu(s):  0.9%us,  3.7%sy,  0.0%ni, 95.5%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
    Mem:  16330584k total,  2335148k used, 13995436k free,   241348k buffers
    Swap:  4194296k total,        0k used,  4194296k free,  1631880k cached
    
    PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    24402 SK      20   0 98.7m 1072  860 S 19.0  0.0   0:12.44 a.out
    
  2. ps(例えばシェルスクリプトで)次のように使用できます。

    ps --format pid,pcpu,cputime,etime,size,vsz,cmd -p `pidof a.out`
    

    Linuxマシン上のアプリケーションのパフォーマンスを記録する手段が必要です

    これを実行するには、perfLinuxカーネルが2.6.32以降の場合、またはOプロフィールどちらのプログラムも、プログラムをインストルメントする必要はありません(Gprofが必要です)。ただし、呼び出しグラフを正しく取得するには、perfプログラムを -fno-omit-frame-pointer でビルドする必要があります。例: g++ -fno-omit-frame-pointer -O2 main.cpp

Linuxの場合perf:

  1. パフォーマンスデータを記録するには:

    perf record -p `pidof a.out`
    

    または 10 秒間録音するには:

    perf record -p `pidof a.out` sleep 10
    

    またはコールグラフで記録する()

    perf record -g -p `pidof a.out`
    
  2. 記録されたデータを分析する

    perf report --stdio
    perf report --stdio --sort=dso -g none
    perf report --stdio -g none
    perf report --stdio -g
    

    の上レッドヘル6.3 では /boot/System.map-2.6.32-279.el6.x86_64 の読み取りが許可されているため、パフォーマンス レポートを作成するときには通常、--kallsyms=/boot/System.map-2.6.32-279.el6.x86_64 を追加します。

    perf report --stdio -g --kallsyms=/boot/System.map-2.6.32-279.el6.x86_64
    

    ここでは、Linux の `perf` の使用に関する詳細情報をいくつか記述しました。

    まず第一に、これはperf を使用した Linux プロファイリングに関するチュートリアル

    使用できますパフォーマンスLinuxカーネルが2.6.32より大きい場合はOProfile、それより古い場合はOProfileを使用します。どちらのプログラムも、プログラムをインストルメントする必要はありません(Gprofのように)。ただし、コールグラフを正しく取得するには、パフォーマンスプログラムを でビルドする必要があります-fno-omit-frame-pointer。 例: g++ -fno-omit-frame-pointer -O2 main.cpp

    アプリケーションの「ライブ」分析を見ることができますパフォーマンストップ:

     sudo perf top -p `pidof a.out` -K
    

 

または、実行中のアプリケーションのパフォーマンス データを記録し、後で分析することもできます。

  1. パフォーマンスデータを記録するには:

    perf record -p `pidof a.out`
    

    または 10 秒間録音するには:

    perf record -p `pidof a.out` sleep 10
    

    またはコールグラフで記録する()

    perf record -g -p `pidof a.out`
    
  2. 記録されたデータを分析する

perf report --stdio
perf report --stdio --sort=dso -g none
perf report --stdio -g none
perf report --stdio -g

または、次のようにアプリケーションを起動して終了するのを待つだけで、アプリケーションのパフォーマンス データを記録し、後で分析することもできます。

perf record ./a.out

これはテスト プログラムのプロファイリングの例です。

テストプログラムはファイルにありますメインメイン答えの一番下にあります):

私は次のようにコンパイルします:

g++ -m64 -fno-omit-frame-pointer -g main.cpp -L.  -ltcmalloc_minimal -o my_test

私はlibmalloc_minimial.soを使用していますが、これは-fno-omit-frame-pointerでコンパイルされているので、libcmalloc はこのオプションなしでコンパイルされているようです。次に、テスト プログラムを実行します。

./my_test 100000000

次に、実行中のプロセスのパフォーマンス データを記録します。

perf record -g  -p `pidof my_test` -o ./my_test.perf.data sleep 30

次に、モジュールごとの負荷を分析します。

perf report --stdio -g none --sort comm,dso -i ./my_test.perf.data

# Overhead  Command                 Shared Object
# ........  .......  ............................
#
    70.06%  my_test  my_test
    28.33%  my_test  libtcmalloc_minimal.so.0.1.0
     1.61%  my_test  [kernel.kallsyms]

次に、関数ごとの負荷が分析されます。

perf report --stdio -g none -i ./my_test.perf.data | c++filt

# Overhead  Command                 Shared Object                       Symbol
# ........  .......  ............................  ...........................
#
    29.30%  my_test  my_test                       [.] f2(long)
    29.14%  my_test  my_test                       [.] f1(long)
    15.17%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator new(unsigned long)
    13.16%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator delete(void*)
     9.44%  my_test  my_test                       [.] process_request(long)
     1.01%  my_test  my_test                       [.] operator delete(void*)@plt
     0.97%  my_test  my_test                       [.] operator new(unsigned long)@plt
     0.20%  my_test  my_test                       [.] main
     0.19%  my_test  [kernel.kallsyms]             [k] apic_timer_interrupt
     0.16%  my_test  [kernel.kallsyms]             [k] _spin_lock
     0.13%  my_test  [kernel.kallsyms]             [k] native_write_msr_safe

     and so on ...

次に、呼び出しチェーンが分析されます。

perf report --stdio -g graph -i ./my_test.perf.data | c++filt

# Overhead  Command                 Shared Object                       Symbol
# ........  .......  ............................  ...........................
#
    29.30%  my_test  my_test                       [.] f2(long)
            |
            --- f2(long)
               |
                --29.01%-- process_request(long)
                          main
                          __libc_start_main

    29.14%  my_test  my_test                       [.] f1(long)
            |
            --- f1(long)
               |
               |--15.05%-- process_request(long)
               |          main
               |          __libc_start_main
               |
                --13.79%-- f2(long)
                          process_request(long)
                          main
                          __libc_start_main

    15.17%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator new(unsigned long)
            |
            --- operator new(unsigned long)
               |
               |--11.44%-- f1(long)
               |          |
               |          |--5.75%-- process_request(long)
               |          |          main
               |          |          __libc_start_main
               |          |
               |           --5.69%-- f2(long)
               |                     process_request(long)
               |                     main
               |                     __libc_start_main
               |
                --3.01%-- process_request(long)
                          main
                          __libc_start_main

    13.16%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator delete(void*)
            |
            --- operator delete(void*)
               |
               |--9.13%-- f1(long)
               |          |
               |          |--4.63%-- f2(long)
               |          |          process_request(long)
               |          |          main
               |          |          __libc_start_main
               |          |
               |           --4.51%-- process_request(long)
               |                     main
               |                     __libc_start_main
               |
               |--3.05%-- process_request(long)
               |          main
               |          __libc_start_main
               |
                --0.80%-- f2(long)
                          process_request(long)
                          main
                          __libc_start_main

     9.44%  my_test  my_test                       [.] process_request(long)
            |
            --- process_request(long)
               |
                --9.39%-- main
                          __libc_start_main

     1.01%  my_test  my_test                       [.] operator delete(void*)@plt
            |
            --- operator delete(void*)@plt

     0.97%  my_test  my_test                       [.] operator new(unsigned long)@plt
            |
            --- operator new(unsigned long)@plt

     0.20%  my_test  my_test                       [.] main
     0.19%  my_test  [kernel.kallsyms]             [k] apic_timer_interrupt
     0.16%  my_test  [kernel.kallsyms]             [k] _spin_lock
     and so on ...

この時点で、プログラムが時間を費やす場所がわかります。

そしてこれがメインテスト用のファイル:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

time_t f1(time_t time_value)
{
  for (int j = 0; j < 10; ++j) {
    ++time_value;
    if (j%5 == 0) {
      double *p = new double;
      delete p;
    }
  }
  return time_value;
}

time_t f2(time_t time_value)
{
  for (int j = 0; j < 40; ++j) {
    ++time_value;
  }
  time_value = f1(time_value);
  return time_value;
}

time_t process_request(time_t time_value)
{
  for (int j = 0; j < 10; ++j) {
    int *p = new int;
    delete p;
    for (int m = 0; m < 10; ++m) {
      ++time_value;
    }
  }
  for (int i = 0; i < 10; ++i) {
    time_value = f1(time_value);
    time_value = f2(time_value);
  }
  return time_value;
}

int main(int argc, char* argv2[])
{
  int number_loops = argc > 1 ? atoi(argv2[1]) : 1;
  time_t time_value = time(0);
  printf("number loops %d\n", number_loops);
  printf("time_value: %d\n", time_value);

  for (int i = 0; i < number_loops; ++i) {
    time_value = process_request(time_value);
  }
  printf("time_value: %ld\n", time_value);
  return 0;
}

おすすめ記事