Mengapa gzip lambat meskipun kinerja CPU dan hard drive tidak maksimal?

14

Saya memiliki beberapa file JSON, masing-masing 20 GB, yang ingin saya kompres dengan gzip:

gzip file1.json

Ini membutuhkan satu inti CPU penuh, semuanya baik-baik saja.

Ini memproses sekitar 25 MB / s (check in atop), hard drive saya dapat membaca 125 MB / s dan saya memiliki 3 core prosesor gratis, jadi saya berharap untuk mendapatkan kecepatan ketika mengompresi beberapa file secara paralel. Jadi saya jalankan di terminal lain:

gzip file2.json
gzip file3.json
gzip file4.json

Anehnya, throughput saya tidak meningkat; CPU adalah sekitar 25% pada setiap inti, dan HD saya masih hanya membaca pada 25 MB / s.

Mengapa dan bagaimana cara mengatasinya?

nh2
sumber

Jawaban:

17

Saya menemukannya:

Alasannya adalah bahwa gzipberoperasi pada (dalam hal kecepatan CPU vs HD mencari kecepatan hari ini) ukuran buffer sangat rendah .

Bunyinya beberapa KB dari dari file input, kompres, dan siram ke file output. Mengingat fakta bahwa ini memerlukan pencarian hard drive, hanya beberapa operasi yang dapat dilakukan per detik.

Alasan kinerja saya tidak skala adalah karena sudah ada gzipyang mencari seperti orang gila.


Saya mengatasi ini dengan menggunakan bufferutilitas unix :

buffer -s 100000 -m 10000000 -p 100 < file1.json | gzip > file1.json.gz

Dengan buffering banyak input sebelum mengirimnya ke gzip, jumlah pencarian kecil dapat dikurangi secara dramatis. Opsi:

  • -sdan -muntuk menentukan ukuran buffer (saya percaya itu dalam KB, tetapi tidak yakin)
  • -p 100 memastikan bahwa data hanya diteruskan ke gzip setelah buffer diisi 100%

Menjalankan empat ini secara paralel, saya bisa mendapatkan throughput 4 * 25 MB / s, seperti yang diharapkan.


Saya masih bertanya-tanya mengapa gzip tidak memungkinkan untuk meningkatkan ukuran buffer - dengan cara ini, cukup berguna jika dijalankan pada disk berputar.

EDIT : Saya mencoba beberapa perilaku program kompresi lagi:

  • bzip2 hanya memproses 2 MB / s karena kompresinya yang lebih kuat / lebih intensif CPU
  • lzop tampaknya memungkinkan buffer yang lebih besar: 70 MB / s per core, dan 2 core dapat memaksimalkan HD saya tanpa mencari berlebihan
nh2
sumber
Bisakah ddmelakukan hal yang sama?
Simon Kuang
@SimonKuang Saya curiga ddbisa melakukan hal yang sama dengan bs=opsinya, ya.
nh2
Kedengarannya seperti kebetulan yang menarik bahwa untuk satu file ukuran blok terjadi untuk sepenuhnya memanfaatkan inti CPU tunggal dan IOPS drive.
Dave L.
3

Setelah melihat sekitar lima kuliah pertama di MIT OpenCourseware untuk 6.172: "Rekayasa Kinerja Sistem Perangkat Lunak", saya menjalankan 'perf' penganalisa kinerja Linux pada file tes yang cukup besar. Hasilnya muncul untuk menunjukkan warung pipa di mana satu instruksi harus menunggu hasil dari yang sebelumnya.

       │         while (lookahead != 0) {                                                                
       │             /* Insert the string window[strstart .. strstart+2] in the                          
       │              * dictionary, and set hash_head to the head of the hash chain:                     
       │              */                                                                                 
       │             INSERT_STRING(strstart, hash_head);                                                 
  2.07 │       movzbl 0x8096d82(%edx),%eax                                                               
  3.99 │       mov    %edx,%ebp                                                                          
       │       shl    $0x5,%ecx                                                                          
  0.03 │       and    $0x7fff,%ebp                                                                       
  1.94 │       xor    %ecx,%eax                                                                          
  1.43 │       and    $0x7fff,%eax                                                                       
  2.01 │       mov    %eax,0x805e588                                                                     
  2.40 │       add    $0x8000,%eax                                                                      
  0.88 │       movzwl 0x8062140(%eax,%eax,1),%ecx                                                        
 23.79 │       movzwl %cx,%edi                                                                           
       │             /* Find the longest match, discarding those <= prev_length.  

Instruksi terakhir kedua adalah menyalin ke %ecxdan yang terakhir harus menunggu (menghentikan jalur pipa) sampai %cxregister memiliki data yang siap digunakan. Kios pipa ini menahan loop yang berisi.

Ini adalah hasil dari gaya pemrograman C 'old-school' yang benar-benar tidak jelas.

pengguna1295785
sumber
1

Tip yang mungkin membawanya ke tingkat kecepatan lain pada CPU multi-core / hyperthreading:
(dengan asumsi Ubuntu)

sudo apt-get install moreutils

moreutils mengandung antara lain "gnu parallel" - yang memiliki banyak opsi untuk membantu menggunakan lebih banyak CPU Anda.

Hannu
sumber