[AIX]tprofの見方の例
CPUをどのプロセスが使っているかを見るためのコマンドです。
注:
この文書での方法は1つの考え方でしかなく異論反論があると思いますので、そういった意見をお持ちの方はぜひとも別の文書で考え方を公開ください。
tprofコマンドの実行例:
※Dedicated CPUの環境では-Rは不要です。
# tprof -RskeutP all -x sleep 10
...
Generating sleep.prof
sleep.profファイルの見方
まずは先頭のプロセス単位のレポートを見ます。
上位がテストプログラム(pth_malloc)とwaitプロセス(つまりIdle状態)のため、テストプログラム(pth_malloc)がCPUを使用していたことが分かります。
Process Freq Total Kernel User Shared Other
======= ==== ===== ====== ==== ====== =====
./pth_malloc 482 89.36 72.05 0.67 16.64 0.00
wait 8 10.56 10.56 0.00 0.00 0.00
/usr/bin/sh 2 0.03 0.03 0.00 0.00 0.00
内訳を見るとKernelの値が高いため、一見OSの問題にも見えますが、今回はそうではないので詳細を確認していきます。
Kernelの値が高かったため、次はAll Processes (KERNEL)を確認します。
Total % For All Processes (KERNEL) = 82.69
Subroutine % Source
========== ====== ======
.unlock_enable_mem 38.65 low.s
svc_epilog64 10.12 low.s
sc_msr_2_point 6.75 low.s
すると、unlock_enable_mem()が多くのCPUを使っていることが分かります。
この関数はロック処理に使用される関数のため、呼び出し元を探していきます。
プロセス単位のレポートで見た際にUserの値が低くSharedが高めだったため、ライブラリコールを確認します。(procstackやpdump.shなどを併用しておくとここから先の作業が不要になる場合があります。)
Total % For All Processes (SH-LIBs) = 16.64
Shared Object %
============= ======
/usr/lib/libpthreads.a[shr_xpg5_64.o] 12.59
/usr/lib/libc.a[shr_64.o] 4.05
上記からlibpthreads.aとlibc.aがCPUを使用していたことが分かります。
内訳を見ると下記のようになっており、libpthreads.aはロック処理でCPUを使用していて、libc.aはmalloc/freeでCPUを使用していたことが分かります。
Total % For All Processes (/usr/lib/libpthreads.a[shr_xpg5_64.o]) = 12.59
Subroutine % Source
========== ====== ======
._global_lock_common 10.98 reads/pth_spinlock.c
.global_unlock_ppc_mp 0.63 pth_locks_ppc_mp.s
._global_unlock_common 0.33 reads/pth_spinlock.c
.global_lock_ppc_mp_eh 0.26 th_locks_ppc_mp_eh.s
.thread_waitlock_ 0.23 glink64.s
.thread_unlock_ 0.08 glink64.s
Profile: /usr/lib/libc.a[shr_64.o]
Total % For All Processes (/usr/lib/libc.a[shr_64.o]) = 4.05
Subroutine % Source
========== ====== ======
.malloc_y 1.25 /lib/libc/malloc_y.c
.free_y 1.20 /lib/libc/malloc_y.c
.splay 0.81 /lib/libc/malloc_y.c
ここでテストプログラムを確認します。
CPU負荷のテスト用プログラム:
# cat pth_malloc.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <memory.h>
#include <string.h>
#define THREAD_SIZE 512
#define MALLOC_SIZE 128*1024
void* thread_start_routine()
{
int i=0;
int *test = NULL;
sleep(1);
for(i = 0; i<10000; i++){
test = (int*)malloc(MALLOC_SIZE);
if ( test == NULL ){
printf("malloc fail\n");
}
memset(&test[0], 0x00, sizeof(MALLOC_SIZE));
free(test);
}
return(NULL);
}
int main()
{
int i;
pthread_t th[THREAD_SIZE];
void *th_ret[THREAD_SIZE];
for(i=0; i<THREAD_SIZE; i++){
if (pthread_create(&th[i], NULL, thread_start_routine, NULL) != 0) {
perror("pthread_create");
return(1);
}
}
for(i=0; i<THREAD_SIZE; i++){
if (pthread_join(th[i], &th_ret[i]) != 0) {
perror("pthread_join");
return(1);
}
}
return(0);
}
# ibm-clang_r -m64 -g pth_malloc.c -o pth_malloc
マルチスレッドから大量にmalloc/freeを実行していて、下記テックノートに類似の状態になっていることが分かります。
Server performance degrades significantly during client backups
https://www.ibm.com/support/pages/node/508579
Throughput problems when malloc is called often in SSL mode
https://www.ibm.com/support/pages/node/271903
そのため、プログラムの見直し、MALLOCOPTIONSなどの環境変数でのチューニング、SMTのOFF、VPの削減などがチューニングが次のアクションプランになることが分かります。
参考:
コマンド tprof
https://www.ibm.com/docs/ja/aix/7.3.0?topic=tools-tprof-command
CPU のボトルネック
https://www.ibm.com/docs/ja/sdk-java-technology/8?topic=aix-cpu-bottlenecks