I've always been amazed/frustrated with how long it takes to simply output to the terminal with a print statement. After some recent painfully slow logging I decided to look into it and was quite surprised to find that almost all the time spent is waiting for the terminal to process the results.
我一直对用print语句输出到终端所花费的时间感到惊讶/沮丧。在最近经历了一些痛苦而缓慢的日志记录之后,我决定研究它,并很惊讶地发现几乎所有花费的时间都在等待终端处理结果。
Can writing to stdout be sped up somehow?
给stdout写信能不能快一点?
I wrote a script ('print_timer.py
' at the bottom of this question) to compare timing when writing 100k lines to stdout, to file, and with stdout redirected to /dev/null
. Here is the timing result:
我编写了一个脚本('print_timer ')。在写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
Wow. To make sure python isn't doing something behind the scenes like recognizing that I reassigned stdout to /dev/null or something, I did the redirection outside the script...
哇。为了确保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
So it isn't a python trick, it is just the terminal. I always knew dumping output to /dev/null sped things up, but never figured it was that significant!
这不是python的把戏,只是终端。我一直都知道,将输出转储到/dev/null会加快速度,但我从来没有想到这有多么重要!
It amazes me how slow the tty is. How can it be that writing to physical disk is WAY faster than writing to the "screen" (presumably an all-RAM op), and is effectively as fast as simply dumping to the garbage with /dev/null?
让我惊讶的是,这辆车真慢。为什么写到物理磁盘要比写到“屏幕”(大概是一个全ram操作)快得多,并且有效地和用/dev/null转储到垃圾中一样快?
This link talks about how the terminal will block I/O so it can "parse [the input], update its frame buffer, communicate with the X server in order to scroll the window and so on"... but I don't fully get it. What can be taking so long?
这个链接讨论了终端将如何阻塞I/O,这样它就可以“解析(输入),更新它的帧缓冲区,与X服务器通信以滚动窗口等等”。但我不完全理解。为什么要花这么长时间?
I expect there is no way out (short of a faster tty implementation?) but figure I'd ask anyway.
我期望没有出路(除了更快的实现吗?)
UPDATE: after reading some comments I wondered how much impact my screen size actually has on the print time, and it does have some significance. The really slow numbers above are with my Gnome terminal blown up to 1920x1200. If I reduce it very small I get...
更新:在阅读了一些评论后,我想知道我的屏幕尺寸实际上对打印时间有多大的影响,它确实有一定的意义。上面的数字非常慢,我的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
That is certainly better (~4x), but doesn't change my question. It only adds to my question as I don't understand why the terminal screen rendering should slow down an application writing to stdout. Why does my program need to wait for screen rendering to continue?
这当然更好(~4x),但是不能改变我的问题。它只增加了我的问题,因为我不明白为什么终端屏幕呈现会减慢编写stdout的应用程序。为什么我的程序需要等待屏幕渲染继续?
Are all terminal/tty apps not created equal? I have yet to experiment. It really seems to me like a terminal should be able to buffer all incoming data, parse/render it invisibly, and only render the most recent chunk that is visible in the current screen configuration at a sensible frame rate. So if I can write+fsync to disk in ~0.1 seconds, a terminal should be able to complete the same operation in something of that order (with maybe a few screen updates while it did it).
是不是所有的终端/tty应用程序都不平等?我还没有实验。在我看来,终端应该能够缓冲所有传入的数据,不可见地解析/呈现它,并且只以合理的帧速率呈现当前屏幕配置中可见的最近的块。因此,如果我可以在0.1秒内将+fsync写入磁盘,那么终端就应该能够按照相同的顺序完成相同的操作(可能还需要进行一些屏幕更新)。
I'm still kind of hoping there is a tty setting that can be changed from the application side to make this behaviour better for programmer. If this is strictly a terminal application issue, then this maybe doesn't even belong on *?
我仍然希望有一个可以从应用程序方面更改的tty设置,使这种行为对程序员更好。如果这是一个严格的终端应用程序问题,那么这甚至不属于*?
What am I missing?
我缺少什么?
Here is the python program used to generate the timing:
下面是用于生成计时的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
6 个解决方案
#1
132
How can it be that writing to physical disk is WAY faster than writing to the "screen" (presumably an all-RAM op), and is effectively as fast as simply dumping to the garbage with /dev/null?
为什么写到物理磁盘要比写到“屏幕”(大概是一个全ram操作)快得多,并且有效地和用/dev/null转储到垃圾中一样快?
Congratulations, you have just discovered the importance of I/O buffering. :-)
恭喜您,您刚刚发现了I/O缓冲的重要性。:-)
The disk appears to be faster, because it is highly buffered: all Python's write()
calls are returning before anything is actually written to physical disk. (The OS does this later, combining many thousands of individual writes into a big, efficient chunks.)
磁盘看起来更快,因为它具有高度缓冲:所有Python的write()调用都在实际写入物理磁盘之前返回。(OS稍后会这么做,将成千上万的个人写合并成一个大的、高效的块。)
The terminal, on the other hand, does little or no buffering: each individual print
/ write(line)
waits for the full write (i.e. display to output device) to complete.
另一方面,终端几乎不做缓冲:每个单独的打印/写(行)都等待完整的写(即显示到输出设备)完成。
To make the comparison fair, you must make the file test use the same output buffering as the terminal, which you can do by modifying your example to:
为了使比较公平,您必须使文件测试使用与终端相同的输出缓冲,您可以将示例修改为:
fp = file("out.txt", "w", 1) # line-buffered, like stdout
[...]
for x in range(lineCount):
fp.write(line)
os.fsync(fp.fileno()) # wait for the write to actually complete
I ran your file writing test on my machine, and with buffering, it also 0.05s here for 100,000 lines.
我在我的机器上运行了您的文件编写测试,使用缓冲,它在这里也有0。05行10万行。
However, with the above modifications to write unbuffered, it takes 40 seconds to write only 1,000 lines to disk. I gave up waiting for 100,000 lines to write, but extrapolating from the previous, it would take over an hour.
但是,由于上面的修改是没有缓冲的,所以只需要40秒就可以将1000行写入磁盘。我放弃了等待10万行的写作,但根据之前的推测,这需要一个多小时。
That puts the terminal's 11 seconds into perspective, doesn't it?
这样就能看清航站楼的11秒了,不是吗?
So to answer your original question, writing to a terminal is actually blazingly fast, all things considered, and there's not a lot of room to make it much faster (but individual terminals do vary in how much work they do; see Russ's comment to this answer).
所以,要回答你最初的问题,写到终端实际上是非常快的,考虑到所有的因素,没有太多的空间让它更快(但是每个终端做的工作是不同的;参见Russ对这个答案的评论)。
(You could add more write buffering, like with disk I/O, but then you wouldn't see what was written to your terminal until after the buffer gets flushed. It's a trade-off: interactivity versus bulk efficiency.)
(您可以添加更多的写缓冲,比如使用磁盘I/O,但是直到缓冲区被刷新之后,您才会看到写到终端的内容。这是一种权衡:交互性与批量效率。
#2
75
Thanks for all the comments! I've ended up answering it myself with your help. It feels dirty answering your own question, though.
谢谢大家的评论!我自己回答了你的帮助。不过,回答你自己的问题会让你觉得很脏。
Question 1: Why is printing to stdout slow?
问题1:为什么打印速度慢?
Answer: Printing to stdout is not inherently slow. It is the terminal you work with that is slow. And it has pretty much zero to do with I/O buffering on the application side (eg: python file buffering). See below.
答:打印到stdout本身并不慢。它是你工作的终端,速度很慢。它与应用程序端的I/O缓冲几乎没有关系(例如:python文件缓冲)。见下文。
Question 2: Can it be sped up?
问题2:可以加快速度吗?
Answer: Yes it can, but seemingly not from the program side (the side doing the 'printing' to stdout). To speed it up, use a faster different terminal emulator.
答:是的,可以,但似乎不是从程序方面(从打印到stdout的那一方)。要加快它,使用一个更快的不同的终端模拟器。
Explanation...
解释……
I tried a self-described 'lightweight' terminal program called wterm
and got significantly better results. Below is the output of my test script (at the bottom of the question) when running in wterm
at 1920x1200 in on the same system where the basic print option took 12s using gnome-terminal:
我尝试了一个自称“轻量级”的终端程序wterm,结果明显更好。下面是我的测试脚本(在问题的底部)的输出,它在wterm中运行于1920x1200,在相同的系统中,基本打印选项使用了gnome-terminal的12s:
----- timing summary (100k lines each) ----- print : 0.261 s write to file (+fsync) : 0.110 s print with stdout = /dev/null : 0.050 s
0.26s is MUCH better than 12s! I don't know whether wterm
is more intelligent about how it renders to screen along the lines of how I was suggesting (render the 'visible' tail at a reasonable frame rate), or whether it just "does less" than gnome-terminal
. For the purposes of my question I've got the answer, though. gnome-terminal
is slow.
0.26比12s好多了!我不知道wterm是否更聪明地按照我的建议(以合理的帧率显示“可见”的尾部)来显示,或者它仅仅比gnome-terminal“做得更少”。为了我的问题,我已经得到了答案。gnome终端是缓慢的。
So - If you have a long running script that you feel is slow and it spews massive amounts of text to stdout... try a different terminal and see if it is any better!
所以——如果你有一个运行时间很长的脚本,你觉得它运行缓慢,而且它会向stdout输出大量的文本……尝试不同的终端,看看是否更好!
Note that I pretty much randomly pulled wterm
from the ubuntu/debian repositories. This link might be the same terminal, but I'm not sure. I did not test any other terminal emulators.
注意,我几乎是从ubuntu/debian库中随机抽取了wterm。这个链接可能是同一个终端,但我不确定。我没有测试任何其他终端模拟器。
Update: Because I had to scratch the itch, I tested a whole pile of other terminal emulators with the same script and full screen (1920x1200). My manually collected stats are here:
更新:因为我不得不挠痒,我测试了一大堆其他的终端模拟器,它们都有相同的脚本和全屏(1920x1200)。我手动收集的统计数据如下:
wterm 0.3s aterm 0.3s rxvt 0.3s mrxvt 0.4s konsole 0.6s yakuake 0.7s lxterminal 7s xterm 9s gnome-terminal 12s xfce4-terminal 12s vala-terminal 18s xvt 48s
The recorded times are manually collected, but they were pretty consistent. I recorded the best(ish) value. YMMV, obviously.
记录的时间是手工收集的,但它们是相当一致的。我记录了最好的价值。很明显,YMMV。
As a bonus, it was an interesting tour of some of the various terminal emulators available out there! I'm amazed my first 'alternate' test turned out to be the best of the bunch.
作为奖励,这是一次有趣的旅行,参观了一些不同的终端模拟器!我很惊讶我的第一个“备用”测试竟然是最好的。
#3
12
Your redirection probably does nothing as programs can determine whether their output FD points to a tty.
你的重定向可能什么也不做,因为程序可以确定他们的输出FD是否指向一个tty。
It's likely that stdout is line buffered when pointing to a terminal (the same as C's stdout
stream behaviour).
当指向终端时,stdout很可能是行缓冲的(与C的stdout流行为相同)。
As an amusing experiment, try piping the output to cat
.
作为一个有趣的实验,可以尝试将输出发送给cat。
I've tried my own amusing experiment, and here are the results.
我自己做了个有趣的实验,结果如下。
$ python test.py 2>foo
...
$ cat foo
-----
timing summary (100k lines each)
-----
print : 6.040 s
write to file : 0.122 s
print with stdout = /dev/null : 0.121 s
$ python test.py 2>foo |cat
...
$ cat foo
-----
timing summary (100k lines each)
-----
print : 1.024 s
write to file : 0.131 s
print with stdout = /dev/null : 0.122 s
#4
3
I can't talk about the technical details because I don't know them, but this doesn't surprise me: the terminal was not designed for printing lots of data like this. Indeed, you even provide a link to a load of GUI stuff that it has to do every time you want to print something! Notice that if you call the script with pythonw
instead, it does not take 15 seconds; this is entirely a GUI issue. Redirect stdout
to a file to avoid this:
我不能谈论技术细节,因为我不了解它们,但这并不让我感到惊讶:终端不是为打印大量这样的数据而设计的。实际上,您甚至提供了一个到GUI内容负载的链接,每当您想要打印一些东西时,它就必须这么做!注意,如果用pythonw调用脚本,它不会花15秒;这完全是一个GUI问题。将stdout重定向到文件,以避免以下情况:
import contextlib, io
@contextlib.contextmanager
def redirect_stdout(stream):
import sys
sys.stdout = stream
yield
sys.stdout = sys.__stdout__
output = io.StringIO
with redirect_stdout(output):
...
#5
1
Printing to the terminal is going to be slow. Unfortunately short of writing a new terminal implementation I can't really see how you'd speed this up significantly.
打印到终端会很慢。不幸的是,由于没有编写新的终端实现,我无法真正看到如何显著加快这个速度。
#6
1
In addition to the output probably defaulting to a line-buffered mode, output to a terminal is also causing your data to flow into a terminal and serial line with a maximum throughput, or a pseudo-terminal and a separate process that is handling a display event loop, rendering characters from some font, moving display bits to implement a scrolling display. The latter scenario is probably spread over multiple processes (e.g. telnet server/client, terminal app, X11 display server) so there are context switching and latency issues too.
除了输出可能违约line-buffered模式,输出到终端也是造成数据流入终端和串行线最大吞吐量,或者伪终端和一个单独的进程处理显示事件循环,呈现一些字体,字符显示比特实现滚动显示。后一种场景可能分布在多个进程(例如telnet服务器/客户端、终端应用程序、X11显示服务器),因此也存在上下文切换和延迟问题。
#1
132
How can it be that writing to physical disk is WAY faster than writing to the "screen" (presumably an all-RAM op), and is effectively as fast as simply dumping to the garbage with /dev/null?
为什么写到物理磁盘要比写到“屏幕”(大概是一个全ram操作)快得多,并且有效地和用/dev/null转储到垃圾中一样快?
Congratulations, you have just discovered the importance of I/O buffering. :-)
恭喜您,您刚刚发现了I/O缓冲的重要性。:-)
The disk appears to be faster, because it is highly buffered: all Python's write()
calls are returning before anything is actually written to physical disk. (The OS does this later, combining many thousands of individual writes into a big, efficient chunks.)
磁盘看起来更快,因为它具有高度缓冲:所有Python的write()调用都在实际写入物理磁盘之前返回。(OS稍后会这么做,将成千上万的个人写合并成一个大的、高效的块。)
The terminal, on the other hand, does little or no buffering: each individual print
/ write(line)
waits for the full write (i.e. display to output device) to complete.
另一方面,终端几乎不做缓冲:每个单独的打印/写(行)都等待完整的写(即显示到输出设备)完成。
To make the comparison fair, you must make the file test use the same output buffering as the terminal, which you can do by modifying your example to:
为了使比较公平,您必须使文件测试使用与终端相同的输出缓冲,您可以将示例修改为:
fp = file("out.txt", "w", 1) # line-buffered, like stdout
[...]
for x in range(lineCount):
fp.write(line)
os.fsync(fp.fileno()) # wait for the write to actually complete
I ran your file writing test on my machine, and with buffering, it also 0.05s here for 100,000 lines.
我在我的机器上运行了您的文件编写测试,使用缓冲,它在这里也有0。05行10万行。
However, with the above modifications to write unbuffered, it takes 40 seconds to write only 1,000 lines to disk. I gave up waiting for 100,000 lines to write, but extrapolating from the previous, it would take over an hour.
但是,由于上面的修改是没有缓冲的,所以只需要40秒就可以将1000行写入磁盘。我放弃了等待10万行的写作,但根据之前的推测,这需要一个多小时。
That puts the terminal's 11 seconds into perspective, doesn't it?
这样就能看清航站楼的11秒了,不是吗?
So to answer your original question, writing to a terminal is actually blazingly fast, all things considered, and there's not a lot of room to make it much faster (but individual terminals do vary in how much work they do; see Russ's comment to this answer).
所以,要回答你最初的问题,写到终端实际上是非常快的,考虑到所有的因素,没有太多的空间让它更快(但是每个终端做的工作是不同的;参见Russ对这个答案的评论)。
(You could add more write buffering, like with disk I/O, but then you wouldn't see what was written to your terminal until after the buffer gets flushed. It's a trade-off: interactivity versus bulk efficiency.)
(您可以添加更多的写缓冲,比如使用磁盘I/O,但是直到缓冲区被刷新之后,您才会看到写到终端的内容。这是一种权衡:交互性与批量效率。
#2
75
Thanks for all the comments! I've ended up answering it myself with your help. It feels dirty answering your own question, though.
谢谢大家的评论!我自己回答了你的帮助。不过,回答你自己的问题会让你觉得很脏。
Question 1: Why is printing to stdout slow?
问题1:为什么打印速度慢?
Answer: Printing to stdout is not inherently slow. It is the terminal you work with that is slow. And it has pretty much zero to do with I/O buffering on the application side (eg: python file buffering). See below.
答:打印到stdout本身并不慢。它是你工作的终端,速度很慢。它与应用程序端的I/O缓冲几乎没有关系(例如:python文件缓冲)。见下文。
Question 2: Can it be sped up?
问题2:可以加快速度吗?
Answer: Yes it can, but seemingly not from the program side (the side doing the 'printing' to stdout). To speed it up, use a faster different terminal emulator.
答:是的,可以,但似乎不是从程序方面(从打印到stdout的那一方)。要加快它,使用一个更快的不同的终端模拟器。
Explanation...
解释……
I tried a self-described 'lightweight' terminal program called wterm
and got significantly better results. Below is the output of my test script (at the bottom of the question) when running in wterm
at 1920x1200 in on the same system where the basic print option took 12s using gnome-terminal:
我尝试了一个自称“轻量级”的终端程序wterm,结果明显更好。下面是我的测试脚本(在问题的底部)的输出,它在wterm中运行于1920x1200,在相同的系统中,基本打印选项使用了gnome-terminal的12s:
----- timing summary (100k lines each) ----- print : 0.261 s write to file (+fsync) : 0.110 s print with stdout = /dev/null : 0.050 s
0.26s is MUCH better than 12s! I don't know whether wterm
is more intelligent about how it renders to screen along the lines of how I was suggesting (render the 'visible' tail at a reasonable frame rate), or whether it just "does less" than gnome-terminal
. For the purposes of my question I've got the answer, though. gnome-terminal
is slow.
0.26比12s好多了!我不知道wterm是否更聪明地按照我的建议(以合理的帧率显示“可见”的尾部)来显示,或者它仅仅比gnome-terminal“做得更少”。为了我的问题,我已经得到了答案。gnome终端是缓慢的。
So - If you have a long running script that you feel is slow and it spews massive amounts of text to stdout... try a different terminal and see if it is any better!
所以——如果你有一个运行时间很长的脚本,你觉得它运行缓慢,而且它会向stdout输出大量的文本……尝试不同的终端,看看是否更好!
Note that I pretty much randomly pulled wterm
from the ubuntu/debian repositories. This link might be the same terminal, but I'm not sure. I did not test any other terminal emulators.
注意,我几乎是从ubuntu/debian库中随机抽取了wterm。这个链接可能是同一个终端,但我不确定。我没有测试任何其他终端模拟器。
Update: Because I had to scratch the itch, I tested a whole pile of other terminal emulators with the same script and full screen (1920x1200). My manually collected stats are here:
更新:因为我不得不挠痒,我测试了一大堆其他的终端模拟器,它们都有相同的脚本和全屏(1920x1200)。我手动收集的统计数据如下:
wterm 0.3s aterm 0.3s rxvt 0.3s mrxvt 0.4s konsole 0.6s yakuake 0.7s lxterminal 7s xterm 9s gnome-terminal 12s xfce4-terminal 12s vala-terminal 18s xvt 48s
The recorded times are manually collected, but they were pretty consistent. I recorded the best(ish) value. YMMV, obviously.
记录的时间是手工收集的,但它们是相当一致的。我记录了最好的价值。很明显,YMMV。
As a bonus, it was an interesting tour of some of the various terminal emulators available out there! I'm amazed my first 'alternate' test turned out to be the best of the bunch.
作为奖励,这是一次有趣的旅行,参观了一些不同的终端模拟器!我很惊讶我的第一个“备用”测试竟然是最好的。
#3
12
Your redirection probably does nothing as programs can determine whether their output FD points to a tty.
你的重定向可能什么也不做,因为程序可以确定他们的输出FD是否指向一个tty。
It's likely that stdout is line buffered when pointing to a terminal (the same as C's stdout
stream behaviour).
当指向终端时,stdout很可能是行缓冲的(与C的stdout流行为相同)。
As an amusing experiment, try piping the output to cat
.
作为一个有趣的实验,可以尝试将输出发送给cat。
I've tried my own amusing experiment, and here are the results.
我自己做了个有趣的实验,结果如下。
$ python test.py 2>foo
...
$ cat foo
-----
timing summary (100k lines each)
-----
print : 6.040 s
write to file : 0.122 s
print with stdout = /dev/null : 0.121 s
$ python test.py 2>foo |cat
...
$ cat foo
-----
timing summary (100k lines each)
-----
print : 1.024 s
write to file : 0.131 s
print with stdout = /dev/null : 0.122 s
#4
3
I can't talk about the technical details because I don't know them, but this doesn't surprise me: the terminal was not designed for printing lots of data like this. Indeed, you even provide a link to a load of GUI stuff that it has to do every time you want to print something! Notice that if you call the script with pythonw
instead, it does not take 15 seconds; this is entirely a GUI issue. Redirect stdout
to a file to avoid this:
我不能谈论技术细节,因为我不了解它们,但这并不让我感到惊讶:终端不是为打印大量这样的数据而设计的。实际上,您甚至提供了一个到GUI内容负载的链接,每当您想要打印一些东西时,它就必须这么做!注意,如果用pythonw调用脚本,它不会花15秒;这完全是一个GUI问题。将stdout重定向到文件,以避免以下情况:
import contextlib, io
@contextlib.contextmanager
def redirect_stdout(stream):
import sys
sys.stdout = stream
yield
sys.stdout = sys.__stdout__
output = io.StringIO
with redirect_stdout(output):
...
#5
1
Printing to the terminal is going to be slow. Unfortunately short of writing a new terminal implementation I can't really see how you'd speed this up significantly.
打印到终端会很慢。不幸的是,由于没有编写新的终端实现,我无法真正看到如何显著加快这个速度。
#6
1
In addition to the output probably defaulting to a line-buffered mode, output to a terminal is also causing your data to flow into a terminal and serial line with a maximum throughput, or a pseudo-terminal and a separate process that is handling a display event loop, rendering characters from some font, moving display bits to implement a scrolling display. The latter scenario is probably spread over multiple processes (e.g. telnet server/client, terminal app, X11 display server) so there are context switching and latency issues too.
除了输出可能违约line-buffered模式,输出到终端也是造成数据流入终端和串行线最大吞吐量,或者伪终端和一个单独的进程处理显示事件循环,呈现一些字体,字符显示比特实现滚动显示。后一种场景可能分布在多个进程(例如telnet服务器/客户端、终端应用程序、X11显示服务器),因此也存在上下文切换和延迟问题。