Der Start meiner Bash-Shell dauert bis zu 3-4 Sekunden. Wenn ich sie --norc
damit starte, wird sie sofort ausgeführt.
Ich habe mit dem "Profiling" begonnen /etc/bash.bashrc
und Anweisungen ~/.bashrc
manuell eingefügt return
und nach Geschwindigkeitsverbesserungen gesucht, aber es ist kein quantitativer Prozess und nicht effizient.
Wie kann ich meine Bash-Skripte profilieren und sehen, welche Befehle am meisten Zeit zum Starten benötigen?
time bash -c 'exit'
undtime bash -i -c 'exit'
und können mit--norc
und spielen--noprofile
.Antworten:
Wenn Sie über GNU
date
(oder eine andere Version, die Nanosekunden ausgeben kann) verfügen, tun Sie dies zu Beginn von/etc/bash.bashrc
(oder wo immer Sie eine Ablaufverfolgung in einem Bash-Skript beginnen möchten):hinzufügen
am Ende
~/.bashrc
(oder am Ende des Abschnitts eines Bash-Skripts, dessen Ablaufverfolgung beendet werden soll). Das\011
ist ein oktales Tabulatorzeichen.Sie sollten ein Ablaufverfolgungsprotokoll erhalten
/tmp/bashstart.PID.log
, das den Zeitstempel von Sekunden und Nanosekunden jedes ausgeführten Befehls anzeigt. Der Unterschied von einem Zeitpunkt zum nächsten ist die Zeit, die der dazwischenliegende Schritt benötigt hat.Wenn Sie die Dinge eingrenzen, können Sie sich
set -x
später undset +x
früher bewegen (oder mehrere Abschnitte von Interesse selektiv einklammern).Obwohl es nicht so feinkörnig ist wie
date
die Nanosekunden von GNU , enthält Bash 5 eine Variable, die die Zeit in Mikrosekunden angibt. Die Verwendung erspart Ihnen das Laichen einer externen ausführbaren Datei für jede Zeile und funktioniert auf Macs oder anderen Geräten ohne GNUdate
- solange Sie natürlich über Bash 5 verfügen. Ändern Sie die Einstellung vonPS4
:Wie von @pawamoy hervorgehoben, können Sie
BASH_XTRACEFD
die Ausgabe des Trace an einen separaten Dateideskriptor senden, wenn Sie über Bash 4.1 oder höher verfügen. Aus dieser Antwort :Dadurch wird die Trace - Ausgabe in die Datei gehen
command.txt
verlassenstdout
undstdout
ausgegeben wird normalerweise (oder separat umgeleitet werden).quelle
exec
sollte fd2 auf normal zurücksetzen, damit Sie die Eingabeaufforderung zurückerhalten.\D{...}
inPS4
können völlig beliebige Zeichenfolgen im Zeitformat erweitert werden, ohne dass der Leistungsaufwand beim Startendate
als Unterprozess steigt.date
versteht GNU%N
und Bash 4.2 nicht (weilstrftime(3)
nicht) auf GNU-System - so willkürlich mit Grenzen. Ihr Standpunkt zu Leistung im Vergleich zur Auflösung ist gut, und ein Benutzer sollte die Wahl mit Bedacht treffen, wobei zu berücksichtigen ist, dass der Leistungseinbruch nur während des Debuggens vorübergehend ist (und nur dann, wenn erset -x
wirksam ist).Profilerstellung Bash (4 Antworten)
Bearbeiten: März 2016
script
Methode hinzufügenLesen Sie dies und da die Profilerstellung ein wichtiger Schritt ist, habe ich einige Tests und Nachforschungen zu dieser gesamten SO-Frage durchgeführt und bereits Antworten veröffentlicht.
Es gibt 4+ Antworten:
Der letzte Einsatz
script
,scriptreplay
und Timing - Datei .Zum Schluss noch ein kleiner Leistungsvergleich.
Verwenden
set -x
unddate
aber mit begrenzten GabelnNehmen Sie von der Idee von @ DennisWilliamson, aber mit der folgenden Syntax gibt es nur eine anfängliche Verzweigung zu 3 Befehlen:
Dies wird
date
nur einmal ausgeführt. Es gibt eine kurze Demo / einen Test, um zu zeigen, wie es funktioniert:Beispielskript:
Durch Ausführen dieses Skripts erstellen Sie zwei Dateien:
/tmp/sample-XXXX.log
und/tmp/sample-XXXX.tim
(wobei XXXX die Prozess-ID des ausgeführten Skripts ist).Sie können sie präsentieren mit
paste
:Oder Sie können sogar die Diff-Zeit berechnen:
oder auf zwei Spalten:
Darf rendern:
Verwenden
trap debug
und/proc/timer_list
auf aktuellen GNU / Linux-Kerneln ohne Gabeln .Unter den neuesten Kerneln von GNU / Linux finden Sie möglicherweise eine
/proc
Datei mit dem Namentimer_list
:Wobei die aktuelle Zeit die Summe von
5461935212966259 + 1383718821564493249
, aber in Nanosekunden ist.Für die Berechnung der verstrichenen Zeit ist es daher nicht erforderlich, den Offset zu kennen.
Für diese Art von Jobs habe ich elap.bash (V2) geschrieben , die mit der folgenden Syntax bezogen werden:
oder
(Siehe Kommentare für die vollständige Syntax)
Sie können also einfach diese Zeile oben in Ihr Skript einfügen:
Kleine Probe:
Rendern Sie auf meinem Host:
Verwenden Sie
trap2
anstelle vontrap
als Argument für den Quellbefehl:Rendert zwei Spalten als letzten Befehl und als Summe :
Verwenden von
strace
Ja,
strace
könnte den Job machen:Aber es könnte eine Menge Zeug machen!
Verwenden eines eingeschränkteren Befehls:
Wird leichteres Holz wegwerfen:
Je nachdem, wonach Sie suchen, sind Sie möglicherweise restriktiver:
Es wird etwas schwieriger sein, sie zu lesen:
Das ursprüngliche Bash-Skript ist in diesem ...
Unter Verwendung
script
,scriptreplay
und Timing - DateiAls Teil von BSD Utils ist
script
(undscriptreplay
) ein sehr altes Tool, mit dem Bash mit sehr geringem Platzbedarf profiliert werden kann.Wird herstellen:
und generieren Sie zwei Dateien:
Datei
script.log
enthält alle Spuren undscript.tim
ist die Timing-Datei :Sie können die Gesamtzeitausführung mit der ersten und letzten Zeile der Protokolldatei und / oder durch Zusammenfassen der Zeiten in der Zeitdatei anzeigen:
In der Timing-Datei ist der zweite Wert die Anzahl der nächsten Bytes in der entsprechenden Protokolldatei. Dies können Sie die Fähigkeit der Wiedergabe von Protokolldatei optional mit einem Beschleunigungsfaktor :
oder
oder
Das Anzeigen von Zeiten und Befehlen nebeneinander ist ebenfalls etwas komplexer:
Tests und Schlussfolgerung
Um Tests durchzuführen, habe ich das zweite Beispiel bei Bash Complex Hello World heruntergeladen. Die Ausführung dieses Skripts auf meinem Host dauert ca. 0,72 Sekunden.
Ich habe oben im Skript Folgendes hinzugefügt:
nach
elap.bash
Funktionvon
set -x
undPS4
by
set -x
und Initial Fork to Long Exec Befehlvon
script
(undset +x
)Mal
Und vergleichen Sie die Ausführungszeiten (auf meinem Host):
Ausgänge
nach
elap.bash
Funktionvon
set -x
undPS4
by
set -x
und initial fork to long exec befehl (und mein zweites beispielskriptpaste
)durch
strace
durch
script
Fazit
Gut! Wenn meine reine Bash bei jedem Befehl schneller ist als das bisherige Gabeln, impliziert meine reine Bash einige Operationen für jeden Befehl.
Die Art und Weise, einen unabhängigen Prozess für die Protokollierung und Speicherung einzurichten, ist deutlich effizienter.
strace
ist ein interessanter Weg, detaillierter, aber schwer zu lesen.script
, mitscriptreplay
und Beschleunigungsfaktor ist auch sehr schön, nicht die gleiche Präzision wie diese basiert auf Konsolenaustausch anstelle von Prozessausführung, aber sehr leicht und effizient (nicht das gleiche Ziel, nicht die gleiche Verwendung).Schließlich denke ich, dass die effizientere Lesbarkeit und Leistung
set + 1 fork
die erste dieser Antwort ist, aber in Ordnung, je nach Einzelfall, verwende ich sie irgendwannstrace
und / oderscript
auch.quelle
exec {BASH_XTRACEFD}>
stattdessenexec 3>&2 2>
die Protokolldatei nur mit der Trace-Protokollierungsausgabe und nicht mit anderen stderr-Ausgaben füllen.script.sh
ich kann einfachbash -c "exec {BASH_XTRACEFD}> >(tee trace.log | sed -u 's/^.*$//' | date -f - +%s.%N > timing.log); set -x; . script.sh
Profildaten erstellen und abrufen, ohne sie zu ändernscript.sh
. Wenn keine Genauigkeit von weniger als einer Sekunde benötigt wird, gefällt mir,bash -c "exec {BASH_XTRACEFD}>trace.log; set -x; PS4='+\t'; . script.sh
welche Zeit jede Trace-Linie mit zweiter Genauigkeit und ohne bisheriges Gabeln stempelt (geringer Overhead).Es ist oft hilfreich, die Systemaufrufe zu verfolgen
Aus dem Handbuch:
-c Zählen Sie Zeit, Aufrufe und Fehler für jeden Systemaufruf und melden Sie eine Zusammenfassung beim Beenden des Programms.
-f Untergeordnete Prozesse verfolgen ...
Dies ist nicht genau das, was Sie wollen und was ein linienorientierter Profiler Ihnen zeigen würde, aber es hilft normalerweise, Hotspots zu finden.
quelle
Sie können sich den
trap
Befehl mit der DEBUG- Bedingung ansehen . Es gibt eine Möglichkeit, einen oder mehrere Befehle festzulegen, die zusammen mit Ihren Befehlen ausgeführt werden sollen. Siehe die Anmerkungen zur Antwort.quelle
help trap
: "Wenn ein SIGNAL_SPEC DEBUG ist, wird ARG vor jedem einfachen Befehl ausgeführt." In Bash 3.2 steht "nach". Das ist ein Tippfehler. Ab Bash 2.05b wird es bereits ausgeführt. Referenz : "Dieses Dokument beschreibt die Änderungen zwischen dieser Version, bash-2.05b-alpha1, und der vorherigen Version, bash-2.05a-release. ... 3. Neue Funktionen in Bash ... w. Die DEBUG-Falle ist jetzt laufen , bevor einfache Befehle, ((...)) Befehle, [[...]] bedingte Befehle und für ((...)) Schleifen“ . Das Testen in jeder Version bestätigt, dass es vorher ist .Time, xtrace, bash -x
set -x
undset+x
( http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html ) bleiben die orthodoxe Methode zum Debuggen eines Skripts.Um unseren Horizont zu erweitern, ist es dennoch möglich, ein System zum Debuggen und Profilieren zu überprüfen, das für die üblichen Linux-Programme verfügbar ist [hier eine der Listen] , z. B. sollte es ein nützliches System sein , das auf valgrind basiert, insbesondere um Speicher oder sysprof to profile zu debuggen das ganze System:
Für sysprof:
Und danach wählen Sie den Zweig der Unterprozesse aus, die Sie interessant finden.
Für Valgrind:
Mit etwas mehr Fitnessstudio scheint es möglich zu sein, Valgrind einige Programme sichtbar zu machen , die wir normalerweise über Binärdateien installieren (z . B. OpenOffice ).
Es ist möglich , aus dem lesen FAQ von valgrind , die
Valgrind
die wird das Profil Kind - Prozesse , wenn explizit angefordert.Dies wird bei aktivierter Option durchgeführt
Zusätzliche Referenzen:
quelle
Dieser Beitrag von Alan Hargreaves beschreibt die Methode zum Profilieren des Bourne-Shell-Skripts mithilfe des DTrace-Anbieters. Soweit ich weiß, funktioniert dies mit Solaris und OpenSolaris (siehe: / bin / sh DTrace Provider ).
Geben Sie also das folgende dtrace-Skript an (
sh_flowtime.d
bei GH basierend auf dem Original ):Sie können den Funktionsfluss einschließlich der Deltazeiten verfolgen.
Beispielausgabe:
Dann mit
sort -nrk7
Befehl die Ausgabe sortieren, um die am meisten konsumierenden Anrufe anzuzeigen.Mir sind keine Anbietersonden bekannt, die für andere Shells verfügbar sind. Machen Sie also einige Nachforschungen (GitHub-Suche?) Oder wenn Sie etwas Zeit investieren möchten, können Sie diese anhand des vorhandenen sh- Beispiels schreiben : (siehe: So aktivieren Sie sh DTrace-Anbieter? ).
quelle