Использование stdbuf: увеличение размера буфера

113
6

У меня есть awk-скрипт, отправляющий длинные строки (> 10K символов) в stdout.

Я хотел бы увеличить размер буфера, чтобы сразу записать куски этих длинных строк. Я приурочил обе трубы ниже с различными размерами -o, но никаких существенных изменений

time stdbuf -o 100MB awk -f processing.awk infile.txt | sort -k1,1 > outfile.txt
time stdbuf -o 100MB awk -f processing.awk infile.txt > outfile.txt

real/user/sys timings все очень похожи на один (+ - 10% на каждую метрику).

Мой вопрос: правильно ли я использую stdbuf? Спасибо.

ФЗ.

спросил(а) 2011-10-17T17:52:00+04:00 8 лет, 8 месяцев назад
1
Решение
77

stdbuf удается изменить буферизацию стандартных каналов ввода-вывода для выполненных команд. Тем не менее, он не (я не думаю, что это может) изменить мощность трубы в O/S. Поэтому я не ожидал увидеть разницу в производительности.

Обратите внимание, что разница в том, что с большим буфером awk конечном итоге отправит все свои данные в один чудовищный системный вызов write() (если infile.txt, измененный скриптом, сам по себе больше 100 MiB), тогда как обычно он будет писать, когда заполняется буфер от 0,5 до 8 килобайт. Однако преимущество такой огромной write() минимально; он все же должен быть сегментирован O/S для установки в трубу (если O/S не делает вещи по-другому - классически, то, что я описываю, будет правдой).

ответил(а) 2011-10-17T18:09:00+04:00 8 лет, 8 месяцев назад
53

Что stdbuf делает, это изменение буферизации в C stdlib, то есть в буфере stdin, stdout или stderr FILE*.

Он не меняет размер буфера канала в ядре. Вероятно, поэтому вы не видите никаких изменений.

Известно, что размер буфера труб не может быть изменен и довольно мал. При обработке больших файлов часто лучше писать промежуточные результаты в файлы, а не транслировать их в другое приложение. Поскольку буфер для буфера довольно мал, будет много контекстного переключения между приложениями, общающимися по трубе, накладные расходы которых могут затмевать время выполнения приложений.

ответил(а) 2011-10-17T18:10:00+04:00 8 лет, 8 месяцев назад
39

Другой способ буферизации в конвейере - использовать команду dd. Я нашел несколько случаев, когда stdbuf не работает (например: git на OSX), и полезно, чтобы выход был исчерпан, прежде чем перейти к следующему шагу конвейера. Вот пример, который будет сбрасывать 1 МБ, прежде чем отправлять что-либо, чтобы sort а также писать 1 МБ фрагментов:

awk -f processing.awk infile.txt |
dd bs=1000000 | # drain/write 1 MB chunks
sort -k1,1 > outfile.txt

Еще один интересный случай использования:

git ls-remote origin |
# obviously psuedo-awk, might print out :refs/tags/{old_versions}
awk '/filter for interesting stuff/ {massage output}' |
dd bs=1000000 2> /dev/null | # drain 1 MB and suppress block summary
xargs -n 10 git push origin

ответил(а) 2018-07-18T09:47:00+03:00 1 год, 11 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема