$ time foo
real 0m0.003s
user 0m0.000s
sys 0m0.004s
$
Was bedeuten "real", "user" und "sys" in der Ausgabe der Zeit?
Welches ist beim Benchmarking meiner App sinnvoll?
unix
time
benchmarking
Rayryeng
quelle
quelle
time
, lassen Sie es etwas tun, das mindestens eine Sekunde dauert.time
ein Bash-Schlüsselwort ist. So Typisierungman time
ist nicht Ihnen eine man - Seite für die Bash gebentime
, sondern es gibt das Manpage/usr/bin/time
. Das hat mich gestolpert.Antworten:
Real-, User- und Sys-Prozesszeitstatistiken
Eines dieser Dinge ist nicht wie das andere. Real bezieht sich auf die tatsächlich verstrichene Zeit; Benutzer und System beziehen sich auf die CPU-Zeit, die nur vom Prozess verwendet wird.
Real ist die Wanduhrzeit - Zeit vom Beginn bis zum Ende des Anrufs. Dies ist die gesamte verstrichene Zeit, einschließlich der von anderen Prozessen verwendeten Zeitscheiben und der Zeit, die der Prozess blockiert verbringt (z. B. wenn er auf den Abschluss der E / A wartet).
Benutzer ist die CPU-Zeit, die im Benutzermoduscode (außerhalb des Kernels) innerhalb des Prozesses verbracht wird. Dies ist nur die tatsächliche CPU-Zeit, die zur Ausführung des Prozesses verwendet wird. Andere Prozesse und die Zeit, die der Prozess blockiert verbringt, zählen nicht für diese Zahl.
Sys ist die CPU-Zeit, die im Kernel innerhalb des Prozesses verbracht wird. Dies bedeutet, dass die CPU-Zeit, die für Systemaufrufe im Kernel aufgewendet wird, ausgeführt wird , im Gegensatz zum Bibliothekscode, der noch im Benutzerbereich ausgeführt wird. Wie bei 'Benutzer' ist dies nur die vom Prozess verwendete CPU-Zeit. Im Folgenden finden Sie eine kurze Beschreibung des Kernel-Modus (auch als "Supervisor" -Modus bezeichnet) und des Systemaufrufmechanismus.
User+Sys
Hier erfahren Sie, wie viel CPU-Zeit Ihr Prozess tatsächlich verwendet hat. Beachten Sie, dass dies für alle CPUs gilt. Wenn der Prozess also mehrere Threads hat (und dieser Prozess auf einem Computer mit mehr als einem Prozessor ausgeführt wird), kann er möglicherweise die vonReal
(normalerweise auftretende) Wanduhrzeit überschreiten . Beachten Sie, dass in der Ausgabe diese Zahlen die umfassenUser
undSys
Zeit aller Child - Prozesse (und ihre Nachkommen) , als auch , wenn sie erhoben wurden , könnten zB durchwait(2)
oderwaitpid(2)
, obwohl die zugrunde liegenden Systemaufrufe die Statistiken für den Prozess und seine Kinder getrennt zurück.Ursprung der Statistiken von
time (1)
Die von gemeldeten Statistiken
time
stammen aus verschiedenen Systemaufrufen. 'User' und 'Sys' kommen je nach System vonwait (2)
( POSIX ) odertimes (2)
( POSIX ). 'Real' wird aus einer Start- und Endzeit berechnet, die aus demgettimeofday (2)
Anruf ermittelt wurde. Abhängig von der Version des Systems können auch verschiedene andere Statistiken wie die Anzahl der Kontextwechsel erfasst werdentime
.Auf einem Multiprozessor-Computer kann ein Multithread-Prozess oder ein Prozess, der untergeordnete Elemente teilt, eine verstrichene Zeit haben, die kleiner als die gesamte CPU-Zeit ist, da verschiedene Threads oder Prozesse parallel ausgeführt werden können. Außerdem stammen die gemeldeten Zeitstatistiken aus unterschiedlichen Quellen, sodass Zeiten, die für sehr kurze Aufgaben aufgezeichnet wurden, Rundungsfehlern unterliegen können, wie das Beispiel auf dem Originalplakat zeigt.
Eine kurze Einführung in den Kernel vs. User-Modus
Unter Unix oder einem Betriebssystem mit geschütztem Speicher bezieht sich der Modus "Kernel" oder "Supervisor" auf einen privilegierten Modus , in dem die CPU arbeiten kann. Bestimmte privilegierte Aktionen, die die Sicherheit oder Stabilität beeinträchtigen können, können nur ausgeführt werden, wenn die CPU in Betrieb ist dieser Modus; Diese Aktionen stehen dem Anwendungscode nicht zur Verfügung. Ein Beispiel für eine solche Aktion könnte die Manipulation der MMU sein , um Zugriff auf den Adressraum eines anderen Prozesses zu erhalten. Normalerweise kann der Benutzermoduscode dies nicht tun (aus gutem Grund), obwohl er gemeinsam genutzten Speicher vom Kernel anfordern kann , was möglich istdurch mehr als einen Prozess gelesen oder geschrieben werden. In diesem Fall wird der gemeinsam genutzte Speicher über einen sicheren Mechanismus explizit vom Kernel angefordert, und beide Prozesse müssen explizit eine Verbindung zu ihm herstellen, um ihn verwenden zu können.
Der privilegierte Modus wird normalerweise als "Kernel" -Modus bezeichnet, da der Kernel von der in diesem Modus ausgeführten CPU ausgeführt wird. Um in den Kernelmodus zu wechseln, müssen Sie eine bestimmte Anweisung (oft als Trap bezeichnet ) ausgeben , die die CPU auf die Ausführung im Kernelmodus umschaltet und Code von einem bestimmten Ort in einer Sprungtabelle ausführt. Aus Sicherheitsgründen können Sie nicht in den Kernelmodus wechseln und beliebigen Code ausführen. Die Traps werden über eine Adresstabelle verwaltet, in die nur geschrieben werden kann, wenn die CPU im Supervisor-Modus ausgeführt wird. Sie fangen mit einer expliziten Trap-Nummer und die Adresse wird in der Sprungtabelle nachgeschlagen. Der Kernel hat eine endliche Anzahl kontrollierter Einstiegspunkte.
Die 'System'-Aufrufe in der C-Bibliothek (insbesondere die in Abschnitt 2 der Manpages beschriebenen) verfügen über eine Benutzermodus-Komponente, die Sie tatsächlich von Ihrem C-Programm aus aufrufen. Hinter den Kulissen können sie einen oder mehrere Systemaufrufe an den Kernel senden, um bestimmte Dienste wie E / A auszuführen, aber sie haben auch weiterhin Code, der im Benutzermodus ausgeführt wird. Es ist auch durchaus möglich, von jedem Benutzerbereichscode aus direkt einen Trap für den Kernelmodus auszugeben, obwohl Sie möglicherweise einen Ausschnitt der Assemblersprache schreiben müssen, um die Register für den Aufruf korrekt einzurichten.
Mehr über 'sys'
Es gibt Dinge, die Ihr Code im Benutzermodus nicht tun kann - beispielsweise das Zuweisen von Speicher oder den Zugriff auf Hardware (Festplatte, Netzwerk usw.). Diese stehen unter der Aufsicht des Kernels und können von ihm allein ausgeführt werden. Einige Operationen wie
malloc
oderfread
/fwrite
rufen diese Kernelfunktionen auf und das zählt dann als 'sys'-Zeit. Leider ist es nicht so einfach wie "jeder Anruf bei malloc wird in 'sys' Zeit gezählt". Der Aufrufmalloc
von führt eine eigene Verarbeitung durch (immer noch in der 'Benutzer'-Zeit gezählt) und ruft dann irgendwo auf dem Weg die Funktion im Kernel auf (in' sys'-Zeit gezählt). Nach der Rückkehr vom Kernel-Aufruf bleibt in 'user' noch etwas Zeitmalloc
wird zu Ihrem Code zurückkehren. Wann der Wechsel stattfindet und wie viel davon im Kernel-Modus ausgegeben wird, kann man nicht sagen. Dies hängt von der Implementierung der Bibliothek ab. Es könnten auch andere scheinbar unschuldige Funktionenmalloc
und dergleichen im Hintergrund verwendet werden, die dann wieder etwas Zeit in 'sys' haben werden.quelle
Um die akzeptierte Antwort zu erweitern , wollte ich nur einen weiteren Grund
real
angeben, warum ≠user
+sys
.Beachten Sie, dass dies
real
die tatsächlich verstrichene Zeit darstellt, währenduser
und diesys
Werte die CPU-Ausführungszeit darstellen. Infolgedessen kann auf einem Multicore-System dieuser
und / odersys
Zeit (sowie deren Summe) tatsächlich die Echtzeit überschreiten . In einer Java-App, die ich für die Klasse ausführe, erhalte ich beispielsweise folgende Werte:quelle
real
Überschreitunguser
undsys
Gesamtheit? Betriebssystem-Overhead wie Thread-Kontextwechsel kann sein?• real : Die tatsächliche Zeit, die für die Ausführung des Prozesses von Anfang bis Ende aufgewendet wurde, als würde sie von einem Menschen mit einer Stoppuhr gemessen
• Benutzer : Die kumulierte Zeit, die alle CPUs während der Berechnung verbracht haben
• sys : Die kumulierte Zeit, die alle CPUs für systembezogene Aufgaben wie die Speicherzuweisung aufgewendet haben.
quelle
sys
Wird die CPU-Zeit für Systemaufrufe (und Seitenfehlerbehandlungsroutinen?) aufgewendet?real
wird oft als "Wanduhr" bezeichnet.Minimal ausführbare POSIX C-Beispiele
Um die Dinge konkreter zu machen, möchte ich einige extreme Fälle
time
mit einigen minimalen C-Testprogrammen veranschaulichen .Alle Programme können kompiliert und ausgeführt werden mit:
und wurden in Ubuntu 18.10, GCC 8.2.0, glibc 2.28, Linux-Kernel 4.18, ThinkPad P51-Laptop, Intel Core i7-7820HQ-CPU (4 Kerne / 8 Threads), 2x Samsung M471A2K43BB1-CRC-RAM (2x 16GiB) getestet.
Schlaf
Nicht beschäftigter Schlaf zählt weder in
user
nochsys
nurreal
.Zum Beispiel ein Programm, das eine Sekunde lang schläft:
GitHub stromaufwärts .
gibt so etwas aus wie:
Gleiches gilt für Programme, die auf E / A blockiert sind und verfügbar werden.
Das folgende Programm wartet beispielsweise darauf, dass der Benutzer ein Zeichen eingibt und die Eingabetaste drückt:
GitHub stromaufwärts .
Und wenn Sie ungefähr eine Sekunde warten, wird genau wie im Schlafbeispiel Folgendes ausgegeben:
Aus diesem Grund
time
können Sie zwischen CPU- und E / A-gebundenen Programmen unterscheiden: Was bedeuten die Begriffe "CPU-gebunden" und "E / A-gebunden"?Mehrere Threads
Im folgenden Beispiel werden
niters
Iterationen nutzloser, rein CPU-gebundener Arbeit annthreads
Threads ausgeführt:GitHub Upstream + Plotcode .
Dann zeichnen wir wall, user und sys als Funktion der Anzahl der Threads für feste 10 ^ 10 Iterationen auf meiner 8-Hyperthread-CPU:
Plotdaten .
Aus der Grafik sehen wir Folgendes:
Bei einer CPU-intensiven Single-Core-Anwendung sind Wand und Benutzer ungefähr gleich
Bei 2 Kernen beträgt der Benutzer ungefähr 2x Wand, was bedeutet, dass die Benutzerzeit über alle Threads hinweg gezählt wird.
Benutzer im Grunde verdoppelt, und während Wand gleich blieb.
Dies setzt bis zu 8 Threads fort, was meiner Anzahl von Hyperthreads in meinem Computer entspricht.
Nach 8 beginnt auch die Wand zu wachsen, da wir keine zusätzlichen CPUs haben, um in einer bestimmten Zeit mehr Arbeit zu leisten!
Das Verhältnis Plateaus an diesem Punkt.
Beachten Sie, dass dieses Diagramm nur so klar und einfach ist, weil die Arbeit rein CPU-gebunden ist: Wenn es speichergebunden wäre, würden wir mit weniger Kernen viel früher einen Leistungsabfall erzielen, da die Speicherzugriffe einen Engpass darstellen würden, wie unter Was gezeigt bedeuten die Begriffe "CPU-gebunden" und "E / A-gebunden"?
Sys schwere Arbeit mit
sendfile
Die schwerste Systemauslastung, die ich finden konnte, war die Verwendung von
sendfile
, die einen Dateikopiervorgang im Kernelbereich ausführt : Kopieren Sie eine Datei auf eine vernünftige, sichere und effiziente WeiseAlso stellte ich mir vor, dass dieser In-Kernel
memcpy
eine CPU-intensive Operation sein wird.Zuerst initialisiere ich eine große 10GiB-Zufallsdatei mit:
Führen Sie dann den Code aus:
GitHub stromaufwärts .
was im Grunde meistens Systemzeit wie erwartet gibt:
Ich war auch neugierig, ob ich
time
zwischen Systemaufrufen verschiedener Prozesse unterscheiden würde, also versuchte ich:Und das Ergebnis war:
Die Systemzeit ist für beide ungefähr gleich wie für einen einzelnen Prozess, aber die Wandzeit ist größer, da die Prozesse wahrscheinlich um den Lesezugriff auf die Festplatte konkurrieren.
Es scheint also tatsächlich zu berücksichtigen, welcher Prozess eine bestimmte Kernelarbeit gestartet hat.
Bash-Quellcode
Wenn Sie nur
time <cmd>
unter Ubuntu arbeiten, verwenden Sie das Schlüsselwort Bash, wie aus folgendem ersichtlich ist:welche Ausgänge:
Also grep wir die Quelle im Bash 4.19-Quellcode für die Ausgabezeichenfolge:
Dies führt uns zur Funktion execute_cmd.c
time_command
, die Folgendes verwendet:gettimeofday()
undgetrusage()
wenn beide verfügbar sindtimes()
AndernfallsAll dies sind Linux-Systemaufrufe und POSIX-Funktionen .
GNU Coreutils Quellcode
Wenn wir es nennen als:
Dann wird die Implementierung von GNU Coreutils verwendet.
Dieser ist etwas komplexer, aber die relevante Quelle scheint bei resuse.c zu sein und es tut:
wait3
Aufruf, falls verfügbartimes
undgettimeofday
sonstquelle
Real zeigt die gesamte Bearbeitungszeit für einen Prozess an. während Benutzer die Ausführungszeit für benutzerdefinierte Anweisungen anzeigt und Sys für die Ausführung von Systemaufrufen vorgesehen ist!
Echtzeit beinhaltet auch die Wartezeit (die Wartezeit für E / A usw.)
quelle