Wilt u weten hoe lang een proces duurt en nog veel meer? Het Linux time
commando retourneert tijdstatistieken, waardoor u coole inzichten krijgt in de bronnen die door uw programma’s worden gebruikt.
tijd heeft veel familieleden
Er zijn veel Linux-distributies en verschillende Unix-achtige besturingssystemen. Elk van deze heeft een standaard opdrachtshell. De meest voorkomende standaardshell in moderne Linux-distributies is de bash-shell. Maar er zijn nog veel meer, zoals de Z-schaal (zsh) en de Korn-schaal (ksh).
Al deze schelpen bevatten hun eigen time
commando, ofwel als een ingebouwd commando of als een gereserveerd woord. Als je typt time
in een terminalvenster zal de shell zijn interne commando uitvoeren in plaats van de GNU te gebruiken time
binair bestand dat wordt geleverd als onderdeel van uw Linux-distributie.
We willen de GNU-versie van time
omdat het meer opties heeft en flexibeler is.
Welke tijd zal lopen?
U kunt controleren welke versie wordt uitgevoerd door de type
opdracht. type
zal u laten weten of de shell uw instructie zelf zal afhandelen, met zijn interne routines, of deze zal doorgeven aan het binaire GNU-bestand.
typ het woord in een terminalvenster type
, een spatie en dan het woord time
en druk op Enter.
type time
We kunnen dat zien in de bash-schaal time
is een gereserveerd woord. Dit betekent dat Bash zijn internetime
routines standaard.
type time
In de Z-shell (zsh) time
is een gereserveerd woord, dus de interne shell-routines worden standaard gebruikt.
type time
In de Korn-schaal time
is een trefwoord. In plaats van de GNU wordt een interne routine gebruikt time
opdracht.
VERWANT: Wat is ZSH en waarom zou u het moeten gebruiken in plaats van Bash?
Het GNU-tijdcommando uitvoeren
Als de shell op uw Linux-systeem een intern time
routine moet u expliciet zijn als u de GNU wilt gebruiken time
binair. U moet ofwel:
- Geef het hele pad naar het binaire bestand op, zoals
/usr/bin/time
. Voer de … uitwhich time
commando om dit pad te vinden. - Gebruik
command time
. - Gebruik een backslash zoals
time
.
De which time
commando geeft ons het pad naar het binaire bestand.
We kunnen dit testen door gebruik te maken van /usr/bin/time
als een commando om het binaire GNU-bestand te starten. Dat werkt. We krijgen een reactie van de time
opdracht die ons vertelt dat we geen opdrachtregelparameters hebben opgegeven om eraan te werken.
Typen command time
werkt ook, en we krijgen dezelfde gebruiksinformatie van time
. De command
commando vertelt de shell om het volgende commando te negeren zodat het buiten de shell wordt verwerkt.
Gebruik maken van een teken voor de commandonaam is hetzelfde als gebruiken
command
voor de commandonaam.
De eenvoudigste manier om ervoor te zorgen dat u de GNU gebruikt time
binair is om de backslash-optie te gebruiken.
time
time
time
roept de schelp versie van de tijd. time
gebruikt de time
binair.
Met behulp van het tijdcommando
Laten we wat programma’s maken. We gebruiken twee programma’s genaamd loop1
en loop2
. Ze zijn gemaakt op basis van loop1.c en loop2.c. Ze doen niets nuttigs behalve het aantonen van de effecten van één type coderingsinefficiëntie.
Dit is loop1.c. De lengte van een string is vereist binnen de twee geneste lussen. De lengte wordt van tevoren bepaald, buiten de twee geneste lussen.
#include "stdio.h" #include "string.h" #include "stdlib.h" int main (int argc, char* argv[]) { int i, j, len, count=0; char szString[]="how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek"; // get length of string once, outside of loops len = strlen( szString ); for (j=0; j<500000; j++) { for (i=0; i < len; i++ ) { if (szString[i] == '-') count++; } } printf("Counted %d hyphensn", count); exit (0); } // end of main
Dit is loop2.c. De lengte van de string wordt keer op keer bepaald voor elke cyclus van de buitenste lus. Deze inefficiëntie zou in de timing moeten verschijnen.
#include "stdio.h" #include "string.h" #include "stdlib.h" int main (int argc, char* argv[]) { int i, j, count=0; char szString[]="how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek-how-to-geek"; for (j=0; j<500000; j++) { // getting length of string every // time the loops trigger for (i=0; i < strlen(szString); i++ ) { if (szString[i] == '-') count++; } } printf("Counted %d hyphensn", count); exit (0); } // end of main
Laten we de loop1
programma en gebruik time
om zijn prestaties te meten.
time ./loop1
Laten we nu hetzelfde doen voor loop2
.
time ./loop2
Dat heeft ons twee reeksen resultaten opgeleverd, maar ze hebben een erg lelijk formaat. Daar kunnen we later iets aan doen, maar laten we een paar stukjes informatie uit de resultaten halen.
Wanneer programma’s worden uitgevoerd, zijn er twee uitvoeringsmodi waartussen ze heen en weer worden geschakeld. Deze worden genoemd gebruikersmodus en kernel-modus.
Kort gezegd, een proces in gebruikersmodus heeft geen directe toegang tot hardware of referentiegeheugen buiten zijn eigen toewijzing. Om toegang te krijgen tot dergelijke bronnen, moet het proces verzoeken doen aan de kernel. Als de kernel het verzoek goedkeurt, gaat het proces naar de uitvoering van de kernelmodus totdat aan de vereiste is voldaan. Het proces wordt dan teruggeschakeld naar uitvoering in gebruikersmodus.
De resultaten voor loop1
vertel ons dat loop1
0,09 seconden in gebruikersmodus doorgebracht. Het heeft ofwel nul tijd doorgebracht in de kernelmodus of de tijd in de kernelmodus is een te lage waarde om te registreren zodra deze naar beneden is afgerond. De totaal verstreken tijd was 0,1 seconde. loop1
ontving gemiddeld 89% van de CPU-tijd gedurende de totale verstreken tijd.
Het inefficiënte loop2
programma duurde drie keer langer om uit te voeren. De totale verstreken tijd is 0,3 seconden. De duur van de verwerkingstijd in de gebruikersmodus is 0,29 seconden. Er wordt niets geregistreerd voor de kernelmodus. loop2
kreeg een gemiddelde van 96% van de CPU-tijd tijdens de uitvoering.
De uitvoer formatteren
U kunt de uitvoer aanpassen van time
met behulp van een opmaakreeks. De opmaakreeks kan tekst en opmaakspecificaties bevatten. De lijst met formaatspecificaties is te vinden op de man-pagina voor time
. Elk van de formaatspecificaties vertegenwoordigt een stukje informatie.
Wanneer de string wordt afgedrukt, worden de formaatspecificaties vervangen door de werkelijke waarden die ze vertegenwoordigen. De formaatspecificatie voor het percentage CPU is bijvoorbeeld de letter P
. Om aan te geven time
dat een formaatspecificatie niet zomaar een gewone letter is, voeg er een procentteken aan toe, zoals %P
. Laten we het in een voorbeeld gebruiken.
De -f
(format string) optie wordt gebruikt om te vertellen time
dat wat volgt is een format string.
Onze format string gaat de karakters “Program:” en de naam van het programma (en eventuele commandoregelparameters die je doorgeeft aan het programma) afdrukken. De %C
formaatspecificatie staat voor “Naam en opdrachtregelargumenten van de opdracht die wordt getimed”. De n
zorgt ervoor dat de uitvoer naar de volgende regel gaat.
Er zijn veel indelingsspecificaties en ze zijn hoofdlettergevoelig, dus zorg ervoor dat u ze correct invoert wanneer u dit voor uzelf doet.
Vervolgens gaan we de tekens ‘Totale tijd:’ afdrukken, gevolgd door de waarde van de totale verstreken tijd voor deze uitvoering van het programma (weergegeven door %E
).
We gebruiken n
om nog een nieuwe regel te geven. Vervolgens printen we de tekens ‘Gebruikersmodus (s)’, gevolgd door de waarde van de CPU-tijd doorgebracht in de gebruikersmodus, aangegeven door de %U
.
We gebruiken n
om nog een nieuwe regel te geven. Deze keer bereiden we ons voor op de tijdwaarde van de kernel. We printen de karakters “Kernel Mode (s)”, gevolgd door de formaatspecificatie voor de CPU-tijd doorgebracht in de kernel-modus, namelijk %S
.
Ten slotte gaan we de karakters afdrukken “n
CPU: ”om ons een nieuwe regel en de titel voor deze gegevenswaarde te geven. De %P
formaatspecificatie geeft het gemiddelde percentage CPU-tijd dat wordt gebruikt door het getimede proces.
De hele opmaakstring is tussen aanhalingstekens geplaatst. We hadden er wat kunnen toevoegen t
tekens om tabs in de uitvoer te plaatsen als we kieskeurig waren over de uitlijning van de waarden.
time -f "Program: %CnTotal time: %EnUser Mode (s) %UnKernel Mode (s) %SnCPU: %P" ./loop1
De uitvoer naar een bestand verzenden
Om de timing van de door u uitgevoerde tests bij te houden, kunt u de uitvoer van verzenden time
naar een bestand. Gebruik hiervoor de -o
(output) optie. De uitvoer van uw programma wordt nog steeds weergegeven in het terminalvenster. Het is alleen de output van time
dat wordt omgeleid naar het bestand.
We kunnen de test opnieuw uitvoeren en de uitvoer opslaan in het test_results.txt
bestand als volgt:
time -o test_results.txt -f "Program: %CnTotal time: %EnUser Mode (s) %UnKernel Mode (s) %SnCPU: %P" ./loop1
cat test_results.txt
De loop1
programma-uitvoer wordt weergegeven in het terminalvenster en de resultaten van time
ga naar de test_results.txt
het dossier.
Als u de volgende reeks resultaten in hetzelfde bestand wilt vastleggen, moet u de -a
(voeg) optie als volgt toe:
time -o test_results.txt -a -f "Program: %CnTotal time: %EnUser Mode (s) %UnKernel Mode (s) %SnCPU: %P" ./loop2
cat test_results.txt
Het zou nu duidelijk moeten zijn waarom we de %C
formaatspecificatie om de naam van het programma op te nemen in de uitvoer van de formaatreeks.
En we hebben geen tijd meer
Waarschijnlijk het meest nuttig voor programmeurs en ontwikkelaars voor het verfijnen van hun code, de time
commando is ook handig voor iedereen die wat meer wil ontdekken over wat er onder de motorkap gebeurt elke keer dat je een programma start.