perf отчет о системном вызове

У меня есть следующий вывод для отчета о производительности (о malloc) для процесса A, B:

записано: perf record -e cycles:u

Процесс А:

0.00%       1833448  Test-Recv  libc-2.17.so           [.] malloc              
0.00%       1833385  Test-Recv  [kernel.kallsyms]      [k] system_call         
0.00%        916588  Test-Recv  libc-2.17.so           [.] _int_malloc

а также следующее для процесса B:

24.90%   10855848444  test.exe  libc-2.17.so   [.] _int_malloc
15.78%    6881565672  test.exe  libc-2.17.so   [.] _int_free
 7.48%    3261672221  test.exe  libc-2.17.so   [.] malloc
 4.66%    2030332370  test.exe  libc-2.17.so   [.] systrim.isra.2
 2.43%    1061251259  test.exe  libc-2.17.so   [.] free
 2.12%     925588492  test.exe  test.exe       [.] main

Оба они делают некоторые malloc в исходном коде.

Могу ли я предположить, что в случае процесса A malloc действительно вызывает системный вызов, но в случае процесса B системный вызов не происходит, поскольку в отчете о производительности процесса B вообще нет [k] system_call !!!


person barfatchen    schedule 16.04.2018    source источник


Ответы (2)


Да вроде разумно. Вероятно, процесс B однажды получил немного памяти от ядра, а затем смог удовлетворить все свои потребности в свободном списке. т. е. список свободных страниц никогда не был достаточно большим (или был слишком фрагментирован), чтобы реализация glibc malloc решила вернуть какую-либо из страниц ядру.

Все сводится к шаблонам выделения/освобождения и размерам отображений. Для больших malloc запросов glibc использует mmap(MAP_ANONYMOUS) напрямую, поэтому он может munmap выполнять free.

person Peter Cordes    schedule 16.04.2018

Вы не получите все функции, вызываемые какой-либо программой, используя выборку, вы получите некоторые из вызываемых функций, те, где событие отбирается больше всего, для «циклов: u» вы получите «самый горячий» функции в пользовательском пространстве (без функций ядра).

Рассмотрите возможность использования трассировки вместо выборки, например: «рабочая нагрузка трассировки производительности». Рассмотрите возможность использования с ним обратных трассировок, например, посмотрев обратные трассировки для системного вызова «brk», который делает «ls», мы можем получить:



# perf trace -e brk --call-graph dwarf ls
   0.933 (0.009 ms): ls brk(brk: 0x5577c4683000) = 0x5577c4683000
                     __brk (/usr/lib64/libc-2.26.so)
                     __GI___sbrk (inlined)
                     __GI___default_morecore (inlined)
                     sysmalloc (/usr/lib64/libc-2.26.so)
                     _int_malloc (/usr/lib64/libc-2.26.so)
                     tcache_init.part.5 (/usr/lib64/libc-2.26.so)
                     __GI___libc_malloc (inlined)
                     __GI___strdup (inlined)
                     [0xffff80aa65b9ae49] (/usr/lib64/libselinux.so.1)
                     [0xffff80aa65b9af0e] (/usr/lib64/libselinux.so.1)
                     call_init.part.0 (/usr/lib64/ld-2.26.so)
                     _dl_init (/usr/lib64/ld-2.26.so)
                     _dl_start_user (/usr/lib64/ld-2.26.so)

Это показывает, что в данном случае системный вызов был вызван в ответ на функцию strdup(), которая вызвала функцию malloc(), которая в конечном итоге запросила у ядра ядра больше памяти с помощью вызова brk.

Поиграйте с 'perf trace' еще немного, и вы обнаружите статистику, подобную той, которую предоставляет 'strace', например, сколько раз программа вызывала brk и другие системные вызовы.

person Arnaldo Melo    schedule 17.04.2018