← На главную

Буферизация по времени ускоряет вывод в терминал

05.11.2026 15:25 · hackernews

Крис Уэллик предлагает улучшить традиционную line-buffered output. При fully buffered выводе данные накапливаются до заполнения буфера или явного flush, а на терминале обычно включается line buffering: завершённая строка отправляется пользователю сразу. За оперативность приходится платить большим количеством мелких write, из-за чего неинтерактивные программы с обильным выводом иногда быстрее работают при перенаправлении в файл или pipe.

Примером служит Info-ZIP unzip. Печать имени каждого распакованного файла может занимать больше времени, чем сама работа с архивом из множества мелких файлов. Автор нередко прерывал процесс и перезапускал его с quiet-режимом, потому что это было быстрее продолжения. В собственном tugz он сохранил видимый список файлов, но устранил связанную с ним задержку.

Реализации line buffering отличаются деталями, но общий принцип одинаков. glibc может выполнять write для каждой строки даже внутри одной исходной строки C, а CPython сбрасывает буфер, если после очередного append в нём оказался newline, иногда отправляя часть незавершённой строки. При последовательной печати множества коротких записей такой подход упускает возможность объединить их.

Автор предлагает ориентироваться не на newline, а на реальную цель: не задерживать вывод надолго. Для этого в буфер добавляется deadline. После появления данных устанавливается короткое время по monotonic clock, а проверка между небольшими этапами работы выполняет flush, если срок истёк. Величину порядка 100 мс человек практически не замечает.

Схема напоминает Nagle’s algorithm: вызовы, которые не знают о буфере, объединяются без отдельного потока. Если tugz успевает обработать несколько файлов внутри одного deadline, их имена отправляются одним write. Если работа занимает больше времени, накопленный вывод регулярно показывается пользователю. Интерфейс программы не меняется, а выигрыш получается за счёт меньшего числа системных вызовов. Для реализации нужны deadline в структуре буфера и явные проверки между короткими участками вычислений.

Читать оригинал →