Bagaimana cara kerja `wc-l`?

11

Saya harus membaca file besar dan sebelum saya mulai membacanya, saya perlu mengetahui jumlah baris dalam file (yang jutaan).

Saya telah menerapkan banyak solusi dan telah menemukan satu. Tetapi selama pencarian saya, saya berpikir untuk melihat cara wc -lkerjanya. Saya tidak dapat menemukan apa pun di Google.

Meskipun saya telah menemukan solusi untuk masalah saya, saya masih ingin tahu cara wc -lkerjanya karena dapat menghitung jumlah baris file dengan 92 Juta baris dalam beberapa detik!

Bagaimana?

detraveller
sumber

Jawaban:

20

Itu membaca seluruh file dan menghitung jumlah akhir baris. Menghitung ujung garis benar-benar murah; sebagian besar waktu yang dihabiskan adalah membaca file. Jika file tersebut (sebagian besar) ada dalam cache buffer, itu akan menjadi murah juga. Kalau tidak, itu akan tergantung pada kecepatan penyimpanan file Anda.

Dengan kata lain, tidak ada sihir.

rici
sumber
Bunyinya seluruh file dan menghitung jumlah akhir baris? Untuk sampai ke akhir baris, bukankah pada dasarnya membaca seluruh baris sampai mencapai akhir? Dan itu berarti membaca seluruh file, kan?
detraveller
@detraveller: ya, ia membaca seluruh file, seperti yang saya katakan. Itu tidak membacanya baris demi baris, atau sekaligus, tetapi membaca setiap karakter dan menghitung berapa banyak dari karakter tersebut adalah karakter garis akhir.
rici
7

WC hanya membaca file dalam blok byte mentah (lebih disukai dalam kelipatan ukuran blok alami dari sistem file yang mendasarinya di mana file itu berada).
Kemudian hanya memindai melalui buffer menghitung karakter end-of-line. (Ini juga menghitung spasi, tab, umpan formulir, dan karakter khusus lainnya, kalau-kalau Anda menginginkan informasi lain selain -l output.)

Membaca dari disk adalah bagian yang mahal dalam hal kecepatan. Pemindaian buffer membutuhkan waktu lebih lama dibandingkan dengan itu.

Katakanlah Anda memiliki 90 juta baris dengan rata-rata 100 karakter per baris.
Itu sekitar 9.000.000.000 karakter atau sekitar 860 MB.
PC yang layak dengan drive SATA-3Gb / s akan melakukan itu di bawah 10 detik. Bahkan pada sistem file yang relatif lambat dengan beberapa aktivitas lain yang terjadi pada saat yang bersamaan.
Mesin yang cepat dengan beberapa penyempurnaan kinerja dan sistem file yang dioptimalkan dapat melakukannya dalam waktu kurang dari 5 detik, bahkan tanpa harus menggunakan SATA-6G dan drive SSD.

Tonny
sumber
hanya memindai melalui buffer menghitung karakter end-of-line ( \n) - "-l, --lines mencetak jumlah baris baru \ n \" - diekstraksi dariwc.c
Rahul Patil
@RahulPatil Sebagian besar implementasi melakukan lebih dari sekedar menghitung baris baru. Lihat contoh yang disebutkan di komentar atas di atas. Itu adalah sumber wc seperti yang digunakan dalam utilitas inti Linux.
Tonny
ya .. Saya telah melihat itu .. hanya saya sebutkan karena, pertanyaan tentang wc -l.. maaf ...
Rahul Patil
3

Selamat datang di dunia perangkat lunak bebas. Anda selalu dapat melihat kode sumber

Meskipun saya harus mengakui bahwa saya bukan seorang programmer C, jadi saya bukan orang yang benar-benar dapat menjelaskan kode untuk Anda (dan saya sendiri yang akan dihina).

Yang saya tahu adalah bahwa karena wc tidak membuka file itu sendiri, tetapi meminta OS untuk melakukannya, ini sangat tergantung pada OS, dan tentu saja, bagaimana file tersebut disimpan. Selain itu, saya berharap bahwa praktik pemrograman yang benar harus ada, misalnya tidak mencoba membaca file secara keseluruhan sekaligus, dll.

Alois Mahdal
sumber
Apa maksud Anda dengan mengatakan 'tidak mencoba membaca seluruh file sekaligus'?
detraveller
Maksud saya memuat file ke memori, katakanlah, ke string / array tunggal. Dalam komunitas Perl ini disebut slurping, dan ini adalah solusi cepat & kotor yang OK ketika Anda tahu Anda akan membaca beberapa baris, tetapi memasukkan file yang sangat besar ke memori sekaligus jarang merupakan ide yang bagus.
Alois Mahdal
1
Di sisi lain, Anda dapat membaca, mengatakan, 64 KiB, menghitung baris baru dan membuangnya, ulangi ... Dengan cara itu Anda akan memakan lebih dari 64 KiB paling banyak, tidak peduli seberapa besar file tersebut. (Ini kurang mudah ketika Anda menyadari bahwa baris baru dapat memiliki 2 byte dan dengan demikian menjadi terbagi antara 2 bongkahan; sekarang di situlah kesenangan dimulai)
Alois Mahdal
Tidak terlalu penting, tetapi: "karena wc tidak membuka file itu sendiri, tetapi meminta OS untuk melakukannya" - tidak yakin apa yang Anda maksud dengan itu, tapi saya ragu ini benar. Ini tentu saja membaca semua karakter dengan sendirinya.
Arjan
2
@Arjan Meskipun, untuk menjadi benar-benar benar: tidak termasuk sistem embedded, program hampir tidak benar-benar melakukan pembacaan sendiri, inti dari Kernel dan OS adalah bahwa ia melakukan pekerjaan untuk mereka. Bahkan, buka (), tutup (), baca () (baik itu Linux, Windows, socket atau file) adalah semua panggilan sistem yang program aktual tidak tahu cara kerja dalam.
Alois Mahdal