Чому gzip повільний, незважаючи на те, що продуктивність процесора та жорсткого диска не заміряється?


12

У мене є кілька файлів JSON, 20 ГБ кожен, які я хочу компресувати gzip:

gzip file1.json

Це займає одне повне ядро ​​процесора, все добре.

Він обробляє близько 25 Мб / с (зареєстрований atop), мій жорсткий диск може читати 125 Мб / с, і у мене є 3 вільних ядра процесора, тому я очікую швидкого прискореного компіляції декількох файлів паралельно. Тож я бігаю в інших терміналах:

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

Дивно, але моя пропускна здатність не збільшується; Процесор становить близько 25% на кожному ядрі, а мій HD досі читає лише зі швидкістю 25 Мб / с.

Чому і як вирішити це?

Відповіді:


16

Я дізнався це:

Причина полягає в тому, що gzipфункціонує на (з точки зору швидкості процесора порівняно з високою швидкістю пошуку в наші дні) надзвичайно низькі розміри буфера .

Він зчитує кілька КБ з вхідного файлу, стискає його і передає у вихідний файл. Зважаючи на той факт, що для цього потрібно шукати жорсткий диск, за секунди можна зробити лише кілька операцій.

Причина мого виступу не масштабувалась в тому, що вже хтось gzipшукав, як божевільний.


Я працював над цим за допомогою bufferутиліти unix :

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

Буферизуючи велику кількість вхідних даних, перш ніж надсилати їх у gzip, кількість дрібних запитів може бути різко зменшена. Варіанти:

  • -sі -mмають вказати розмір буфера (я вважаю, що він є в КБ, але не впевнений)
  • -p 100 гарантує, що дані передаються в gzip лише після того, як буфер на 100% заповнений

Запустивши чотири з них паралельно, я міг отримати пропускну здатність 4 * 25 Мб / с, як очікувалося.


Мені все ще цікаво, чому gzip не дозволяє збільшити розмір буфера - таким чином, це досить марно, якщо працювати на спінінг-диску.

EDIT : Я випробував ще кілька поведінкових програм стиснення:

  • bzip2 обробляє лише 2 Мб / с завдяки сильнішому / більш інтенсивному стисненню процесора
  • lzop Схоже, дозволяють більші буфери: 70 Мб / с на ядро, і 2 ядра можуть максимально збільшити мій HD без надмірного пошуку

Можна ddзробити те ж саме?
Саймон Куанг

@SimonKuang Я підозрюю, що ddможе зробити те саме зі своїм bs=варіантом, так.
nh2

Здається, що цікавий збіг обставин, що для одного файлу розмір блоку повністю використовував як одне ядро ​​CPU, так і IOPS накопичувача.
Дейв Л.

3

Переглянувши перші п'ять лекцій у програмі MIT OpenCourseware для 6.172: "Інженерія продуктивності програмних систем", я запустив аналізатор продуктивності Linux "perf" на помірно великий тестовий файл. Здається, що результат показує стояки конвеєра, де одна інструкція повинна чекати результату попередньої.

       │         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.  

Друга остання інструкція - це копіювання, %ecxі остання повинна почекати (зупиняючи конвеєр), поки %cxреєстр не буде готовими до використання даних. Цей конвеєр трубопроводу утримує петлю, що містить.

Це результат деякого дійсно неясного стилю програмування на «стару школу».


1

Порада, яка може перенести його на ще один рівень швидкості на багатоядерному / гіпертоковому процесорі:
(припускаючи Ubuntu)

sudo apt-get install moreutils

moreutils містить, серед іншого, "гну паралель" - яка має безліч варіантів, щоб допомогти більше використовувати ваш процесор.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.