Я завжди був вражений / засмучений тим, скільки часу потрібно просто вивести на термінал із заявою про друк. Після деякої недавно болісно повільної реєстрації я вирішив заглянути в це і здивовано виявив, що майже весь витрачений час чекає, поки термінал обробить результати.
Чи можна записати в stdout якось швидше?
Я написав сценарій (' print_timer.py
' внизу цього питання) для порівняння часу при написанні 100k рядків для stdout, file та stdout, переспрямованого на /dev/null
. Ось результат часу:
$ python print_timer.py
this is a test
this is a test
<snipped 99997 lines>
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
Тож це не трюк пітона, це лише термінал. Я завжди знав демпінговий вихід на / dev / null прискорив речі, але ніколи не вважав, що це таке суттєве!
Мене дивує, наскільки повільний TTY. Яким чином може бути те, що запис на фізичний диск ШЛЮШЕ швидше, ніж запис на "екран" (імовірно, всеоперативна пам'ять), і це так само швидко, як просто скидання на сміття з / dev / null?
Це посилання говорить про те, як термінал блокує введення-виведення, щоб він міг "розібрати [вхід], оновити буфер кадру, спілкуватися з сервером X для того, щоб прокрутити вікно тощо", але я не повністю отримати це. Що може зайняти так довго?
Я сподіваюся, що виходу немає (окрім швидшого впровадження?), Але я все одно попрошу.
ОНОВЛЕННЯ: прочитавши деякі коментарі, я задумався, як сильно впливає розмір екрана на час друку, і це має певне значення. Дійсно повільні цифри вище, коли мій термінал Gnome підірвався до 1920x1200. Якщо я скорочую його дуже мало, я отримую ...
-----
timing summary (100k lines each)
-----
print : 2.920 s
write to file (+fsync) : 0.121 s
print with stdout = /dev/null : 0.048 s
Це, звичайно, краще (~ 4х), але не міняє мого питання. Це лише додає мого запитання, оскільки я не розумію, чому візуалізація екрана терміналу повинна уповільнити запис програми до stdout. Чому моїй програмі потрібно чекати продовження візуалізації екрана?
Чи всі термінальні / tty додатки не створені рівними? Мені ще потрібно експериментувати. Мені справді здається, що термінал повинен мати змогу буферизувати всі вхідні дані, проаналізувати / зробити їх непомітними, а лише зробити найсвіжіший фрагмент, який видно в поточній конфігурації екрану з розумною частотою кадрів. Отже, якщо я можу записати + fsync на диск за ~ 0,1 секунди, термінал повинен мати можливість виконати ту саму операцію в чомусь такому порядку (можливо, з кількома оновленнями екрана, поки це робив).
Я все ще сподіваюся, що існує ціла настройка, яку можна змінити з боку програми, щоб зробити цю поведінку кращою для програміста. Якщо це суворо проблема термінальної програми, то, можливо, це навіть не належить до 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