Untuk file yang sangat besar seperti 1GB wc -l
terjadi lambat. Apakah kita memiliki cara yang lebih cepat menghitung jumlah baris baru untuk file tertentu?
command-line
wc
prosti
sumber
sumber
0x0A
inesnya, I / O tidak diragukan lagi adalah hambatannya.wc
memiliki terlalu banyak overhead, Anda dapat mencoba menerapkannya sendiriforeach byte in file: if byte == '\n': linecount++
. Jika diimplementasikan dalam C atau assembler saya tidak berpikir itu akan menjadi lebih cepat, kecuali mungkin dalam ruang kernel pada RTOS dengan prioritas tertinggi (atau bahkan menggunakan interupsi untuk itu - Anda tidak dapat melakukan hal lain dengan sistem. .. baiklah, saya ngelantur ;-))time wc -l some_movie.avi
pada file yang tidak di-cache, menghasilkan5172672 some_movie.avi -- real 0m57.768s -- user 0m0.255s -- sys 0m0.863s
. Yang pada dasarnya membuktikan @ thrig benar, I / O menghancurkan kinerja Anda dalam hal ini.time wc -l some_large_file_smaller_than_cache
dua kali berturut-turut dengan cepat dan lihat seberapa cepat operasi kedua, lalutime wc -l some_large_file_larger_than_cache
dan lihat bagaimana waktu tidak berubah di antara proses yang berjalan. Untuk file ~ 280MB di sini, waktunya berubah dari 1,7 detik menjadi 0,2 detik, tetapi untuk file 2GB adalah 14 detik dua kali./usr/bin/time wc -l <file>
dikatakan? Apa perangkat keras Anda? Apakah lebih cepat jika Anda menjalankan perintah berulang kali? Kami benar-benar memerlukan informasi lebih lanjut;)Jawaban:
Anda dapat mencoba menulis dalam C:
Simpan dalam mis.
wcl.c
, Kompilasi mis. Dengangcc wcl.c -O2 -o wcl
dan jalankan denganIni menemukan baris baru ditaburi dalam file 1GB di sistem saya di sekitar 370ms (berjalan berulang). (Meningkatkan ukuran buffer sedikit meningkatkan waktu, yang diharapkan - BUFSIZ harus mendekati optimal). Ini sangat sebanding dengan ~ 380ms yang saya dapatkan
wc -l
.Mmaping memberi saya waktu yang lebih baik sekitar 280ms , tetapi tentu saja memiliki keterbatasan untuk dibatasi pada file nyata (tidak ada FIFOS, tidak ada input terminal, dll.):
Saya membuat file pengujian dengan:
dan menambahkan beberapa baris baru uji dengan:
dan hex editor.
sumber
for
loop OpenMP ) sehingga beberapa kemajuan dapat dibuat sementara satu utas terhenti menunggu input. Tetapi di sisi lain, itu mungkin menghambat penjadwalan I / O, jadi yang bisa saya rekomendasikan adalah mencobanya, dan ukur!read()
Versi dapat mengambil manfaat dari membaca-depan.Anda dapat meningkatkan solusi yang disarankan oleh @pskocik dengan mengurangi jumlah panggilan
read
. Ada banyak panggilan untuk membacaBUFSIZ
potongan dari file 1Gb. Pendekatan yang biasa dilakukan adalah dengan meningkatkan ukuran buffer:BUFSIZ
adalah 8192. Dengan program asli, itu 120 ribu operasi baca. Anda mungkin dapat membeli buffer input 1Mb untuk menguranginya dengan faktor 100.Saat membandingkan berbagai pendekatan, Anda mungkin perlu diingat bahwa beberapa sistem (seperti Linux) menggunakan sebagian besar memori mesin Anda yang tidak digunakan sebagai cache disk. Beberapa waktu yang lalu (hampir 20 tahun yang lalu, disebutkan dalam FAQ keji ), saya bingung dengan hasil yang tidak terduga baik dari algoritma paging (tidak terlalu baik) yang telah saya kembangkan untuk menangani kondisi memori rendah dalam editor teks. Dijelaskan kepada saya bahwa itu berjalan cepat karena program ini bekerja dari buffer memori yang digunakan untuk membaca file, dan bahwa hanya jika file tersebut dibaca ulang atau ditulis akan ada perbedaan dalam kecepatan.
Hal yang sama berlaku untuk
mmap
(dalam kasus lain masih dalam daftar tugas saya untuk dimasukkan ke dalam FAQ, pengembang melaporkan hasil yang sangat baik dalam skenario di mana cache disk adalah alasan sebenarnya untuk perbaikan). Mengembangkan tolok ukur membutuhkan waktu dan perhatian untuk menganalisis alasan kinerja yang baik (atau buruk).Bacaan lebih lanjut:
sumber
dd
, menggunakan buffer 1MB lebih lambat dari 8KB. Nilai default 8KB untuk wc sebenarnya dipilih dengan cukup baik, itu akan mendekati optimal untuk berbagai sistem.