Saya ingin time
perintah yang terdiri dari dua perintah terpisah dengan satu keluaran perpipaan ke yang lain. Misalnya, perhatikan dua skrip di bawah ini:
$ cat foo.sh
#!/bin/sh
sleep 4
$ cat bar.sh
#!/bin/sh
sleep 2
Sekarang, bagaimana saya bisa time
melaporkan waktu yang diperlukan foo.sh | bar.sh
(dan ya, saya tahu pipa itu tidak masuk akal di sini, tetapi ini hanya sebuah contoh)? Itu berfungsi seperti yang diharapkan jika saya menjalankannya secara berurutan dalam subkulit tanpa memipis:
$ time ( foo.sh; bar.sh )
real 0m6.020s
user 0m0.010s
sys 0m0.003s
Tapi saya tidak bisa membuatnya bekerja ketika memiploskan:
$ time ( foo.sh | bar.sh )
real 0m4.009s
user 0m0.007s
sys 0m0.003s
$ time ( { foo.sh | bar.sh; } )
real 0m4.008s
user 0m0.007s
sys 0m0.000s
$ time sh -c "foo.sh | bar.sh "
real 0m4.006s
user 0m0.000s
sys 0m0.000s
Saya sudah membaca pertanyaan serupa ( Bagaimana menjalankan waktu pada banyak perintah DAN menulis waktu keluaran ke file? ) Dan juga mencoba time
dieksekusi mandiri :
$ /usr/bin/time -p sh -c "foo.sh | bar.sh"
real 4.01
user 0.00
sys 0.00
Bahkan tidak berfungsi jika saya membuat skrip ketiga yang hanya menjalankan pipa:
$ cat baz.sh
#!/bin/sh
foo.sh | bar.sh
Dan waktu itu:
$ time baz.sh
real 0m4.009s
user 0m0.003s
sys 0m0.000s
Menariknya, itu tidak muncul seolah-olah time
keluar segera setelah perintah pertama selesai. Jika saya berubah bar.sh
menjadi:
#!/bin/sh
sleep 2
seq 1 5
Dan sekali time
lagi, saya mengharapkan time
hasilnya akan dicetak sebelum seq
tetapi tidak:
$ time ( { foo.sh | bar.sh; } )
1
2
3
4
5
real 0m4.005s
user 0m0.003s
sys 0m0.000s
Sepertinya time
tidak menghitung waktu yang diperlukan untuk mengeksekusi bar.sh
meskipun menunggu sampai selesai sebelum mencetak laporannya 1 .
Semua tes dijalankan pada sistem Arch dan menggunakan bash 4.4.12 (1) -release. Saya hanya dapat menggunakan bash untuk proyek ini adalah bagian dari jadi bahkan jika zsh
atau beberapa shell kuat lainnya dapat mengatasinya, itu tidak akan menjadi solusi yang layak untuk saya.
Jadi, bagaimana saya bisa mendapatkan waktu yang dibutuhkan seperangkat perintah pipa untuk dijalankan? Dan, sementara kita melakukannya, mengapa itu tidak berhasil? Sepertinya time
segera keluar segera setelah perintah pertama selesai. Mengapa?
Saya tahu saya bisa mendapatkan waktu individu dengan sesuatu seperti ini:
( time foo.sh ) 2>foo.time | ( time bar.sh ) 2> bar.time
Tapi saya masih ingin tahu apakah mungkin mengatur waktu semuanya sebagai satu operasi.
1 Ini sepertinya bukan masalah penyangga, saya mencoba menjalankan skrip dengan unbuffered
dan stdbuf -i0 -o0 -e0
dan angkanya masih dicetak sebelum time
hasilnya.
Jawaban:
Hal ini bekerja.
Bagian-bagian berbeda dari sebuah pipa dieksekusi bersamaan. Satu-satunya hal yang menyinkronkan / membuat serialisasi proses dalam pipa adalah IO, yaitu satu proses menulis ke proses berikutnya dalam pipa dan proses selanjutnya membaca apa yang ditulis pertama. Selain itu, mereka mengeksekusi secara independen satu sama lain.
Karena tidak ada pembacaan atau penulisan yang terjadi di antara proses-proses dalam pipeline Anda, waktu yang diperlukan untuk mengeksekusi pipeline adalah
sleep
panggilan yang terlama .Anda mungkin juga telah menulis
Terdon memposting beberapa skrip contoh yang sedikit dimodifikasi dalam obrolan :
dan
Pertanyaannya adalah "mengapa
time ( sh foo.sh | sh bar.sh )
kembali 4 detik daripada 3 + 3 = 6 detik?"Untuk melihat apa yang terjadi, termasuk perkiraan waktu setiap perintah dieksekusi, seseorang dapat melakukan ini (output berisi anotasi saya):
Jadi, untuk menyimpulkan, pipa membutuhkan 4 detik, bukan 6, karena buffering dari output dari dua panggilan pertama
echo
masukfoo.sh
.sumber
ksh93
hanya menunggu komponen terakhir dari pipa (sleep 3 | sleep 1
akan bertahan 1 detik). shell Bourne tidak memilikitime
kata kunci, tetapi padaksh93
saat dijalankan dengantime
, semua komponen menunggu.sleep 10 | sleep 1
membutuhkan waktu satu detik, sementaratime sleep 10 | sleep 1
butuh 10 detik di ksh93. Dalam shell Bournetime sleep 10 | sleep 1
akan mengambil satu detik, tetapi Anda akan mendapatkan output waktu (sleep 10
hanya untuk dan dari/usr/bin/time
) keluar dari biru 9 detik kemudian.time
kali benar pipa, tetapi mengubah perilaku shell di ksh93.(sleep 10 | sleep 1)
butuh 1 detik,time (sleep 10 | sleep 1)
butuh 10 detik.{ (sleep 10 | sleep 1); echo x; }
outputx
setelah 1 detik,time { (sleep 10 | sleep 1); echo x; }
outputx
setelah 10 detik. Sama jika Anda meletakkan kode itu di fungsi dan waktu fungsi.ksh93
seperti dizsh
( di-o promptsubst
sini), Anda dapat melakukantypeset -F SECONDS
untuk mendapatkan perkiraan jumlah detik yang kurang (POSIXsh
tidak memilikiSECONDS
)Apakah ini contoh yang lebih baik?
Script busyloop selama 3 dan 4 detik (resp.), Mengambil total 4 detik secara real time karena eksekusi paralel, dan 7 detik waktu CPU. (setidaknya sekitar.)
Atau ini:
Ini tidak berjalan secara paralel, sehingga total waktu yang diambil adalah 5 detik. Semuanya dihabiskan untuk tidur, jadi tidak ada waktu CPU yang digunakan.
sumber
Jika sudah,
sysdig
Anda dapat memasukkan pelacak pada titik-titik sembarang, dengan asumsi Anda dapat memodifikasi kode untuk menambahkan penulisan yang diperlukan/dev/null
(tapi itu gagal "operasi tunggal" persyaratan Anda) dan kemudian merekam hal-hal melalui
dan kemudian Anda mungkin perlu pahat sysdig untuk mengekspor hanya durasinya
yang pernah disimpan ke
sysdig/chisels
direktori Anda sebagai filespantagduration.lua
dapat digunakan sebagaiAtau Anda bisa bermain-main dengan
csysdig
atau output JSON.sumber