CPU-Flammendiagramme für Python

Lesezeit: 4 Minuten

Benutzer-Avatar
Cross Langshan

Brendan Greggs CPU-Flammendiagramme sind eine Möglichkeit, die CPU-Auslastung über einen bestimmten Zeitraum basierend auf Aufruflisten zu visualisieren.

Seine FlameGraph-Github-Projekt bietet eine sprachunabhängige Möglichkeit, diese Diagramme zu zeichnen:

Für jede Sprache benötigt FlameGraph eine Möglichkeit, Stapeleingaben in Form von Zeilen wie dieser bereitzustellen:

grandparent_func;parent_func;func 42

Dies bedeutet, dass das instrumentierte Programm als laufende Funktion beobachtet wurde funcwoher das aufgerufen wurde parent_funcdie wiederum von der Funktion der obersten Ebene aufgerufen wird grandparent_func. Es heißt, dass der Aufrufstapel 42 Mal beobachtet wurde.

Wie kann ich Stack-Informationen aus Python-Programmen sammeln und sie FlameGraph zur Verfügung stellen?

Für Bonuspunkte: Wie kann das so erweitert werden, dass sowohl der C- als auch der Python-Stack angezeigt werden, oder sogar bis zum Kernel unter Linux (ähnlich wie bei einigen Flammendiagrammen für Java und node.js auf Brendans Website)?

Geben Sie hier die Bildbeschreibung ein

  • Sie sollten in der Lage sein, etwas mit dtrace zu tun – erfordert ein Betriebssystem, das dtrace und eine gepatchte Version von Python unterstützt.

    – ErikR

    17. Januar 2015 um 15:36 Uhr

  • Für das, was es wert ist, übersteigt meiner Meinung nach die Schönheit von Flammendiagrammen ihre Nützlichkeit zum Auffinden von Beschleunigungen, und es gibt einen Weg, der weniger hübsch, aber effektiver ist. Hier erklärt.

    – Mike Dunlavey

    18. Januar 2015 um 1:29 Uhr


  • user5402: Zuletzt habe ich gehört, dass dtrace nicht für den Produktionseinsatz unter Linux geeignet ist

    – Croad Langshan

    18. Januar 2015 um 17:15 Uhr

  • Mike Dunlavey: Ich bin nicht anderer Meinung, aber ich denke, es ist alles in Ordnung, Leistungsprobleme zu finden, also würde ich auch gerne Flammendiagramme ausprobieren

    – Croad Langshan

    18. Januar 2015 um 17:17 Uhr

  • Perf-Skript [-s [Python]:Skript[.py] ], aber der Linux-Kernel sollte mit einem speziellen Flag (NO_LIBPYTHON=0) wie hier beschrieben gebaut werden askubuntu.com/questions/577768/…

    – VelikiiNehochuha

    2. Mai 2016 um 22:12 Uhr

Benutzer-Avatar
gdlmx

Vielleicht kannst du es versuchen sys.setprofiledas ist der Kern für den Standard-Python-Profiler profile und cProfile. Diese Methode setzt einen Haken zu den “call”- und “return”-Ereignissen jeder Funktion, einschließlich jener Funktionen der C-API.

Die Profilfunktion des Systems wird ähnlich wie die Trace-Funktion des Systems aufgerufen (siehe settrace()), aber sie wird nicht für jede ausgeführte Codezeile aufgerufen (nur bei Aufruf und Rückgabe, aber das Rückgabeereignis wird auch dann gemeldet, wenn eine Ausnahme aufgetreten ist einstellen).

Unten ist ein funktionierendes Beispiel:

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)

Dies wird ausgedruckt

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

Sehen Sie sich eine umfassendere Profilerstellungsfunktion an hier.

C-Stapel in Python

Sie können innerhalb des Python-Interpreters nicht auf den C-Stack zugreifen. Es ist erforderlich, einen Debugger oder Profiler zu verwenden, der C/C++ unterstützt. Ich würde empfehlen gdb-python.

  • Vielen Dank für all diese Informationen – das ist hilfreich

    – slashdottir

    4. Mai 2016 um 22:59 Uhr

  • Das ist großartig, aber ich denke, das tut es nicht ziemlich Beantworten Sie die Frage aus dem trivialen, aber wichtigen Grund, dass sie meiner Meinung nach keine Ausgabe in der Form erzeugt, die FlameGraph möchte

    – Croad Langshan

    8. Juni 2016 um 22:37 Uhr

  • @gdlmx Richtig. Ich auch nicht

    – Croad Langshan

    14. Juni 2016 um 20:46 Uhr


Pyflame unterstützt das Zeichnen von Flammendiagrammen in zwei Formaten (entweder die ‘traditionelle’ Form wie in der Frage oder die ‘seitlichen’ Flammendiagramme von Chrome unter Verwendung von Chrom selbst).

Aus https://github.com/uber/pyflame:

# Attach to PID 12345 and profile it for 1 second
pyflame -p 12345

# Attach to PID 768 and profile it for 5 seconds, sampling every 0.01 seconds
pyflame -s 5 -r 0.01 -p 768

# Run py.test against tests/, emitting sample data to prof.txt
pyflame -o prof.txt -t py.test tests/

1370200cookie-checkCPU-Flammendiagramme für Python

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy