Mengapa utilitas wc sangat lambat?
Ketika saya menjalankannya pada file besar, dibutuhkan sekitar 20 kali lebih lama dari md5sum:
MyDesktop:/tmp$ dd if=/dev/zero bs=1024k count=1024 of=/tmp/bigfile
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.687094 s, 1.6 GB/s
MyDesktop:/tmp$ time wc /tmp/bigfile
0 0 1073741824 /tmp/bigfile
real 0m45.969s
user 0m45.424s
sys 0m0.424s
MyDesktop:/tmp$ time md5sum /tmp/bigfile
cd573cfaace07e7949bc0c46028904ff /tmp/bigfile
real 0m2.520s
user 0m2.196s
sys 0m0.316s
Ini bukan hanya kondisi tepi aneh yang disebabkan oleh file yang penuh dengan nol, saya melihat perbedaan kinerja yang sama bahkan jika file diisi dengan data acak atau file teks.
(ini ada di Ubuntu 13.04, 64 bit)
performance
wc
Johnny
sumber
sumber
Jawaban:
Jadi saya pergi ke sumbernya, dan sepertinya kelambanan dalam menangani karakter byte ganda. Intinya, untuk setiap karakter yang dibaca, perlu memanggil
mbrtowc()
untuk mencoba mengubahnya menjadi karakter lebar, maka karakter lebar itu diuji untuk melihat apakah itu pemisah kata, pemisah garis, dll.Memang, jika saya mengubah
LANG
variabel lokal saya dari defaulten_US.UTF-8
(UTF-8 adalah set karakter multibyte) dan mengaturnya ke "C
" (set karakter byte tunggal sederhana),wc
dapat menggunakan optimasi byte tunggal, yang mempercepatnya jauh, hanya membutuhkan sekitar seperempat selama sebelumnya.Selain itu, ia hanya perlu memeriksa setiap karakter jika itu menghitung kata (
-w
), panjang baris (-L
) atau karakter (-m
). Jika hanya melakukan byte dan / atau jumlah baris, itu dapat melewati penanganan karakter lebar dan kemudian berjalan sangat cepat - lebih cepat darimd5sum
.Aku berlari melalui
gprof
, dan fungsi-fungsi yang digunakan untuk menangani karakter multibyte (mymbsinit()
,mymbrtowc()
,myiswprint()
, dll) yang mengambil sekitar 30% dari waktu eksekusi saja, dan kode bahwa langkah-langkah melalui buffer jauh lebih kompleks karena harus menangani langkah-langkah berukuran variabel melalui buffer untuk karakter berukuran variabel, serta menjejalkan setiap karakter yang diselesaikan sebagian yang span buffer kembali ke awal buffer sehingga dapat ditangani di waktu berikutnya.Sekarang saya tahu apa yang harus dicari, saya menemukan beberapa posting menyebutkan lambatnya utf-8 dengan beberapa utilitas:
/programming/13913014/grepping-a-huge-file-80gb-any-way-to-speed-it-up http://dtrace.org/blogs/brendan/2011/12/08 / 2000x-performance-win /
sumber
md5sum
tidak akan pernah mengizinkan Anda untuk menghitung nomor kata danwc
tidak akan menghitung hash md5 dari file! Ini seperti bertanya mengapa mobil saya sangat lambat dibandingkan dengan mesin tik saya saat menulis teks.wc
sebenarnya terikat CPU, saat memproses karakter multi-byte.Hanya tebakan tetapi Anda agak membandingkan apel dengan jeruk sehubungan dengan apa
wc
yang dilakukan vs apamd5sum
yang dilakukan.tugas md5sum
Saat
md5sum
memproses file, ia hanya membuka file sebagai stream dan kemudian mulai menjalankan stream melalui fungsi MD5 checksum yang membutuhkan memori sangat sedikit. Ini pada dasarnya CPU & disk I / O terikat.tugas wc
Saat
wc
dijalankan, ia melakukan lebih dari sekadar mengurai file karakter pada satu waktu. Itu harus benar-benar menganalisis struktur file, garis pada satu waktu membuat penentuan di mana batas antara karakter dan apakah itu kata batas atau tidak.Contoh
Pikirkan string berikut dan bagaimana masing-masing algoritma harus bergerak melalui mereka ketika mereka menguraikannya:
Untuk MD5, itu secara sepintas bergerak melalui string ini karakter pada suatu waktu. Untuk
wc
itu harus memutuskan apa kata & garis batas dan melacak jumlah kemunculan yang dilihatnya.Diskusi wc tambahan
Saya menemukan tantangan pengkodean ini dari 2006 yang membahas implementasi
wc
di .NET. Kesulitannya cukup jelas ketika Anda melihat beberapa kode semu, jadi ini mungkin membantu untuk mulai menjelaskan mengapawc
tampaknya jauh lebih lambat daripada operasi lain.sumber
wc
menghitung banyak hal saat mem-parsing file. Itu menghitung jumlah kata, baris, dan byte saat mem-parsing file. Baca halaman manual!wc
hanya menghitung garis membatasi penguraian internal sehingga hanya menghitung hal-hal ini atau hanya melaporkan hasil garis, meskipun masih menghitung semuanya.