简体   繁体   English

为什么我的 function 在 IDLE 中比 python 的 print function 快?

[英]Why is my function faster than python's print function in IDLE?

I wrote this function a while back:我不久前写了这个 function:

def faster_print(*args, sep=" ", end="\n", file=stdout):
    file.write(sep.join(map(str, args))+end)

and I tested it:我测试了它:

from sys import stdout
from time import perf_counter

def faster_print(*args, sep=" ", end="\n", file=stdout):
    file.write(sep.join(map(str, args))+end)

def time(function, *args, **kwargs):
    start = perf_counter()
    function(*args, **kwargs)
    return perf_counter()-start

def using_normal_print(number):
    for i in range(number):
        print("Hello world.", 5, 5.0, ..., str)

def using_faster_print(number):
    for i in range(number):
        faster_print("Hello world.", 5, 5.0, ..., str)

normal_time = time(using_normal_print, number=100)
faster_time = time(using_faster_print, number=100)

print("Normal print:", normal_time)
print("My print function", faster_time)

It turns out that it is only faster in IDLE and not cmd.事实证明,它只是在 IDLE 中更快,而不是 cmd。 I know that IDLE creates its own objects for sys.stdout , sys.stdin and sys.stderr but I don't get why it only slows down python's built in print function.我知道 IDLE 为sys.stdoutsys.stdinsys.stderr创建了自己的对象,但我不明白为什么它只会减慢 python 的内置print function。 This answer says that the built in print function is written in c.这个答案说内置print function 是用 c 编写的。 Shouldn't that make it faster as my function needs to be compiled from python bytecode into machine code?这不应该让它更快,因为我的 function 需要从 python 字节码编译成机器码吗?

I am using Python 3.7.9 and IDLE version 3.7.9我正在使用 Python 3.7.9 和 IDLE 版本 3.7.9

TheLizard, thank you for reporting and amending your experiments. TheLizard,感谢您报告和修改您的实验。 As an IDLE maintainer, am concerned about IDLE speed.作为 IDLE 维护者,我很关心 IDLE 速度。 I noticed that printing to screen is sometimes much slower than in the Python terminal/console REPL.我注意到打印到屏幕有时比 Python 终端/控制台 REPL 慢得多。 In the latter, Python executes in the same process as the screen window and screen.write directly writes to the screen buffer.在后者中,Python 与屏幕 window 在同一进程中执行,screen.write 直接写入屏幕缓冲区。 IDLE, on the other hand, executes user code in a separate process.另一方面,IDLE 在单独的进程中执行用户代码。 In that process, the replacement sys.stdout send output through a socket to the IDLE GUI process, which then call tkinter text.insert, which calls tcl/tk functions that write to a screen bugger.在该过程中,替换 sys.stdout 通过套接字将 output 发送到 IDLE GUI 进程,然后调用 tkinter text.insert,后者调用 tcl/tk 函数来写入屏幕窃听器。 But until now, I have not properly investigated.但直到现在,我都没有好好调查过。

I ran your code in 3.10.0a5 on my Win 10 machine.我在我的 Win 10 机器上运行了 3.10.0a5 中的代码。 In the REPL, normal and fast print took.05 seconds.在 REPL 中,正常和快速打印需要 05 秒。 In IDLE, they took about 1.1 and.3 seconds.在 IDLE 中,他们花了大约 1.1 和 3 秒。 The factor of 6 (.3/.05) is explained by the overhead above.上面的开销解释了 6 (.3/.05) 的因数。 But the additional factor of about 3.7 (1.1/.3)?但是大约 3.7 (1.1/.3) 的附加因子?

To test kaya3's 2nd hypothesis, I defined s = 'a'*75 and replaced your print arguments by s .为了测试 kaya3 的第二个假设,我定义s = 'a'*75并将您的打印 arguments 替换为s In REPL, times are still.05 and.05.在 REPL 中,时间仍然是.05 和.05。 In IDLE, they are about.41 and.31.在 IDLE 中,它们约为 41 和 31。 I conclude that there is a little internal print function overhead, but that most of the 3.7 is additional socket-to-screen overhead.我的结论是有一点内部打印 function 开销,但 3.7 的大部分是额外的套接字到屏幕开销。 When print is writing to a buffer, there is no reason to pre-join little strings, because multiple stdout.writes are essentially doing a join, whether to the screen buffer or a disk buffer.当 print 写入缓冲区时,没有理由预先连接小字符串,因为多个 stdout.write 本质上是在进行连接,无论是对屏幕缓冲区还是磁盘缓冲区。

To further test this, I altered the test to write 3 blocks of 40 lines.为了进一步测试这一点,我将测试更改为编写 3 个 40 行的块。 The REPL times remain the same. REPL 时间保持不变。 In IDLE, they average about.058 and.05, about as fast as in the REPL.在 IDLE 中,它们的平均速度约为 0.058 和 0.05,与 REPL 中的速度差不多。

Conclusion: I should document that if one prints in code written to run regularly in IDLE and one cares about speed, one should pre-assemble everything one wants displayed together into one string first and just print that string.结论:我应该记录一下,如果一个人打印为在 IDLE 中定期运行而编写的代码并且关心速度,则应该首先将想要显示的所有内容预先组装成一个字符串,然后打印该字符串。 IDLE does this for tracebacks, which is why they display 'all at once'. IDLE 为回溯执行此操作,这就是它们显示“一次全部”的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM