2009-01-20 10 views
19

Während ich an einem Universitätsprojekt arbeitete, benutzte ich einen projektinternen Profiler, der von einem älteren Studenten erstellt wurde. Er war sehr einfach, aber gut genug, da seine Aufgabe darin bestand, Zeiten zwischen zwei Punkten des Codes zu subtrahieren und Statistiken zu geben.Wie funktionieren Code-Profiler?

Nun, wie funktioniert ein professioneller Profiler? Bearbeitet es den Code vor, um Prüfpunkte oder ähnliches einzufügen? Liest es den Binärcode mit Debug-Daten, um herauszufinden, wo eine Funktion aufgerufen wird?

Danke.

Antwort

22

Es gibt viele verschiedene Profiler, die auf verschiedene Arten funktionieren.

Häufig verwendete Profilometer einfach das laufende Programm untersuchen regelmäßig, um zu sehen, welche Montageanleitung gerade ausgeführt wird (den Programmzähler) und die die aktuelle Funktion aufgerufenen Routinen (der Call-Stack). Diese Art von Sampling Profiler kann mit Standard-Binärdateien arbeiten, sind aber nützlicher, wenn Sie Debugging-Symbole haben, um Codezeilen auszuwerten Adressen im Programm.

Neben regelmäßigen Stichproben können Sie nach einer bestimmten Anzahl von Ereignissen (z. B. Cache-Misses) auch Prozessorleistungsindikatoren verwenden, um festzustellen, welche Teile Ihres Programms aufgrund von Speicherzugriffen langsamer werden.

Andere Profilometer beinhalten Neukompilierung die Programmbefehle einzufügen (bekannt als Instrumentierungs) zu zählen, wie oft jede kontinuierliche Reihe von Anweisungen (Basisblocks) ausgeführt werden, oder vielleicht sogar die Reihenfolge aufzeichnen, in den Basisblocks ausgeführt werden, oder Zeichne den Inhalt von Variablen an bestimmten Stellen auf.

Der Instrumentierungsansatz kann Ihnen die ganze Präzision und Daten geben, die Sie wünschen, aber wird das Programm verlangsamen und das wird seine Leistungsmerkmale ändern. Im Gegensatz dazu können Sie bei Sampling-basierten Ansätzen die Auswirkungen auf die Leistung anhand der Zeit, die Sie für die Ausführung des Programms benötigen, an die Genauigkeit der Profildaten anpassen, die Sie erhalten.

2

es von der Art des Codes hängt analysierten zum Beispiel .NET CLR facility für die Code-Profilers liefert. Beim Umgang mit verwaltetem Code ist es möglich, Zwischencode neu zu schreiben, um benutzerdefinierte Hooks zu injizieren. Außerdem können Sie Stack-Trace der Anwendungen analysieren. Das Betriebssystem kann Mittel zur Profilerstellung bereitstellen, beispielsweise Windows performance counters. Bei Embedded-Code können Sie die zugrunde liegende Hardware emulieren/ersetzen, um die Systemleistung effektiv zu überwachen.

+0

Was meinen Sie mit "verwaltetem Code"? – tunnuz

+0

http://en.wikipedia.org/wiki/Managed_code – aku

13

Es gibt zwei gängige Profilierungsstrategien (für VM-basierte Sprachen sowieso): Instrumentierung und Probenahme.

Besetzung fügt Checkpoints und informiert den Profiler jedes Mal, wenn ein Verfahren startet und beendet. Dies kann durch den JIT/Interpreter oder durch eine Post-Normal-Kompilier- aber Vor-Ausführungsphase erfolgen, die nur die ausführbare Datei ändert. Dies kann sich sehr stark auf die Leistung auswirken (wodurch eventuelle Timingergebnisse verfälscht werden). Es ist jedoch gut, genaue Zahlen zu erhalten.

Sampling fragt die VM in regelmäßigen Abständen, was die Stack-Trace wie für alle Threads aussieht, und aktualisiert seine Statistik auf diese Weise. Dies wirkt sich typischerweise weniger auf die Leistung aus, führt jedoch zu weniger genauen Anrufzählungen.

+1

IMO, ist die beste Methode, eine kleinere Anzahl von Stack-Traces zu erfassen. Dann melden sie für jedes Heft/Instrument den% der Proben, die es enthalten. Die besten zu untersuchenden Punkte sind in dieser Liste, selbst wenn die Zeitschätzungen grob sind. Dies ist nützlicher als das Funktionstiming. –

0

für gprof in * nix, bei der Kompilierung und Link Zeit durch die -pg verwenden, einige zusätzliche Code wird in den Objektcode injiziert. Anschließend wird durch Ausführen von gprof eine Berichtsdatei mit dem injizierten Code generiert.

2

Wie Jon Skeet oben geschrieben hat, gibt es zwei Strategien: Instrumentierung und Sampling.

Die Instrumentierung erfolgt sowohl manuell als auch automatisch. Im manuellen Fall: Der Entwickler fügt Code manuell ein, um den Anfang/das Ende einer Region von Code von Interesse zu verfolgen. Zum Beispiel ein einfacher "StartTimer" und "EndTimer". Einige Profiler-Tools können dies auch automatisch tun. Dazu muss der Profiler eine statische Analyse des Codes durchführen, d. H. Er analysiert den Code und identifiziert wichtige Prüfpunkte wie den Start/das Ende einer bestimmten Methode. Dies ist am einfachsten mit Sprachen, die Reflektion unterstützen (z. B. jede .net-Sprache). Mithilfe von 'reflection' kann der Profiler den gesamten Quellcode-Baum (zusammen mit Call-Graphen) rekonstruieren.

Die Abtastung erfolgt durch den Profiler und es wird in den Binärcode hineingeschaut. Der Profiler kann auch Techniken wie Hooks oder Trap Windows Ereignisse/Nachrichten zum Zwecke der Profilerstellung.

Sowohl Instrumentations- als auch Stichprobenmethoden haben ihre eigenen Gemeinkosten. Die Menge an Kopf hängt ab - z.B. Wenn die Abtastfrequenz auf hohe Werte eingestellt ist, kann das Profiling selbst erheblich zur gemeldeten Leistung beitragen.

Instrumentierung Vs Probenahme: Es ist nicht wie man ist besser als der andere Ansatz. Beide haben ihren Platz.

Der beste Ansatz ist, mit einem Sampling-basierten Profiler zu beginnen und die gesamte Systemebene zu betrachten. Dadurch wird der Sampler ausgeführt und die systemweite Ressourcennutzung angezeigt: Speicher, Festplatte, Netzwerk, CPU.

Aus dem oben genannten identifizieren die Ressourcen, die erstickt werden.

Mit den obigen Informationen können Sie Ihrem Code nun Instrumente hinzufügen, um den Schuldigen genau zu lokalisieren. Wenn zum Beispiel Speicher die am häufigsten verwendete Ressource ist, wird es helfen, Ihren Speicherzuordnungscode zu instrumentieren. Beachten Sie, dass Sie sich bei der Instrumentierung auf einen bestimmten Bereich Ihres Codes konzentrieren.