Утиліта для буферизації необмеженої кількості даних у трубопроводі?


14

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

$ producer | buf | consumer

По суті, я хочу, щоб утиліта, bufяка читає його вхід якомога швидше, зберігаючи його в пам'яті, щоб consumerзайняти її солодкий час, поки producerпрацює як можна швидше.


Я також хотів би бачити таке
Антті Хаапала

stdbufІнструмент , як видається sizeпараметр. Я не впевнений, чи працює він, хоча.
CMCDragonkai

Відповіді:


14

pv(Глядач труба) утиліта може це зробити (з -Bопцією) і багато іншого, в тому числі надаючи вам звіти про хід робіт.


Чи є спосіб зробити це з необмеженою кількістю даних? Як найкраще я можу сказати, мені потрібно поставити номер з -В, і якщо виробник випередить споживача, він знову сповільниться. Якщо у вас ситуація, коли є кілька споживачів ( producer | tee >(pv -cB $SIZE | consumer1) | pv -cB $SIZE2 | consumer2), це може знову спричинити уповільнення.
Даніель Н

Я використовував pvсотні разів і ніколи цього не знав. Дуже приємно, дякую!
Rucent88

pv -B 4096 -c -N in /dev/zero | pv -q -B 1000000000 | pv -B 4096 -c -N out -L 100k > /dev/null- Я очікую, що обидва pvs кінця будуть гладкими (хоча одна на 1 Гб вперед). Це не працює так, на відміну відmbuffer
Vi.

9

Ви можете використовувати dd:

producer | dd obs=64K | consumer

Він доступний на кожному Unix.


+1 за використання стандартної утиліти, хоча pvце, мабуть, приємніше використовувати (показує прогрес).
Тотор

2
Це насправді декупаж швидкості читання і запису? Здається, що ddзберігається лише один блок за один раз, тому це просто затримає все на кількість часу, необхідне для створення розміру блоку; будь ласка, виправте мене, якщо я помиляюся. Крім того, чи можна розширити цю буферизацію до необмеженого розміру, або лише що введено для розміру блоку?
Даніель Н

@DanielH - це зараз.
mikeserv

7

Погляньте на mbuffer . Він може бути буферним для пам'яті або файлу, відображеного в пам'яті ( -t/ -T).


Як я запитав у інших, чи є спосіб сказати йому, щоб він буферував стільки, скільки потрібно, чи він має максимальний розмір? Чи є концептуальна причина, чому більшість цих програм мають максимальний розмір і, наприклад, не використовують пов'язаний список менших буферів (або будь-яку іншу реалізацію черги довільного розміру)?
Даніель Н

Можливо, для запобігання помилок, що не знаходяться в пам'яті. Можливо, ви можете скористатися опцією, щоб встановити дуже великий буфер (4 Гб або близько), якщо ви цього хочете (спробуйте).
Давид Балажич

1

Це в основному негативна відповідь. Виявляється, що ні dd, ні mbuffer, ні навіть не pvпрацюють всі випадки, зокрема, якщо швидкість даних, створених виробником, може сильно відрізнятися. Я даю кілька тестів нижче. Після введення команди зачекайте приблизно 10 секунд, а потім наберіть >(щоб перейти до кінця даних, тобто чекати закінчення введення).

zsh -c 'echo foo0; sleep 3; \
        printf "Line %060d\n" {1..123456}; \
        echo foo1; sleep 5; \
        echo foo2' | dd bs=64K | less

Тут, після набору тексту >, потрібно почекати 5 секунд, тобто виробник (zsh script) заблокував перед sleep 5. Збільшення bsрозміру, наприклад, 32 М, не змінює поведінку, хоча буфер 32 МБ досить великий. Я підозрюю, що це тому, що ddблоки на виході замість того, щоб продовжуватись із введенням. Використання oflag=nonblockне є рішенням, оскільки це відкидає дані.

zsh -c 'echo foo0; sleep 3; \
        printf "Line %060d\n" {1..123456}; \
        echo foo1; sleep 5; \
        echo foo2' | mbuffer -q | less

З mbuffer, проблема полягає в тому , що перший рядок (foo0) не виникає відразу. Здається, не існує жодної опції, щоб увімкнути буферизацію рядків на вході.

zsh -c 'echo foo0; sleep 3; \
        printf "Line %060d\n" {1..123456}; \
        echo foo1; sleep 5; \
        echo foo2' | pv -q -B 32m | less

З pv, поведінка схожа на dd. Гірше, я підозрюю, що він робить неправильні речі для терміналу, оскільки іноді lessбільше не може отримувати вхід від терміналу; наприклад, з цим не можна кинути q.


0

Нестандартний хід: використання буферів сокет.

Приклад:

# echo 2000000000 > /proc/sys/net/core/wmem_max
$ socat -u system:'pv -c -N i /dev/zero',sndbuf=1000000000 - | pv -L 100k -c -N o > /dev/null
        i:  468MB 0:00:16 [ 129kB/s] [  <=>                        ]
        o: 1.56MB 0:00:16 [ 101kB/s] [       <=>                   ]

Реалізовано два додаткових інструментів для цього: buffered_pipeline і mapopentounixsocket

$ ./buffered_pipeline ! pv -i 10 -c -N 1 /dev/zero ! $((20*1000*1000)) ! pv -i 10 -L 100k -c -N 2 ! > /dev/zero
        1: 13.4MB 0:00:40 [ 103kB/s] [         <=>      ]
        2: 3.91MB 0:00:40 [ 100kB/s] [         <=>      ]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.