Подтвердить что ты не робот

Графические плагины процессора для Python

Brendan Gregg Графы пламени CPU - это способ визуализации использования ЦП в течение определенного периода времени на основе стеков вызовов.

Его проект FlameGraph github предоставляет независимый от языка способ построения этих графиков:

Для каждого языка FlameGraph требует способа ввода стека в виде таких строк:

grandparent_func;parent_func;func 42

Это означает, что в инструментальной программе наблюдалась работающая функция func, где она была вызвана из parent_func, в свою очередь вызванная из функции верхнего уровня grandparent_func. В нем говорится, что стек вызовов наблюдался 42 раза.

Как я могу собрать информацию о стеке из программ Python и предоставить его FlameGraph?

Для бонусных очков: как это можно расширить, чтобы показать как стек C, так и Python, или даже до ядра на Linux (аналогично некоторым планам Java и node.js Сайт Брендана)?

введите описание изображения здесь

4b9b3361

Ответ 1

Возможно, вы можете попробовать sys.setprofile, который является ядром стандартного профилировщика python profile и cProfile. Этот метод устанавливает привязку к событиям "вызова" и "возврата" каждой функции, включая функции C-API.

Функция системного профиля называется аналогично функции трассировки системы (см. метод settrace()), но она не вызывается для каждой исполняемой строки кода (только при вызове и возврате, но событие возврата сообщается даже тогда, когда исключение имеет был установлен).

Ниже приведен рабочий пример:

from time import clock 
t0 = clock()

def getFun(frame):
    code = frame.f_code 
    return  code.co_name+' in '+code.co_filename+':'+str(code.co_firstlineno)

def trace_dispatch(frame, event, arg):
    if event in [ "c_call" , 'call', 'return', 'c_return']:
        t = int((clock()-t0)*1000)
        f = frame
        stack=[]
        while(f):
          stack.insert( 0,getFun(f) )
          f = f.f_back
        print event, '\t', '; '.join(stack), '; ', t

import sys
sys.setprofile(trace_dispatch)
try:
    execfile('test.py')
finally:
    sys.setprofile(None)

Test.py

def f(x):
    return x+1
def main(x):
    return f(x)
main(10)

Откроется

c_call    0
call      <module> in test.py:2 ;  1
call      <module> in test.py:2; main in test.py:5 ;  1
call      <module> in test.py:2; main in test.py:5; f in test.py:2 ;  5
return    <module> in test.py:2; main in test.py:5; f in test.py:2 ;  8
return    <module> in test.py:2; main in test.py:5 ;  11
return    <module> in test.py:2 ;  14
c_return  18
c_call    21

См. более полную функцию профилирования здесь.

C стека в python

Вы не можете получить доступ к стеку C в интерпретаторе python. Необходимо использовать отладчик или профилировщик, который поддерживает C/С++. Я бы рекомендовал gdb python.