为什么我的函数在 IDLE 中比 python 的打印函数快? [英] Why is my function faster than python's print function in IDLE?

查看:54
本文介绍了为什么我的函数在 IDLE 中比 python 的打印函数快?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不久前写了这个函数:

I wrote this function a while back:

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

我测试了它:

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)

事实证明,它只是在 IDLE 中更快,而不是在 cmd 中.我知道 IDLE 为 sys.stdoutsys.stdinsys.stderr 创建了自己的对象,但我不明白为什么它只是减慢 python 的内置 print 函数.这个答案说内置的print函数是用c编写的.因为我的函数需要从 python 字节码编译成机器码,所以这不应该让它更快吗?

It turns out that it is only faster in IDLE and not 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. This answer says that the built in print function is written in c. Shouldn't that make it faster as my function needs to be compiled from python bytecode into machine code?

我使用的是 Python 3.7.9 和 IDLE 版本 3.7.9

I am using Python 3.7.9 and IDLE version 3.7.9

推荐答案

TheLizard,感谢您报告和修改您的实验.作为 IDLE 维护者,我关心 IDLE 速度.我注意到打印到屏幕有时比在 Python 终端/控制台 REPL 中慢得多.在后者中,Python 与屏幕窗口在同一进程中执行,并且 screen.write 直接写入屏幕缓冲区.另一方面,IDLE 在单独的进程中执行用户代码.在该过程中,替换 sys.stdout 通过套接字将输出发送到 IDLE GUI 进程,然后调用 tkinter text.insert,后者调用写入屏幕错误的 tcl/tk 函数.但直到现在,我还没有进行适当的调查.

TheLizard, thank you for reporting and amending your experiments. As an IDLE maintainer, am concerned about IDLE speed. I noticed that printing to screen is sometimes much slower than in the Python terminal/console REPL. In the latter, Python executes in the same process as the screen window and screen.write directly writes to the screen buffer. IDLE, on the other hand, executes user code in a separate process. 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. But until now, I have not properly investigated.

我在 Win 10 机器上的 3.10.0a5 中运行了您的代码.在 REPL 中,正常和快速打印需要 0.05 秒.在 IDLE 中,他们花费了大约 1.1 和 0.3 秒.6 (.3/.05) 的因子由上面的开销解释.但是大约 3.7 (1.1/.3) 的附加系数?

I ran your code in 3.10.0a5 on my Win 10 machine. In the REPL, normal and fast print took .05 seconds. In IDLE, they took about 1.1 and .3 seconds. The factor of 6 (.3/.05) is explained by the overhead above. But the additional factor of about 3.7 (1.1/.3)?

为了测试 kaya3 的第二个假设,我定义了 s = 'a'*75 并用 s 替换了你的打印参数.在 REPL 中,时间仍然是 0.05 和 0.05.在 IDLE 中,它们大约是 0.41 和 0.31.我的结论是有一点内部打印功能开销,但 3.7 的大部分是额外的套接字到屏幕开销.当 print 写入缓冲区时,没有理由预先连接小字符串,因为多个 stdout.writes 本质上是在执行连接,无论是屏幕缓冲区还是磁盘缓冲区.

To test kaya3's 2nd hypothesis, I defined s = 'a'*75 and replaced your print arguments by s. In REPL, times are still .05 and .05. In IDLE, they are about .41 and .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. 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.

为了进一步测试这一点,我修改了测试以编写 3 个 40 行的块.REPL 时间保持不变.在 IDLE 中,它们的平均速度约为 0.058 和 0.05,与 REPL 中的速度差不多.

To further test this, I altered the test to write 3 blocks of 40 lines. The REPL times remain the same. In IDLE, they average about .058 and .05, about as fast as in the REPL.

结论:我应该记录一下,如果在为在 IDLE 中定期运行而编写的代码中打印并且关心速度,则应该先将想要显示的所有内容预先组装成一个字符串,然后只打印该字符串.IDLE 为回溯执行此操作,这就是它们显示一次全部"的原因.

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 does this for tracebacks, which is why they display 'all at once'.

这篇关于为什么我的函数在 IDLE 中比 python 的打印函数快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆