Idealnya, saya memerlukan aplikasi yang akan dilampirkan ke proses dan mencatat snapshot berkala dari:
- penggunaan memori
- jumlah utas
- Penggunaan CPU
Nah, untuk mengumpulkan jenis informasi tentang proses Anda, Anda sebenarnya tidak memerlukan profiler di Linux.
-
Anda dapat menggunakan
top
dalam mode batch. Ini berjalan dalam mode batch sampai dimatikan atau sampai N iterasi selesai:top -b -p `pidof a.out`
atau
top -b -p `pidof a.out` -n 100
dan Anda akan mendapatkan ini:
$ 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
-
Anda dapat menggunakan
ps
(misalnya dalam skrip Shell)
ps --format pid,pcpu,cputime,etime,size,vsz,cmd -p `pidof a.out`
Saya memerlukan beberapa cara untuk merekam kinerja aplikasi di mesin Linux
Untuk melakukan ini, Anda perlu menggunakan
perf
jika kernel Linux Anda lebih besar dari 2.6.32 atau OProfile jika lebih tua. Kedua program tidak mengharuskan Anda untuk melengkapi program Anda (seperti yang dibutuhkan Gprof). Namun, untuk mendapatkan grafik panggilan dengan benar diperf
Anda perlu membangun program Anda dengan -fno-omit-frame-pointer. Misalnya:g++ -fno-omit-frame-pointer -O2 main.cpp
.
Sedangkan untuk Linux perf
:
-
Untuk merekam data performa:
perf record -p `pidof a.out`
atau untuk merekam selama 10 detik:
perf record -p `pidof a.out` sleep 10
atau untuk merekam dengan grafik panggilan ()
perf record -g -p `pidof a.out`
-
Untuk menganalisis data yang direkam
perf report --stdio perf report --stdio --sort=dso -g none perf report --stdio -g none perf report --stdio -g
Pada RHEL 6.3 diperbolehkan untuk membaca /boot/System.map-2.6.32-279.el6.x86_64, jadi saya biasanya menambahkan --kallsyms=/boot/System.map-2.6.32-279.el6.x86_64 saat melakukan laporan kinerja:
Di sini saya menulis beberapa informasi lebih lanjut tentang penggunaan Linux `perf`:perf report --stdio -g --kallsyms=/boot/System.map-2.6.32-279.el6.x86_64
Pertama-tama - ini adalah tutorial tentang pembuatan profil Linux dengan perf
Anda dapat menggunakan sempurna jika Kernel Linux Anda lebih besar dari 2.6.32 atau OProfile jika lebih tua. Kedua program tidak mengharuskan Anda untuk melengkapi program Anda (seperti yang dibutuhkan Gprof). Namun, untuk mendapatkan grafik panggilan dengan benar di perf Anda perlu membuat program dengan
-fno-omit-frame-pointer
. Misalnya:g++ -fno-omit-frame-pointer -O2 main.cpp
.Anda dapat melihat analisis "langsung" dari aplikasi Anda dengan perf top :
sudo perf top -p `pidof a.out` -K
Atau Anda dapat merekam data kinerja aplikasi yang sedang berjalan dan menganalisisnya setelah itu:
-
Untuk merekam data performa:
perf record -p `pidof a.out`
atau untuk merekam selama 10 detik:
perf record -p `pidof a.out` sleep 10
atau untuk merekam dengan grafik panggilan ()
perf record -g -p `pidof a.out`
-
Untuk menganalisis data yang direkam
perf report --stdio
perf report --stdio --sort=dso -g none
perf report --stdio -g none
perf report --stdio -g
Atau Anda dapat merekam data performa aplikasi dan menganalisisnya setelah itu hanya dengan meluncurkan aplikasi dengan cara ini dan menunggu hingga keluar:
perf record ./a.out
Ini adalah contoh pembuatan profil program pengujian.
Program pengujian ada di file main.cpp (main.cpp ada di bagian bawah jawaban):
Saya mengkompilasinya dengan cara ini:
g++ -m64 -fno-omit-frame-pointer -g main.cpp -L. -ltcmalloc_minimal -o my_test
Saya menggunakan libmalloc_minimial.so karena dikompilasi dengan -fno-omit-frame-pointer sementara libc malloc tampaknya dikompilasi tanpa opsi ini. Kemudian saya menjalankan program pengujian saya:
./my_test 100000000
Lalu saya merekam data kinerja dari proses yang sedang berjalan:
perf record -g -p `pidof my_test` -o ./my_test.perf.data sleep 30
Kemudian saya menganalisis beban per modul:
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]
Kemudian muat per fungsi dianalisis:
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 ...
Kemudian rantai panggilan dianalisis:
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 ...
Jadi pada titik ini Anda tahu di mana program Anda menghabiskan waktu.
Dan ini adalah main.cpp file untuk pengujian:
#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;
}
Mengutip Linus Torvalds sendiri:
Jangan gunakan gprof. Kamu banyak lebih baik menggunakan alat 'perf' Linux yang agak baru.
Dan nanti ...
Saya dapat menjamin bahwa begitu Anda mulai menggunakannya, Anda tidak akan pernah menggunakan gprof atau oprofile lagi.
Lihat Re:[PATCH] grep:jangan lakukan grep eksternal pada entri skip-worktree (2010-01-04)