Perlu saran ahli tentang perbandingan di bawah ini:
Segmen kode menggunakan loop:
for file in `cat large_file_list`
do
gzip -d $file
done
Segmen kode menggunakan ekspansi sederhana:
gzip -d `cat large_file_list`
Yang mana yang lebih cepat? Harus memanipulasi set data besar.
linux
bash
shell-script
shell
Leon
sumber
sumber
gzip
pada sistem Anda, jumlah file dalam daftar file dan ukuran file-file itu.xargs gzip -d < large_file_list
tapi hati-hati dengan spasi dalam nama file, mungkin dengantr \\n \\0 large_file_list | xargs -0 gzip -d
Jawaban:
Komplikasi
Yang berikut ini hanya akan berfungsi kadang-kadang:
Tiga masalah adalah (di
bash
dan sebagian besar kerang mirip Bourne):Ini akan gagal jika ada nama file yang memiliki tab spasi atau karakter baris baru di dalamnya (dengan asumsi
$IFS
belum dimodifikasi). Ini karena pemisahan kata shell .Itu juga mungkin gagal jika ada nama file yang memiliki karakter glob-active di dalamnya. Ini karena shell akan menerapkan ekspansi pathname ke daftar file.
Ini juga akan gagal jika nama file dimulai dengan
-
(jikaPOSIXLY_CORRECT=1
itu hanya berlaku untuk file pertama) atau jika ada nama file-
.Itu juga akan gagal jika ada terlalu banyak nama file di dalamnya untuk muat pada satu baris perintah.
Kode di bawah ini memiliki masalah yang sama dengan kode di atas (kecuali untuk yang keempat)
Solusi andal
Jika Anda
large_file_list
memiliki tepat satu nama file per baris, dan file yang dipanggil-
tidak ada di antara mereka, dan Anda menggunakan sistem GNU, maka gunakan:-d'\n'
memberitahuxargs
untuk memperlakukan setiap baris input sebagai nama file yang terpisah.-r
memberitahuxargs
untuk tidak menjalankan perintah jika file input kosong.--
memberitahugzip
bahwa argumen berikut ini tidak diperlakukan sebagai opsi meskipun mereka mulai dengan-
.-
sendiri masih akan diperlakukan sebagai-
pengganti file yang dipanggil-
sekalipun.xargs
akan menempatkan banyak nama file pada setiap baris perintah tetapi tidak terlalu banyak sehingga melebihi batas baris perintah. Ini mengurangi berapa kali suatugzip
proses harus dimulai dan karenanya membuatnya cepat. Ini juga aman: nama file juga akan dilindungi dari pemisahan kata dan perluasan pathname .sumber
for
akan — paling jauh— paling lambat. Dua metode lainnya akan sangat dekat dalam kecepatan satu sama lain.xargs
: setidaknya versi GNU memiliki--arg-file
opsi (formulir pendek-a
). Jadi orang bisa melakukannyaxargs -a large_file_list -rd'\n' gzip -d
. Secara efektif, tidak ada perbedaan, selain dari fakta bahwa<
operator shell dan akanxargs
membaca dari stdin (yang shell "link" ke file), sementara-a
akan membuatxargs
secara eksplisit membuka file tersebutparallel
untuk menjalankan banyak salinangzip
, tetapixargs
(setidaknya satu GNU), memiliki-P
saklar untuk itu juga. Pada mesin multicore yang mungkin membuat perbedaan. Tapi itu juga mungkin bahwa dekompresi benar-benar terikat I / O.Saya ragu itu akan sangat berarti.
Saya akan menggunakan loop, hanya karena saya tidak tahu berapa banyak file yang terdaftar dalam file daftar, dan saya tidak (umumnya) tahu jika ada nama file yang memiliki spasi dalam namanya. Melakukan substitusi perintah yang akan menghasilkan daftar argumen yang sangat panjang dapat menghasilkan kesalahan "Daftar argumen terlalu panjang" ketika panjang daftar yang dihasilkan terlalu panjang.
Lingkaran saya akan terlihat seperti
Ini juga akan memungkinkan saya untuk memasukkan perintah untuk memproses data setelah
gunzip
perintah. Faktanya, tergantung pada apa sebenarnya data itu dan apa yang perlu dilakukan dengannya, bahkan mungkin untuk memprosesnya tanpa menyimpannya sama sekali:(di mana
process_data
ada beberapa pipa yang membaca data yang tidak terkompresi dari input standar)Jika pemrosesan data membutuhkan waktu lebih lama daripada pengompresannya, pertanyaan apakah perulangan lebih efisien atau tidak menjadi tidak relevan.
Idealnya , saya lebih suka untuk tidak bekerja dari daftar nama file, dan alih-alih menggunakan pola globbing nama file, seperti pada
di mana
./*.gz
beberapa pola yang cocok dengan file yang relevan. Dengan cara ini kita tidak tergantung pada jumlah file atau karakter yang digunakan dalam nama file (mereka mungkin berisi baris baru atau karakter spasi putih lainnya, atau mulai dengan tanda hubung, dll.)Terkait:
sumber
Dari keduanya, file dengan semua file yang diteruskan ke satu permintaan
gzip
kemungkinan akan lebih cepat, tepatnya karena Anda hanya perlu meluncurkangzip
sekali. (Yaitu, jika perintah bekerja sama sekali, lihat jawaban lain untuk peringatan.)Tapi, saya ingin mengingatkan aturan emas optimasi : Jangan lakukan itu sebelum waktunya.
Jangan mengoptimalkan hal semacam itu sebelum Anda tahu itu masalah.
Apakah bagian dari program ini memakan waktu lama? Yah, dekompresi file besar mungkin, dan Anda harus tetap melakukannya, jadi itu mungkin tidak mudah untuk dijawab.
Mengukur. Sungguh, ini cara terbaik untuk memastikan.
Anda akan melihat hasilnya dengan mata kepala Anda sendiri (atau dengan stopwatch Anda sendiri), dan mereka akan berlaku untuk situasi Anda yang jawaban acaknya di Internet mungkin tidak. Masukkan kedua varian ke dalam skrip dan jalankan
time script1.sh
, dantime script2.sh
. (Lakukan itu dengan daftar file terkompresi kosong untuk mengukur jumlah absolut overhead.)sumber
Seberapa cepat disk Anda?
Ini harus menggunakan semua CPU Anda:
Jadi batas Anda kemungkinan akan menjadi kecepatan disk Anda.
Anda dapat mencoba menyesuaikan dengan
-j
:Ini akan menjalankan setengah dari pekerjaan secara paralel seperti perintah sebelumnya, dan akan membuat disk Anda lebih sedikit, jadi tergantung pada disk Anda, ini bisa lebih cepat.
sumber