Dapatkan waktu eksekusi program di shell

407

Saya ingin mengeksekusi sesuatu di shell linux dalam beberapa kondisi yang berbeda, dan dapat menampilkan waktu eksekusi dari setiap eksekusi.

Saya tahu saya bisa menulis skrip perl atau python yang akan melakukan ini, tetapi apakah ada cara saya bisa melakukannya di shell? (yang kebetulan bash)

ʞɔıu
sumber
2
Kasing
apakah mungkin untuk mendapatkan Tickscase seperti windows?
freeforall tousez
unix.stackexchange.com/questions/52313/…
Ciro Santilli 郝海东 冠状 病 六四 六四 事件 法轮功

Jawaban:

534

Gunakan timekata kunci bawaan:

$ waktu bantuan

waktu: waktu [-p] PIPELINE
    Jalankan PIPELINE dan cetak ringkasan waktu nyata, waktu CPU pengguna,
    dan waktu CPU sistem yang digunakan untuk mengeksekusi PIPELINE saat itu berakhir.
    Status pengembalian adalah status pengembalian dari PIPELINE. Opsi `-p '
    mencetak ringkasan waktu dalam format yang sedikit berbeda. Ini menggunakan
    nilai variabel TIMEFORMAT sebagai format output.

Contoh:

$ time sleep 2
0m2.009s nyata
pengguna 0m0,000s
sys 0m0.004s
Robert Gamble
sumber
1
Bagaimana ini digunakan pada perintah seperti time -p i=x; while read line; do x=x; done < /path/to/file.txt? Segera mengembalikan 0,00 kecuali saya tidak meletakkan sesuatu sebelum loop sementara .. apa yang terjadi?
natli
ini adalah versi 'waktu' yang buruk, bash builtin. di mana perintah 'waktu' eksternal?
Znik
6
@Znik, coba / usr / bin / waktu
Mark Rajcok
10
@natli: Meskipun timedapat mengatur waktu seluruh pipa apa adanya (berdasarkan menjadi kata kunci Bash ), Anda perlu menggunakan perintah grup ({ ...; ...; } ) untuk time -p { i=x; while read line; do x=x; done < /path/to/file.txt; }
menentukan
2
Untuk melihat semua versi waktu yang telah Anda instal pada sistem Anda, Anda dapat menggunakan type -a time
spinup
120

Anda bisa mendapatkan informasi yang lebih detail daripada bash built-in time(yang Robert Gamble sebutkan) menggunakan waktu (1) . Biasanya ini /usr/bin/time.

Catatan editor: Untuk memastikan bahwa Anda menggunakan utilitas eksternal time daripada milik shell Andatime kata kunci , panggil sebagai /usr/bin/time.
timeadalah utilitas yang diamanatkan POSIX , tetapi satu-satunya opsi yang diperlukan untuk mendukungnya adalah -p.
Platform tertentu menerapkan tertentu, ekstensi tidak standar: -vbekerja dengan GNU 'stime utilitas, seperti yang ditunjukkan di bawah ini (pertanyaannya adalah ditandai); implementasi BSD / macOS digunakan -luntuk menghasilkan keluaran yang serupa - lihat man 1 time.

Contoh keluaran verbose:


$ /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

grepsedawk
sumber
2
Anda tidak akan tahu paket debian apa yang akan datang? tampaknya tidak diinstal secara default
ʞɔıu
1
Saya merujuk posting Anda Robert. Kecuali Anda maksud perintah yang Anda sarankan bukan bash built-in?
grepsedawk
24
Hebatnya, itu diinstal dari paket yang disebut "waktu".
Paul Tomblin
2
Output dari / usr / bin / time terlihat seperti "0,00 pengguna 0,00 sistem 0: 02.00 CPU 0% (0avgtext + 0avgdata 0maxresident) k 0inputs + 0outputs (0major + 172minor) pagefault 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"
David
sumber
14
Ada banyak cara yang lebih sederhana. Bash menghitung secara otomatis variabel khusus $ DETIK, kemudian perhitungan ulang berdasarkan perintah tanggal eksternal tidak diperlukan. Variabel $ SECONDS menyimpan berapa detik skrip bash berjalan saat dijalankan. Variabel ini memiliki beberapa properti khusus. Lihat halaman manual: D
Znik
Saya sudah mencoba keduanya di atas & metode dalam komentar. Pada tanggal 1 saya mendapatkan kesalahan 'variabel ilegal' & ke-2 saya mendapatkan 'variabel tidak dikenal'
DrBwts
45

Untuk pengukuran delta baris demi baris, coba gnomon .

Utilitas baris perintah, sedikit seperti ts moreutils, untuk menambahkan informasi stempel waktu ke output standar dari perintah lain. Berguna untuk proses jangka panjang di mana Anda ingin catatan sejarah tentang apa yang butuh waktu lama.

Anda juga dapat menggunakan opsi --highdan / atau --mediumuntuk menentukan ambang panjang dalam detik, di mana gnomon akan menyorot timestamp berwarna merah atau kuning. Dan Anda dapat melakukan beberapa hal lain juga.

contoh

Adriano Resende
sumber
3
Tip yang bagus, tetapi hanya untuk memperjelas: ini berguna untuk penentuan waktu baris per baris , tetapi biaya tambahan dari pengambilan waktu yang berbutir halus seperti itu secara signifikan menambah waktu keseluruhan .
mklement0
2
Utilitas yang luar biasa .. Terima kasih telah berbagi
Kishan B
19

Jika Anda ingin lebih presisi, gunakan %Ndengan date(dan gunakan bcuntuk diff, karena $(())hanya menangani bilangan bulat).

Inilah cara melakukannya:

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

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

Contoh:

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

Hasil:

Execution time: 0.104623 seconds
Benoit Duffez
sumber
15

Jika Anda berniat menggunakan waktu untuk menghitung, pelajari cara menggunakan -fopsi /usr/bin/timeuntuk menghasilkan kode yang menghemat waktu. Berikut adalah beberapa kode yang saya gunakan baru-baru ini untuk mendapatkan dan mengurutkan waktu pelaksanaan dari seluruh kelas program siswa:

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...

Saya kemudian menggabungkan semua $timefilefile dan menyalurkan output ke juru bahasa Lua . Anda dapat melakukan hal yang sama dengan Python atau bash atau apa pun sintaks favorit Anda. Saya suka teknik ini.

Norman Ramsey
sumber
Catatan: Path lengkap /usr/bin/timediperlukan karena meskipun which timeakan memberi tahu Anda sebaliknya, jika Anda hanya menjalankan time, itu akan menjalankan versi shell Anda timeyang tidak menerima argumen apa pun.
Kevin Dice
Saya akan pergi dengan env time:-)
Ciro Santilli 郝海东 冠状 病 六四 事件 事件 法轮功
13

Jika Anda hanya membutuhkan ketelitian untuk yang kedua, Anda dapat menggunakan $SECONDSvariabel bawaan , yang menghitung jumlah detik bahwa shell telah berjalan.

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
glenn jackman
sumber
10

Anda dapat menggunakan timedan subkulit () :

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

Atau dalam shell yang sama {}:

time {
  for (( i=1; i<10000; i++ )); do
    echo 1 >/dev/null
  done
}
Eduardo Cuomo
sumber
Anda memposting dua cuplikan kode yang identik. Anda pasti bermaksud memiliki sesuatu yang berbeda di sana.
stason
3
@StasBekman tidak benar, pertama menggunakan (& )(konteks baru, subkulit ), dan lainnya dengan {& }(shell yang sama, konteks yang sama)
Eduardo Cuomo
Aha! Saya melihat sangat keras pada keduanya dan tidak melihat perbedaannya. Terima kasih telah menjelaskannya {} vs ().
stason
2

Jalannya adalah

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

output adalah >>

real    0m0.014s
user    0m0.010s
sys     0m0.002s
Robel Sharma
sumber
Tidak perlu menggunakan -lphtreadatau -otag. Hanya perlu menggunakan timeperintah, yang jawaban yang diterima menjelaskan lebih baik.
Dennis
7
Itu adalah contoh. Itu adalah perform.c saya memiliki threading jadi saya perlu -lpthread dan untuk identitas sederhana itu -o per.
Robel Sharma
0

satu metode yang mungkin sederhana (yang mungkin tidak memenuhi kebutuhan pengguna yang berbeda) adalah penggunaan shell PROMPT.it adalah solusi sederhana yang dapat berguna dalam beberapa kasus. Anda dapat menggunakan fitur bash prompt seperti pada contoh di bawah ini:

export PS1 = '[\ t \ u @ \ h] \ $' 

Perintah di atas akan menghasilkan perubahan prompt shell ke:

[HH: MM: SS username @ hostname] $ 

Setiap kali Anda menjalankan perintah (atau tekan enter) kembali ke prompt shell, prompt akan menampilkan waktu saat ini.

Catatan:
1) berhati-hatilah bahwa jika Anda menunggu beberapa saat sebelum Anda mengetik perintah berikutnya, maka kali ini perlu dipertimbangkan, yaitu waktu yang ditampilkan dalam prompt shell adalah timestamp ketika prompt shell ditampilkan, bukan ketika Anda memasukkan perintah. beberapa pengguna memilih untuk menekan tombol Enter untuk mendapatkan prompt baru dengan stempel waktu baru sebelum mereka siap untuk perintah berikutnya.
2) Ada opsi dan pengubah lain yang tersedia yang dapat digunakan untuk mengubah prompt bash, lihat (man bash) untuk detail lebih lanjut.

tstorym
sumber
Bukan itu intinya ketika program dieksekusi, tetapi durasi eksekusi program.
Geno Chen