Почему печать на стандартный вывод выполняется так медленно? Можно ли его ускорить?

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

Можно ли ускорить запись в стандартный вывод. каким-то образом?

Я написал сценарий (' print_timer.py ' внизу этого вопроса) для сравнения времени при записи 100 тыс. строк в стандартный вывод, в файл, и с перенаправлением стандартного вывода на / dev / null . Вот результат измерения времени:

$ python print_timer.py
this is a test
this is a test

this is a test
-----
timing summary (100k lines each)
-----
print                         :11.950 s
write to file (+ fsync)       : 0.122 s
print with stdout = /dev/null : 0.050 s

Вау. Чтобы убедиться, что python не делает что-то за кулисами, например, распознает, что я переназначил stdout на / dev / null или что-то в этом роде, я выполнил перенаправление вне сценария ...

$ python print_timer.py > /dev/null
-----
timing summary (100k lines each)
-----
print                         : 0.053 s
write to file (+fsync)        : 0.108 s
print with stdout = /dev/null : 0.045 s

Так что это не уловка с python, это просто терминал. Я всегда знал, что выгрузка вывода в / dev / null ускоряет работу, но никогда не думал, что это так важно!

Меня поражает, насколько медленным является tty. Как может быть так, что запись на физический диск происходит НАМНОГО быстрее, чем запись на «экран» (предположительно, операция с ОЗУ), и по сути так же быстро, как просто выгрузка в мусор с помощью / dev / null?

Эта ссылка говорит о том, как терминал будет блокировать ввод-вывод, чтобы он мог «анализировать [ввод], обновлять свой буфер кадра, Почему моей программе нужно ждать продолжения рендеринга экрана?

Все ли терминальные / tty-приложения созданы одинаковыми? Я еще не экспериментировал. Мне действительно кажется, что терминал должен иметь возможность буферизовать все входящие данные, анализировать / визуализировать их невидимо и отображать только самый последний фрагмент, который виден в текущей конфигурации экрана, с разумной частотой кадров. Так что, если я могу записать + fsync на диск примерно за 0,1 секунды, терминал должен иметь возможность выполнить ту же операцию в каком-то таком порядке (возможно, с несколькими обновлениями экрана, пока он это делал).

Я все еще любезен надеюсь, что есть параметр tty, который можно изменить со стороны приложения, чтобы сделать это поведение лучше для программиста. Если это проблема исключительно терминального приложения, то, возможно, это не так. они даже не принадлежат StackOverflow?

Что мне не хватает?


Вот программа на Python, используемая для генерации времени:

import time, sys, tty
import os

lineCount = 100000
line = "this is a test"
summary = ""

cmd = "print"
startTime_s = time.time()
for x in range(lineCount):
    print line
t = time.time() - startTime_s
summary += "%-30s:%6.3f s\n" % (cmd, t)

#Add a newline to match line outputs above...
line += "\n"

cmd = "write to file (+fsync)"
fp = file("out.txt", "w")
startTime_s = time.time()
for x in range(lineCount):
    fp.write(line)
os.fsync(fp.fileno())
t = time.time() - startTime_s
summary += "%-30s:%6.3f s\n" % (cmd, t)

cmd = "print with stdout = /dev/null"
sys.stdout = file(os.devnull, "w")
startTime_s = time.time()
for x in range(lineCount):
    fp.write(line)
t = time.time() - startTime_s
summary += "%-30s:%6.3f s\n" % (cmd, t)

print >> sys.stderr, "-----"
print >> sys.stderr, "timing summary (100k lines each)"
print >> sys.stderr, "-----"
print >> sys.stderr, summary

159
задан slm 28 September 2018 в 19:06
поделиться