Saya mencoba memperbarui stempel waktu ke waktu saat ini di semua file xml dalam direktori saya (secara rekursif). Saya menggunakan Mac OSX 10.8.5.
Pada sekitar 300.000 file, echo
perintah berikut ini membutuhkan waktu 10 detik :
for file in `find . -name "*.xml"`; do echo >> $file; done
Namun, touch
perintah berikut ini memakan waktu 10 menit ! :
for file in `find . -name "*.xml"`; do touch $file; done
Mengapa gema jauh lebih cepat daripada sentuhan di sini?
echo >> $file
akan ditambahkan baris baru$file
dan karenanya memodifikasinya. Saya menganggap itu akan sama untuk OS / X. Jika Anda tidak menginginkannya, gunakanecho -n >> $file
.touch `find . -name "*.xml"`
akan lebih cepat dari kedua hal di atas?>>$file
touch
berkali-kali?find . -name '*.xml' -print0 | xargs -0 touch
meminta waktu yangtouch
jauh lebih sedikit (mungkin hanya sekali). Bekerja di Linux, harus bekerja pada OS X.Jawaban:
Dalam bash,
touch
adalah biner eksternal, tetapiecho
merupakan shell bawaan :Karena
touch
biner eksternal, dan Anda memanggiltouch
sekali per file, shell harus membuat 300.000 instancetouch
, yang membutuhkan waktu lama.echo
Namun, adalah builtin shell, dan eksekusi shell builtin tidak memerlukan forking sama sekali. Sebaliknya, shell saat ini melakukan semua operasi dan tidak ada proses eksternal yang dibuat; inilah alasan mengapa jauh lebih cepat.Berikut adalah dua profil operasi shell. Anda dapat melihat bahwa banyak waktu dihabiskan untuk mengkloning proses baru saat menggunakan
touch
. Menggunakan/bin/echo
bukannya builtin shell harus menunjukkan hasil yang jauh lebih sebanding.Menggunakan sentuhan
Menggunakan gema
sumber
Seperti orang lain telah menjawab, menggunakan
echo
akan lebih cepat daritouch
yangecho
adalah perintah yang umum (meskipun tidak diperlukan untuk menjadi) built-in ke shell. Menggunakannya membuang-buang dengan overhead kernel terkait dengan menjalankan memulai proses baru untuk setiap file yang Anda dapatkantouch
.Namun, perhatikan bahwa cara tercepat untuk mencapai efek ini masih digunakan
touch
, tetapi daripada menjalankan program satu kali untuk setiap file, dimungkinkan untuk menggunakan-exec
opsi denganfind
untuk memastikan bahwa hanya dijalankan beberapa kali. Pendekatan ini biasanya akan lebih cepat karena menghindari overhead yang terkait dengan loop shell:Menggunakan
+
(sebagai lawan dari\;
) denganfind ... -exec
menjalankan perintah hanya sekali jika memungkinkan dengan setiap file sebagai argumen. Jika daftar argumen sangat panjang (seperti halnya dengan 300.000 file) beberapa jalan akan dibuat dengan daftar argumen yang memiliki panjang dekat dengan batas (ARG_MAX
pada kebanyakan sistem).Keuntungan lain dari pendekatan ini adalah bahwa ia berperilaku kuat dengan nama file yang mengandung semua karakter spasi putih yang tidak terjadi pada loop asli.
sumber
+1
untuk menunjukkan+
argumen find . Saya pikir banyak orang tidak menyadari hal ini (saya tidak).find
memiliki+
argumen. Anda bisa mendapatkan efek yang serupa dengan memipipkan kexargs
.+
bagian ini diperlukan oleh POSIX, jadi harus portabel.-print0
bukan.find
memiliki opsi yang tersedia tetapi hanya memperlakukannya seperti di;
bawah permukaan.echo
adalah shell builtin. Di sisi lain,touch
adalah biner eksternal.Shell bawaan jauh lebih cepat karena tidak ada overhead yang terlibat dalam memuat program, yaitu tidak ada
fork
/exec
terlibat. Dengan demikian, Anda akan mengamati perbedaan waktu yang signifikan ketika mengeksekusi perintah builtin vs eksternal beberapa kali.Inilah alasan mengapa utilitas seperti
time
tersedia sebagai shell bawaan.Anda bisa mendapatkan daftar lengkap shell builtins dengan mengatakan:
Seperti disebutkan di atas, menggunakan utilitas yang bertentangan dengan hasil builtin dalam penurunan kinerja yang signifikan. Berikut ini adalah statistik waktu yang diperlukan untuk membuat ~ 9000 file menggunakan builtin
echo
dan utilitasecho
:sumber
echo
biner pada sebagian besar sistem (bagi saya itu/bin/echo
), sehingga Anda dapat mencoba kembali tes pengaturan waktu menggunakan itu daripada built-in