Тройник тормозит трубопроводы?

10

Мне интересно, замедляет ли тройник трубопроводы. В конце концов, запись данных на диск происходит медленнее, чем их передача.

Дождется ли передача данных в следующий канал, пока они не будут записаны на диск? (Если нет, то, наверное, нужно поставить в очередь данные, которые были отправлены вместе, но не записаны на диск, что мне кажется маловероятным.)

$ program1 input.txt | tee intermediate-file.txt | program2 ...
Несчастный кот
источник
Нет, эта «следующая труба» - самое первое, что она пишет (также упоминается здесь ).
ManRow

Ответы:

12

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

Например, вот тривиальное использование канала pv, что приятно, поскольку отображает скорость передачи:

$ pv -s 50g -S -pteba /dev/zero | cat > /dev/null 
  50GiB 0:00:09 [ 5.4GiB/s] [===============================================>] 100%

Теперь давайте добавим teeтуда, даже не написав лишнюю копию - просто перешлем ее:

$ pv -s 50g -S -pteba /dev/zero | tee | cat > /dev/null 
  50GiB 0:00:20 [2.44GiB/s] [===============================================>] 100%            

Так что это немного медленнее, и он даже ничего не делал! Это накладные расходы на внутреннее копирование STDIN в STDOUT. (Интересно, что добавление секунды pvостается на скорости 5,19 ГБ / с, так что pvэто значительно быстрее, чем tee. pvИспользует splice(2), teeскорее всего, нет.)

В любом случае, давайте посмотрим, что произойдет, если я скажу teeзаписать файл на диск. Он запускается довольно быстро (~ 800 МБ / с), но по мере замедления продолжает замедляться - в конечном счете, до ~ 100 МБ / с, что составляет в основном 100% пропускной способности записи на диск. (Быстрый запуск происходит из-за того, что ядро ​​кэширует запись на диск, а замедление до скорости записи на диск приводит к отказу ядра в бесконечном росте кеша.)

Это имеет значение?

Выше приведен худший случай. Выше используется канал для выброса данных как можно быстрее. Единственное реальное использование, о котором я могу думать, это передача необработанных данных YUV в / из ffmpeg.

Когда вы отправляете данные с более низкой скоростью (потому что вы их обрабатываете и т. Д.), Это будет гораздо менее значительным эффектом.

derobert
источник
Хорошее объяснение
Шубхам
5

В конце концов, ничего удивительного

> POSIX говорит ,

ОПИСАНИЕ

Тройник утилита должна копировать стандартный ввод в стандартный вывод, что делает копию в ноль или более файлов. Тройник утилита не должна буфер вывода.

А также что

ОБОСНОВАНИЕ

Требование буферизации означает, что не допускается использование стандартных буферизованных или строковых записей стандарта ISO C. Это не означает, что тройник должен выполнить 1-байтовое чтение, а затем 1-байтовое.

Таким образом, без объяснения «обоснования», teeвероятно , будет считываться и записываться только то количество байтов, которое может поместиться в буфер канала за раз, сбрасывая вывод при каждой записи.

И да, в зависимости от приложения, это может быть довольно неэффективно, поэтому вы можете просто удалить / прокомментировать любой из них:
https://github.com/coreutils/coreutils/blob/master/src/tee.c#L208
https://github.com/coreutils/coreutils/blob/master/src/tee.c#L224

ManRow
источник
+1 за ссылки на исходники ответственные. Действительно ли эти части отвечают за такое поведение, чтобы удаление / комментирование их teeвыполнялось быстрее?
Хашим
1
Похоже, это было бы так! Ти переопределяет схему буферизации, которую в противном случае выбирает ОС
ManRow