Мне нужно какое-то средство записи производительности приложения на машине Linux. У меня не будет IDE.
В идеале мне нужно приложение, которое будет прикрепляться к процессу и записывать периодические снимки:
использование памяти
количество потоков
Использование ЦП
Ответ 2
В идеале, мне нужно приложение, которое будет прикрепляться к процессу и записывать периодические снимки: количество использования памяти в потоках использования процессора
Ну, для сбора этих типов информации о вашем процессе вам не нужен профилировщик в 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
(например, в оболочке script)
ps --format pid,pcpu,cputime,etime,size,vsz,cmd -p `pidof a.out`
Мне нужны некоторые средства записи производительности приложения на машине Linux
Для этого вам нужно использовать perf
, если ваш Linux Kernal больше 2.6.32 или Oprofile, если он старше. Обе программы не требуют от вас инструктировать вашу программу (например, gporf
). Однако для правильного отображения графика звонка в 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
В RHEL 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:
Прежде всего - это учебник по профилированию Linux с перфомансом
Вы можете использовать perf, если ваше ядро Linux больше 2.6.32 или oprofile, если оно старше. Обе программы не требуют от вас инструментария вашей программы (например, требуется gprof). Однако, чтобы правильно получить график звонков в перфомансе, вам нужно создать программу с помощью -fno-omit-frame-pointer
. Например: g++ -fno-omit-frame-pointer -O2 main.cpp
.
Вы можете увидеть "живой" анализ вашего приложения с помощью perf top:
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
Это пример профилирования тестовой программы
Тест-программа находится в файле main.cpp(я поставлю main.cpp в нижней части сообщения):
Я скомпилирую его следующим образом:
g++ -m64 -fno-omit-frame-pointer -g main.cpp -L. -ltcmalloc_minimal -o my_test
Я использую libmalloc_minimial.so, поскольку он скомпилирован с -fno-omit-frame-pointer, в то время как libc malloc, кажется, скомпилирован без этой опции. Затем я запускаю свою тестовую программу
./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 ...
Итак, в этот момент вы знаете, где ваша программа проводит время.
И это main.cpp для теста:
#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;
}