Saya punya file teks besar (1,5 G),
Saya ingin tahu apa alat tercepat dan lebih dapat diandalkan di Linux.
Saya biasanya menggunakan:
awk '!x[$0]++' file.txt
Tetapi ketika saya menggunakan htop
perintah saya melihat penggunaan memori saya meningkat.
Saya ingin tahu apa yang tercepat dan lebih dapat diandalkan untuk file besar.
uniq?
sort?
sed?
awk?
Mengapa?
time
?Jawaban:
Mari kita perhatikan bagaimana setiap solusi bekerja.
uniq
Ini mengharuskan file sudah diurutkan. Jika tidak, Anda harus mem-pipesort
dulu, artinyasort
harus membaca seluruh file ke dalam memori, menyusun ulang (O(n log n)
), dan kemudian menulisnya ke dalam pipa. Pekerjaannyauniq
sangat murah, karena hanya perlu membandingkan jalur input yang berdekatan.sort -u
Ini menggabungkan karyasort | uniq
. Ini harus mengumpulkan semua input unik ke dalam memori seperti yang dilakukanawk
skrip, tetapi juga membuang waktu untuk menyortirnya sebelum menghasilkan output. IniO(n log n)
, meskipun dalam hal inin
adalah jumlah item unik, tidak semua input. Jadi itu lebih baik daripada pipa.sed
Saya tidak yakin mengapa Anda mendaftar ini, karena saya tidak bisa memikirkan cara yang baik untuk melakukan inised
sama sekali. Mungkin jika Anda pertama kali mengurutkannya dan menyalurkannya kesed
skrip, ada cara untuk membandingkan garis yang berdekatan. Jadised
hanya akan melakukan apa yanguniq
dilakukan, danuniq
mungkin melakukannya seefisien mungkin.awk
Ini mungkin yang terbaik karena hanya melakukan sedikit pekerjaan yang diperlukan. Saat membaca setiap baris, ia melakukan pencarian hash yang efisien untuk melihat apakah garis tersebut sudah ada di memorinya, dan hanya menyimpan garis-garis unik sebagai kunci hash, dan penghitung sebagai nilainya. (Jika garis itu sebelumnya tidak ada, kondisinya akan benar, sehingga garis itu akan dicetak. Kalau tidak, garis itu tidak akan ada.) Ini menggunakanO(n)
waktu danO(uniq n)
memori.Setiap metode akan menggunakan sejumlah besar memori, baik untuk menyortir input atau melacak input yang telah dilihat sehingga mereka dapat menghapus duplikat.
sumber
awk
juga menjelaskan mengapa menggunakan jumlah memori yang meningkat. Apa pun yang melakukan pengurutan akan berakhir dengan melakukan ini juga, hanya 1) itu mungkin akan menggunakannya sekaligus, 2) itu mungkin menggunakan sedikit lebih banyak, tergantung pada jumlah kunci yang unik vs digandakan.sort
file-file sementara (dengan cara yang cerdas) untuk menghindari pengisian memori. Penggunaan memorinya terikat. Batas dibatasi dengan beberapa implementasi semacam. Lebih efisien jika membiarkan sistem menukar memori secara acak ke disk (yang juga memengaruhi aplikasi pada sistem).awk
kehabisan memori,sort
mungkin satu-satunya solusi karena telah dirancang untuk menangani ini. Di sisi lain, semua disk membaca dan menulis akan memperlambatnya, sehingga mungkin akan memakan waktu lama untuk menyelesaikannya. Jika Anda berurusan dengan data dalam jumlah besar, Anda mungkin harus menggunakan DBMS daripada file teks.O(n log n)
? Atau Anda tahu dari mana saja?Saya telah menemukan bahwa semacam itu tampaknya menjadi alat uniq tercepat seperti yang ditunjukkan di sini -> Cara tercepat untuk menghapus duplikat dalam daftar kata yang besar?
sumber
Saya hanya ingin menunjukkan bahwa gnu
uniq
tampaknya sangat lambat, bahkan pada daftar yang diurutkan.Saya baru saja mencoba mendapatkan daftar awalan direktori dari daftar nama file yang diurutkan:
sort -u tampaknya dua kali lebih cepat dari uniq, dan ini dengan sorting membaca dari stdin dan menulis ke stdout, jadi saya belum melihatnya melakukan paralelisasi. Saya tidak tahu mengapa uniq harus jauh lebih lambat daripada mengurutkan, karena tidak harus mengurutkan daftar ...
Outpuf dari perintah ini sangat kecil (ada banyak duplikat), hanya 264kb dan urutkan berakhir langsung setelah pv selesai.
Kecepatan yang sama tetap jika Anda memutar urutan perintah, aliran saya dibatasi oleh waktu cpu di sini, bukan akses disk dan cache (saya hanya memiliki 8GB RAM dan swap saya tidak digunakan)
Saya menjalankan ini pada mesin fedora 31 dengan semacam gnu coreutils dan uniq dan gnu awk; lokal diatur ke en_US.UTF-8
PEMBARUAN , karena ini sedikit menggelitik saya, saya melakukan beberapa tes lagi, mari kita potong bagian dari jalan, dan pastikan file diurutkan dengan baik
cat all_files | cut -d '/' -f 1,2,3,4 | sort -T . > test
Ini membutuhkan 8,4 menit. Tes sekarang 7.9GB besar
mari kita jalankan alat-alat ini pada file daripada di dalam pipa, ini akan memungkinkan alat-alat ini untuk melakukan beberapa optimasi, seperti sort akan multi-thread. dan juga dari SSD yang lebih cepat.
Anda mungkin tidak memperhatikan bahwa pengurutan juga mengambil banyak memori, karena ia melakukan trik cerdas dengan file temp di / tmp yang mungkin tmpfs dan akan ada di ram Anda (Coba mengurutkan file yang lebih besar daripada / tmp, Anda akan lari ke ruang angkasa masalah, itu sebabnya saya perlu flag -T pada perintah di atas)
Jadi sepertinya solusi awk Anda adalah yang tercepat dari 3 ini , dan sebenarnya menggunakan memori paling sedikit
pembaruan2 dan sekarang dengan lokal yang lebih sederhana
Kali ini uniq memenangkan perlombaan ... sebagaimana Stéphane Chazelas mengisyaratkan dalam komentar, mengatur lokal Anda ke C membuat mengurutkan dan menyatukan sejumlah besar lebih cepat!
sumber
sort
danuniq
? Lokal apa?