2012-04-29 63 views
0

我问这个问题,因为当一个循环用重复的打印语句调试时,它会减慢我原本预期的程序。我已经习惯了这一点,但现在我很好奇,为什么会出现这种情况的技术原因?在我看来,变量的各种计算和分配将比输出字符串更昂贵。Python打印语句涉及多少条计算机指令?

+6

该问题与CPU指令无关;你的终端比CPU慢得多。 – geoffspear 2012-04-29 13:06:44

+0

谢谢大家的好的答案。我自学成才,我的教育才刚刚开始。 – talloaktrees 2012-04-29 14:59:28

回答

6

相当多的,但另一个重要的(甚至是最重要的)瓶颈与CPU无关:I/O开销。一旦字节码指令被分派并且所有参数都被转换为字符串,就会调用一个函数将这些字符串写入sys.stdout。根据您的系统,以及如何运行该程序,这可能是:

  1. 从终端仿真器上磁盘
  2. 管道内的文件
  3. ,捕捉输出一些Python对象(这就是闲置呢IIRC)完成对它的了解(捕获它,将其放入GUI等)。

在案例#1中涉及磁盘I/O,这比写入RAM容易一个数量级。与现在的CPU相比,RAM已经非常慢了。正如评论中指出的那样,由于操作系统和Python的大量缓冲,这不是一个问题,但是仍然需要时间来发布写入和(取决于我不太了解的实现细节),它可能仍然需要一些时间是否有人过早地冲洗任何缓冲区。

在情况#2,一切都保留在内存中,但它仍然是一个系统调用,一些拷贝,而另一端已读它,并用它做什么让你看到(如呈现在一个奇特的终端模拟器带有反锯齿字体,这本身就是一项复杂的任务)。因为它可能会同时发生,所以不会造成问题,但它仍然会给CPU带来负担。

如果情况#3,所有投注都关闭。它可以用bcrypt对输出进行散列,并将它发送给我们所知的所有月球。你碰巧使用IDLE?我记得有一个投诉,IDLE是(是?)缓慢重定向输出,特别是有很多尖齿。它必须捕获输出,并将其与输出连接在一起,然后让Tkinter进行渲染。

1

这不是CPU指令的问题,至少不是你的Python程序中的CPU指令。当您使用终端仿真程序(命令窗口)作为输出执行print时,要打印的字符串将被复制到内核缓冲区中,然后复制到终端进程的内存中。开销是在上下文切换(两个进程正在进行系统调用,即跳入内核模式)以及将字符串复制到内存中。

+0

实际上,通常IO上盘容易感到更快,因为,除非你'sync'所有的时间/输出数据吨,它在很大程度上缓冲,而你的程序是做其他的东西的OS可以采取刷新缓冲区的护理。另一方面,控制台上的IO不能具有最轻的缓冲,否则用户将不会及时看到程序打印的内容。 – 2012-04-29 13:16:50

+0

@MatteoItalia:你是对的,我忘了终端通常是线路缓冲。删除了有关磁盘的位,以免混淆OP。 – 2012-04-29 13:19:00

2

一个巨大的,巨大的,巨大数量,尤其是如果所述输出在屏幕上可见的,如在现代多任务系统上的终端仿真窗口。首先,如果你输出十进制数字,每个数字都有一个divmod,相对于比较而言,这是一个相对昂贵的操作。 (如果以十六进制输出,它可能会便宜一点,因为每个数字只能使用移位和屏蔽来提取。)如果输出浮点数,则需要进行更多计算;与日期和时间,有几个月的各种长度,闰年,闰秒,DST和时区都需要考虑。

但这都只是计算和逻辑,所以它是由什么来了矮。

接着Python有将输出发送文本到终端用于显示,这意味着该操作系统必须在步骤通过缓冲来传输数据,则唤醒其他过程。终端进程扫描其控制序列的输入以移动光标或更改颜色。然后,文本渲染器会扫描文本中需要特殊处理的字符:可能会应用一些合成重音符号,或者需要重新排列用于显示的一些从右到左的脚本。

一旦文本被摆出来,终端告诉它需要重绘它的窗口区域的窗口管理器和窗口管理器检查它是否是可见的 - 这可能是最小化或隐藏在其它窗口后面。终端会被告知哪个区域实际上需要绘画,最后用适当的字体和颜色绘制文字和字体的抗锯齿。窗户是否有一个酷炫的透明背景?这也必须合并。

根据不同的视窗系统上,像素然后可以去另一行通过操作系统缓冲区来一个合成器,这实际上绘制窗口内容到屏幕上,同时考虑到窗口的透明度。

最后,像素到屏幕上,他们几乎都被数以百万计的继任者被一扫之前看到的时候,当你看到输出流过去过于快速阅读。

这是惊人的,我们的电脑为我们做了多少工作要做。