Uzyskaj czas wykonania programu w powłoce


407

Chcę wykonać coś w powłoce linuksowej w kilku różnych warunkach i móc wyprowadzić czas wykonania każdego wykonania.

Wiem, że mógłbym napisać skrypt Perla lub Pythona, który by to zrobił, ale czy istnieje sposób, aby to zrobić w powłoce? (która okazuje się bash)


2

czy można uzyskać Tickspodobną obudowę systemu Windows?
— freeforall tousez

Odpowiedzi:


534

Użyj wbudowanego timesłowa kluczowego:

$ czas pomocy

time: time [-p] PIPELINE
    Uruchom PIPELINE i wydrukuj podsumowanie czasu rzeczywistego, czasu procesora użytkownika,
    oraz czas procesora systemu spędzony na wykonywaniu PIPELINE po jego zakończeniu.
    Status zwrotu to status zwrotu PIPELINE. Opcja `-p '
    drukuje podsumowanie czasowe w nieco innym formacie. To używa
    wartość zmiennej TIMEFORMAT jako formatu wyjściowego.

Przykład:

$ time sleep 2
prawdziwe 0m2.009s
użytkownik 0m0.000s
sys 0m0,004s

1
Jak to jest używane w poleceniu time -p i=x; while read line; do x=x; done < /path/to/file.txt? Natychmiast zwraca 0,00, chyba że nie wstawię niczego przed pętlą while. Co daje?
— natli

jest to kiepska wersja „czasu”, wbudowana bash. gdzie jest zewnętrzne polecenie „czas”?
— Znik

6
@Znik, spróbuj / usr / bin / time
— Mark Rajcok

10
@natli: Chociaż timemożna odmierzać czas trwania całego potoku w stanie, w jakim się znajduje (ze względu na to, że jest słowem kluczowym Bash ), musisz użyć polecenia group ( { ...; ...; }), aby time -p { i=x; while read line; do x=x; done < /path/to/file.txt; }
— zmierzyć

2
Aby zobaczyć wszystkie wersje czasu, które zainstalowałeś w swoim systemie, możesz użyćtype -a time
— spinup

120

Możesz uzyskać znacznie bardziej szczegółowe informacje niż wbudowane bash time(o czym wspomina Robert Gamble), używając czasu (1) . Zwykle tak jest /usr/bin/time.

Uwaga edytora: Aby upewnić się, że wywołujesz zewnętrzne narzędzie time zamiast time słowa kluczowego powłoki , wywołaj je jako /usr/bin/time.
timejest narzędziem wymaganym przez POSIX , ale jedyną opcją wymaganą do obsługi jest -p.
Konkretnych platform realizacji konkretnych niestandardowe rozszerzenia: -vprace z GNU „s timeużyteczności, jak pokazano poniżej (pytanie jest oznaczone); implementacja BSD / macOS używa -ldo generowania podobnych wyników - patrz man 1 time.

Przykład pełnego wyjścia:


$ /usr/bin/time -v sleep 1
       Command being timed: "sleep 1"
       User time (seconds): 0.00
       System time (seconds): 0.00
       Percent of CPU this job got: 1%
       Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.05
       Average shared text size (kbytes): 0
       Average unshared data size (kbytes): 0
       Average stack size (kbytes): 0
       Average total size (kbytes): 0
       Maximum resident set size (kbytes): 0
       Average resident set size (kbytes): 0
       Major (requiring I/O) page faults: 0
       Minor (reclaiming a frame) page faults: 210
       Voluntary context switches: 2
       Involuntary context switches: 1
       Swaps: 0
       File system inputs: 0
       File system outputs: 0
       Socket messages sent: 0
       Socket messages received: 0
       Signals delivered: 0
       Page size (bytes): 4096
       Exit status: 0


2
nie zdarzyłbyś się, z jakiego pakietu debian pochodziłby? nie wydaje się być instalowany domyślnie
— ʞɔıu

1
Odniosłem się do twojego postu Robert. Chyba że masz na myśli polecenie, które sugerujesz, nie jest wbudowane w bash?
— grepsedawk

24
O dziwo, jest instalowany z pakietu o nazwie „czas”.
— Paul Tomblin,

2
Dane wyjściowe z / usr / bin / time wyglądają jak "0,00user 0,00system 0: 02.00 upłynął 0% CPU (0avgtext + 0avgdata 0maxresident) k 0 wejść + 0 wyjść (0major + 172minor) błędy strony 0swaps"
— Paul Tomblin

4
@Nick: „sudo apt-get install time”.
— Robert Gamble,

79
#!/bin/bash
START=$(date +%s)
# do something
# start your script work here
ls -R /etc > /tmp/x
rm -f /tmp/x
# your logic ends here
END=$(date +%s)
DIFF=$(( $END - $START ))
echo "It took $DIFF seconds"

14
Jest o wiele prostszy sposób. Bash automatycznie oblicza specjalną zmienną $ SECONDS, następnie niepotrzebne jest ponowne obliczanie na podstawie polecenia daty zewnętrznej. Zmienna $ SECONDS przechowuje liczbę sekund uruchomionego skryptu bash. Ta zmienna ma jakąś specjalną właściwość. Zobacz stronę
— podręcznika

Próbowałem zarówno powyższej, jak i metody w komentarzu. W pierwszym dostaję błąd „nielegalnej zmiennej”, a w drugim dostaję „niezidentyfikowaną zmienną”
— DrBwts

45

Do pomiaru delta linia po linii spróbuj gnomon .

Narzędzie wiersza poleceń, trochę jak ts moreutils, do dołączania informacji o znaczniku czasu do standardowego wyjścia innego polecenia. Przydatny w długotrwałych procesach, w których potrzebujesz historycznego zapisu tego, co trwa tak długo.

Możesz także użyć opcji --highi / lub, --mediumaby określić próg długości w sekundach, powyżej którego gnomon podświetli znacznik czasu na czerwono lub żółto. Możesz także zrobić kilka innych rzeczy.

przykład


3
Świetna wskazówka, ale dla jasności: jest to przydatne w przypadku taktowania linia po linii , ale narzut związany z przyjmowaniem tak drobnoziarnistych taktów znacznie zwiększa ogólny czas.
— mklement0

2
Niesamowite narzędzie .. Dzięki za udostępnienie
— Kishan B

19

Jeśli chcesz uzyskać większą precyzję, użyj %Nz date(i użyj bcdla diff, ponieważ $(())obsługuje tylko liczby całkowite).

Oto jak to zrobić:

start=$(date +%s.%N)
# do some stuff here
dur=$(echo "$(date +%s.%N) - $start" | bc)

printf "Execution time: %.6f seconds" $dur

Przykład:

start=$(date +%s.%N); \
  sleep 0.1s; \
  dur=$(echo "$(date +%s.%N) - $start" | bc); \
  printf "Execution time: %.6f seconds\n" $dur

Wynik:

Execution time: 0.104623 seconds

15

Jeśli zamierzasz wykorzystać czasy później do obliczeń, dowiedz się, jak korzystać z -fopcji /usr/bin/timegenerowania kodu, który oszczędza czas. Oto kod, którego ostatnio użyłem, aby uzyskać i posortować czasy wykonania całej klasy programów dla studentów:

fmt="run { date = '$(date)', user = '$who', test = '$test', host = '$(hostname)', times = { user = %U, system = %S, elapsed = %e } }"
/usr/bin/time -f "$fmt" -o $timefile command args...

Później połączyłem wszystkie $timefilepliki i potokowałem dane wyjściowe do interpretera Lua . Możesz zrobić to samo z Pythonem, bash lub dowolną ulubioną składnią. Uwielbiam tę technikę.


Uwaga: Pełna ścieżka /usr/bin/timejest konieczna, ponieważ chociaż which timepowie ci inaczej, jeśli po prostu uruchomisz time, uruchomi ona wersję powłoki, timektóra nie przyjmuje żadnych argumentów.
— Kevin Dice,

env time
— Poszedłbym

13

Jeśli potrzebujesz dokładności co do sekundy, możesz użyć wbudowanej $SECONDSzmiennej, która zlicza liczbę sekund, które uruchomiła powłoka.

while true; do
    start=$SECONDS
    some_long_running_command
    duration=$(( SECONDS - start ))
    echo "This run took $duration seconds"
    if some_condition; then break; fi
done

10

Możesz użyć timei podpowłoki () :

time (
  for (( i=1; i<10000; i++ )); do
    echo 1 >/dev/null
  done
)

Lub w tej samej powłoce {}:

time {
  for (( i=1; i<10000; i++ )); do
    echo 1 >/dev/null
  done
}

Opublikowałeś dwa identyczne fragmenty kodu. Musiałeś mieć tam coś innego.
— Stason

3
@StasBekman nie jest prawdą, najpierw używa (& )(nowy kontekst, podpowłoka ), a inne z {& }(ta sama powłoka, ten sam kontekst)
— Eduardo Cuomo

Aha! Patrzyłem na nich bardzo mocno i nie zauważyłem różnicy. Dziękujemy za wyjaśnienie, że {} vs ().
— Stason

2

Tak jest

$ > g++ -lpthread perform.c -o per
$ > time ./per

wyjście to >>

real    0m0.014s
user    0m0.010s
sys     0m0.002s

Nie trzeba używać -lphtreadani -otagować. Wystarczy użyć timepolecenia, które zaakceptowana odpowiedź wyjaśnia lepiej.
— Dennis

7
To był przykład. Oto moja wydajność. C ma wątki, więc potrzebuję -lpthread, a dla prostej tożsamości jest to -o per.
— Robel Sharma

0

jedną z możliwie prostych metod (która może nie spełniać różnych potrzeb użytkowników) jest użycie powłoki PROMPT. jest to proste rozwiązanie, które może być przydatne w niektórych przypadkach. Możesz użyć funkcji monitowania bash, jak w poniższym przykładzie:

eksport PS1 = „[\ t \ u @ \ h] \ $” 

Powyższe polecenie spowoduje zmianę monitu powłoki na:

[GG: MM: nazwa użytkownika SS @ nazwa hosta] $ 

Za każdym razem, gdy uruchomisz polecenie (lub naciśniesz Enter), wracając do monitu powłoki, w monicie wyświetli się bieżąca godzina.

uwagi:
1) strzeż się, że jeśli poczekałeś chwilę przed wpisaniem następnego polecenia, to należy wziąć to pod uwagę, tj. czas wyświetlany w wierszu polecenia powłoki jest znacznikiem czasu, gdy polecenie wiersza było wyświetlane, a nie po wprowadzeniu polecenia. niektórzy użytkownicy wybierają klawisz Enter, aby otrzymać nowy monit z nowym znacznikiem czasu, zanim będą gotowi na następne polecenie.
2) Istnieją inne dostępne opcje i modyfikatory, których można użyć do zmiany monitu bash, patrz (man bash), aby uzyskać więcej szczegółów.


Nie punkt, w którym program się uruchamia, ale czas jego trwania.
— Geno Chen
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.