Shell bash saya membutuhkan waktu hingga 3-4 detik untuk memulai, sementara jika saya memulainya dengan --norc
itu segera berjalan.
Saya mulai "membuat profil" /etc/bash.bashrc
dan ~/.bashrc
dengan memasukkan return
pernyataan secara manual dan mencari peningkatan kecepatan, tetapi ini bukan proses kuantitatif dan tidak efisien.
Bagaimana cara membuat profil skrip bash saya dan melihat perintah mana yang membutuhkan waktu paling lama untuk memulai?
time bash -c 'exit'
dantime bash -i -c 'exit'
dan mungkin bermain dengan--norc
dan--noprofile
.Jawaban:
Jika Anda memiliki GNU
date
(atau versi lain yang dapat mengeluarkan nanodetik), lakukan ini di awal/etc/bash.bashrc
(atau di mana pun Anda ingin memulai pelacakan dalam skrip Bash mana pun):Menambahkan
di akhir
~/.bashrc
(atau di akhir bagian skrip Bash mana pun yang ingin Anda hentikan penelusurannya). Ini\011
adalah karakter tab oktal.Anda harus mendapatkan log jejak
/tmp/bashstart.PID.log
yang menunjukkan stempel waktu detik.nanoseconds dari setiap perintah yang dijalankan. Perbedaan dari satu waktu ke waktu berikutnya adalah jumlah waktu yang diambil langkah intervensi.Saat Anda mempersempit semuanya, Anda dapat bergerak
set -x
nanti danset +x
sebelumnya (atau kurung beberapa bagian yang menarik secara selektif).Meskipun tidak berbutir halus seperti
date
nanodetik GNU , Bash 5 menyertakan variabel yang memberikan waktu dalam mikrodetik. Menggunakannya menyelamatkan Anda dari pemijahan eksternal yang dapat dieksekusi untuk setiap baris dan berfungsi di Mac atau di tempat lain yang tidak memiliki GNUdate
- selama Anda memiliki Bash 5, tentu saja. Ubah pengaturanPS4
:Seperti yang ditunjukkan oleh @pawamoy, Anda dapat menggunakan
BASH_XTRACEFD
untuk mengirim keluaran pelacakan ke deskriptor file terpisah jika Anda memiliki Bash 4.1 atau yang lebih baru. Dari jawaban ini :Ini akan menyebabkan keluaran jejak pergi ke file
command.txt
pergistdout
danstdout
menjadi keluaran secara normal (atau dialihkan secara terpisah).sumber
exec
akan mengembalikan fd2 ke normal sehingga Anda harus mendapatkan prompt kembali.\D{...}
inPS4
memungkinkan string format waktu yang sepenuhnya sewenang-wenang diperluas tanpa overhead kinerjadate
saat diluncurkan sebagai subproses.date
mengerti%N
dan Bash 4.2 tidak (karenastrftime(3)
tidak) pada sistem GNU - jadi sewenang-wenang dengan batasan. Poin Anda tentang kinerja versus resolusi bagus dan pengguna harus membuat pilihan dengan bijak, mengingat bahwa kinerja yang dicapai hanya sementara selama debugging (dan hanya jikaset -x
diterapkan).Profiling pesta (4 jawaban)
Edit:
script
metode tambahkan Maret 2016Membaca ini dan karena pembuatan profil adalah langkah penting, saya telah melakukan beberapa tes dan penelitian tentang seluruh pertanyaan SO ini dan jawaban yang sudah diposting.
Ada 4+ jawaban:
Penggunaan terakhir
script
,scriptreplay
dan file waktu .Akhirnya, sedikit perbandingan penampilan di bagian akhir.
Menggunakan
set -x
dandate
tetapi dengan garpu terbatasAmbil dari ide @ DennisWilliamson, tetapi dengan sintaks berikut, hanya akan ada satu percabangan awal ke 3 perintah:
Melakukan ini
date
hanya akan berjalan sekali. Ada demo / tes cepat untuk menunjukkan cara kerjanya:Contoh skrip:
Dengan menjalankan skrip ini, Anda membuat 2 file:
/tmp/sample-XXXX.log
dan/tmp/sample-XXXX.tim
(dengan XXXX adalah ID proses dari skrip yang sedang berjalan).Anda dapat mempresentasikannya dengan menggunakan
paste
:Atau Anda bahkan dapat menghitung waktu yang berbeda:
atau pada dua kolom:
Dapat membuat:
Menggunakan
trap debug
dan/proc/timer_list
pada kernel GNU / Linux terbaru , tanpa garpu .Di bawah kernel terbaru GNU / Linux , Anda mungkin menemukan
/proc
file bernamatimer_list
:Di mana waktu saat ini adalah jumlah
5461935212966259 + 1383718821564493249
, tetapi dalam nanodetik.Jadi untuk menghitung waktu yang berlalu , tidak perlu mengetahui offset.
Untuk jenis pekerjaan ini, saya menulis elap.bash (V2) , yang bersumber dari sintaks berikut:
atau
(Lihat komentar untuk sintaks lengkap)
Jadi Anda cukup menambahkan baris ini di atas skrip Anda:
Sampel kecil:
Lakukan render di host saya:
Menggunakan
trap2
alih-alihtrap
sebagai argumen ke perintah sumber:Akan membuat dua kolom perintah terakhir dan total :
Menggunakan
strace
Ya,
strace
bisa melakukan pekerjaan itu:Tapi bisa membuat banyak barang!
Menggunakan perintah yang lebih terbatas:
Akan membuang log yang lebih ringan:
Bergantung pada apa yang Anda telusuri, Anda mungkin lebih membatasi:
Membacanya akan sedikit lebih sulit:
Skrip bash asli tidak begitu mudah diikuti dalam hal ini ...
Menggunakan
script
,scriptreplay
dan file waktuSebagai bagian dari BSD Utils ,
script
(danscriptreplay
) adalah alat yang sangat tua yang dapat digunakan untuk membuat profil bash, dengan footprint yang sangat kecil.Akan menghasilkan:
dan menghasilkan dua file:
File
script.log
berisi semua jejak danscript.tim
merupakan file waktu :Anda bisa melihat total waktu eksekusi dengan baris pertama dan terakhir logfile dan / atau dengan meringkas waktu dalam file waktu:
Dalam file waktu, nilai kedua adalah jumlah byte berikutnya dalam file log yang sesuai. Ini memungkinkan Anda untuk memutar ulang file log secara opsional dengan faktor percepatan :
atau
atau
Menampilkan waktu dan perintah secara berdampingan juga sedikit lebih rumit:
Tes dan kesimpulan
Untuk melakukan tes, saya telah mengunduh sampel kedua di bash complex hello world , skrip ini membutuhkan waktu sekitar 0,72 detik untuk diselesaikan di host saya.
Saya telah menambahkan di atas skrip salah satu dari:
berdasarkan
elap.bash
fungsioleh
set -x
danPS4
oleh
set -x
dan garpu awal ke perintah exec panjangoleh
script
(danset +x
)Waktu
Dan bandingkan waktu eksekusi (di host saya):
Keluaran
berdasarkan
elap.bash
fungsioleh
set -x
danPS4
oleh
set -x
dan percabangan awal ke perintah exec panjang (danpaste
skrip sampel kedua saya )oleh
strace
oleh
script
Kesimpulan
Baik! Jika bash murni saya lebih cepat daripada bercabang hingga saat ini pada setiap perintah , bash murni saya menyiratkan beberapa operasi pada setiap perintah.
Cara mendedikasikan proses independen untuk logging dan penyimpanan jelas lebih efisien.
strace
adalah cara yang menarik, lebih detail, tetapi sulit dibaca.script
, denganscriptreplay
dan faktor akselerasi juga sangat bagus, tidak presisi yang sama karena ini didasarkan pada pertukaran konsol daripada eksekusi proses, tetapi sangat ringan dan efisien (bukan tujuan yang sama, penggunaan yang tidak sama).Akhirnya, saya pikir yang lebih efisien, dalam keterbacaan dan kinerja adalah
set + 1 fork
, Yang pertama dari jawaban ini, tetapi baik-baik saja, tergantung pada kasus tertentu, saya menggunakan kadangstrace
- kadang dan / atauscript
juga.sumber
exec {BASH_XTRACEFD}>
bukan hanyaexec 3>&2 2>
akan mengisi file log dengan keluaran pencatatan jejak dan bukan keluaran stderr lainnya.script.sh
, saya hanya bisa melakukanbash -c "exec {BASH_XTRACEFD}> >(tee trace.log | sed -u 's/^.*$//' | date -f - +%s.%N > timing.log); set -x; . script.sh
dan mendapatkan data profil tanpa memodifikasiscript.sh
. Saat presisi sub-detik tidak diperlukan, saya sukabash -c "exec {BASH_XTRACEFD}>trace.log; set -x; PS4='+\t'; . script.sh
waktu yang memberi cap setiap garis jejak dengan presisi kedua dan tanpa forking hingga saat ini (overhead rendah).Seringkali membantu untuk melacak panggilan sistem
Dari manual:
-c Hitung waktu, panggilan, dan kesalahan untuk setiap panggilan sistem dan laporkan ringkasan keluar dari program.
-f Lacak proses anak ...
Ini tidak persis seperti yang Anda inginkan dan apa yang ditampilkan profiler berorientasi garis kepada Anda, tetapi biasanya membantu menemukan hot spot.
sumber
Anda mungkin melihat
trap
perintah dengan kondisi DEBUG . Ada cara untuk mengatur perintah yang akan dieksekusi bersama dengan perintah Anda. Lihat catatan jawabannya.sumber
help trap
: "Jika SIGNAL_SPEC adalah DEBUG, ARG dijalankan sebelum setiap perintah sederhana." Di Bash 3.2, dikatakan "setelah". Itu salah ketik. Mulai Bash 2.05b, ini dijalankan sebelumnya. Referensi : "Dokumen ini merinci perubahan antara versi ini, bash-2.05b-alpha1, dan versi sebelumnya, bash-2.05a-release. ... 3. Fitur Baru di Bash ... w. Perangkap DEBUG sekarang dijalankan sebelum perintah sederhana, ((...)) perintah, [[...]] perintah bersyarat, dan untuk ((...)) loop. " Pengujian di setiap versi menegaskan bahwa itu sebelumnya .Waktu, xtrace, bash -x,
set -x
danset+x
( http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html ) tetap menjadi cara ortodoks untuk men-debug skrip.Bagaimanapun juga untuk memperbesar wawasan kita, dimungkinkan untuk memberikan pemeriksaan ke beberapa sistem untuk debugging dan profiling yang tersedia untuk program Linux biasa [di sini salah satu daftarnya] , misalnya itu akan menghasilkan yang berguna berdasarkan valgrind terutama untuk men-debug memori atau sysprof ke profil seluruh sistem:
Untuk sysprof:
Dan setelah memilih cabang sub-proses yang menurut Anda menarik.
Untuk Valgrind:
Dengan beberapa gym lagi, tampaknya itu mungkin untuk membuat terlihat untuk Valgrind beberapa program yang biasa kita install dari biner (misalnya OpenOffice ).
Dimungkinkan untuk membaca dari FAQ valgrind yang
Valgrind
akan membuat profil proses anak jika diminta secara khusus.Ini akan melakukannya dengan opsi ini diaktifkan
Referensi Tambahan:
sumber
Posting ini oleh Alan Hargreaves menjelaskan metode pembuatan profil skrip Bourne shell menggunakan penyedia DTrace. Sejauh yang saya tahu ini berfungsi dengan Solaris dan OpenSolaris (lihat: / bin / sh DTrace Provider ).
Jadi diberikan skrip dtrace berikut (
sh_flowtime.d
di GH berdasarkan aslinya ):Anda dapat melacak aliran fungsi termasuk waktu delta.
Output sampel:
Kemudian menggunakan
sort -nrk7
perintah, Anda dapat mengurutkan output untuk menunjukkan panggilan yang paling banyak digunakan.Saya tidak mengetahui adanya probe penyedia yang tersedia untuk shell lain, jadi lakukan beberapa penelitian (pencarian GitHub?) Atau jika Anda ingin menginvestasikan waktu, Anda dapat menulisnya berdasarkan contoh sh yang ada : (lihat: Cara mengaktifkan sh DTrace Provider? ).
sumber