인쇄 문으로 터미널에 간단히 출력하는 데 걸리는 시간이 항상 놀랐습니다. 최근의 고통스럽게 느린 로깅 후 나는 그것을 조사하기로 결정했고 거의 모든 시간이 터미널이 결과를 처리하기를 기다리고 있음을 알게되어 매우 놀랐 습니다.
어떻게 든 stdout에 글을 쓸 수 있습니까?
print_timer.py
100k 줄을 stdout, 파일 및 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
와. 파이썬이 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가 얼마나 느린 지 놀랍습니다. 물리 디스크에 쓰는 것이 "스크린"(아마도 모든 RAM op)에 쓰는 것보다 더 빠르며 / dev / null을 사용하여 가비지에 덤프하는 것만 큼 효과적입니까?
이 링크 는 터미널이 I / O를 차단하는 방법에 대해 설명하여 "[입력] 구문 분석, 프레임 버퍼 업데이트, X 서버와 통신하여 창을 스크롤하는 등"을 수행 할 수 있지만 ... 완전히 가져옵니다. 너무 오래 걸릴 수있는 것은 무엇입니까?
나는 더 빠른 tty 구현이 부족한 방법이 없을 것으로 예상하지만 어쨌든 묻습니다.
업데이트 : 일부 의견을 읽은 후 화면 크기가 실제로 인쇄 시간에 얼마나 큰 영향을 미치는지 궁금해했으며 약간의 중요성이 있습니다. 위의 정말 느린 숫자는 내 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 배) 내 질문은 바뀌지 않습니다. 그것은 단지 추가 터미널 화면 렌더링이 표준 출력에 쓰는 응용 프로그램을 느리게해야하는 이유를 이해하지 않는 내 질문에. 프로그램에서 화면 렌더링이 계속되기를 기다려야하는 이유는 무엇입니까?
모든 터미널 / tty 앱이 동일하게 생성되지 않습니까? 아직 실험하지 않았습니다. 터미널이 들어오는 모든 데이터를 버퍼링하고, 보이지 않게 파싱 / 렌더링하고, 현재 화면 구성에서 볼 수있는 가장 최근의 청크 만 적절한 프레임 속도로 렌더링 할 수 있어야합니다. 따라서 ~ 0.1 초 안에 디스크에 쓰거나 fsync 할 수 있다면, 터미널은 그 순서에 따라 동일한 작업을 완료 할 수 있어야합니다.
나는 여전히 프로그래머 에게이 행동을 더 잘하기 위해 응용 프로그램 측에서 변경할 수있는 tty 설정이 있기를 바라고 있습니다. 이것이 엄격하게 터미널 응용 프로그램 문제인 경우 StackOverflow에 속하지 않을 수도 있습니다.
내가 무엇을 놓치고 있습니까?
타이밍을 생성하는 데 사용되는 파이썬 프로그램은 다음과 같습니다.
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