为什么我的函数比 python 的 IDLE 打印函数快?
Why is my function faster than python's print function in IDLE?
我前阵子写过这个函数:
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.stdout
、sys.stdin
和 sys.stderr
创建了自己的对象,但我不明白为什么它只会减慢 python 的内置 print
] 功能。 回答说内置的 print
函数是用 c 语言编写的。这不应该让它更快,因为我的函数需要从 python 字节码编译成机器码吗?
我正在使用 Python 3.7.9 和 IDLE 版本 3.7.9
TheLizard,感谢您报告和修改您的实验。作为 IDLE 维护者,我很关心 IDLE 速度。我注意到打印到屏幕有时比 Python terminal/console REPL 慢得多。在后者中,Python 与屏幕 window 在同一进程中执行,而 screen.write 直接写入屏幕缓冲区。另一方面,IDLE 在单独的进程中执行用户代码。在那个过程中,替换 sys.stdout 通过套接字将输出发送到 IDLE GUI 进程,然后调用 tkinter text.insert,后者调用 tcl/tk 写入屏幕错误的函数。但是直到现在,我还没有好好调查过。
我 运行 你的代码在我的 Win 10 机器上的 3.10.0a5 中。在 REPL 中,正常和快速打印耗时 0.05 秒。在 IDLE 中,他们花费了大约 1.1 秒和 0.3 秒。上面的开销解释了因子 6 (.3/.05)。但是附加系数大约3.7(1.1/.3)?
为了检验 kaya3 的第二个假设,我定义了 s = 'a'*75
并将您的打印参数替换为 s
。在 REPL 中,时间仍然是 .05 和 .05。在 IDLE 中,它们大约为 .41 和 .31。我得出的结论是,内部打印功能有一些开销,但 3.7 的大部分是额外的套接字到屏幕开销。当 print 正在写入缓冲区时,没有理由预先连接小字符串,因为多个 stdout.writes 本质上是在进行连接,无论是屏幕缓冲区还是磁盘缓冲区。
为了进一步测试这一点,我将测试更改为编写 3 个块,每块 40 行。 REPL 时间保持不变。在 IDLE 中,它们的平均速度约为 0.058 和 0.05,与在 REPL 中一样快。
结论:我应该记录,如果一个人在 IDLE 中定期打印写入 运行 的代码并且关心速度,那么他应该先 assemble 预先 assemble 将他想要的所有内容一起显示到一个字符串中并打印该字符串。 IDLE 为回溯执行此操作,这就是它们显示 'all at once'.
的原因
我前阵子写过这个函数:
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.stdout
、sys.stdin
和 sys.stderr
创建了自己的对象,但我不明白为什么它只会减慢 python 的内置 print
] 功能。 print
函数是用 c 语言编写的。这不应该让它更快,因为我的函数需要从 python 字节码编译成机器码吗?
我正在使用 Python 3.7.9 和 IDLE 版本 3.7.9
TheLizard,感谢您报告和修改您的实验。作为 IDLE 维护者,我很关心 IDLE 速度。我注意到打印到屏幕有时比 Python terminal/console REPL 慢得多。在后者中,Python 与屏幕 window 在同一进程中执行,而 screen.write 直接写入屏幕缓冲区。另一方面,IDLE 在单独的进程中执行用户代码。在那个过程中,替换 sys.stdout 通过套接字将输出发送到 IDLE GUI 进程,然后调用 tkinter text.insert,后者调用 tcl/tk 写入屏幕错误的函数。但是直到现在,我还没有好好调查过。
我 运行 你的代码在我的 Win 10 机器上的 3.10.0a5 中。在 REPL 中,正常和快速打印耗时 0.05 秒。在 IDLE 中,他们花费了大约 1.1 秒和 0.3 秒。上面的开销解释了因子 6 (.3/.05)。但是附加系数大约3.7(1.1/.3)?
为了检验 kaya3 的第二个假设,我定义了 s = 'a'*75
并将您的打印参数替换为 s
。在 REPL 中,时间仍然是 .05 和 .05。在 IDLE 中,它们大约为 .41 和 .31。我得出的结论是,内部打印功能有一些开销,但 3.7 的大部分是额外的套接字到屏幕开销。当 print 正在写入缓冲区时,没有理由预先连接小字符串,因为多个 stdout.writes 本质上是在进行连接,无论是屏幕缓冲区还是磁盘缓冲区。
为了进一步测试这一点,我将测试更改为编写 3 个块,每块 40 行。 REPL 时间保持不变。在 IDLE 中,它们的平均速度约为 0.058 和 0.05,与在 REPL 中一样快。
结论:我应该记录,如果一个人在 IDLE 中定期打印写入 运行 的代码并且关心速度,那么他应该先 assemble 预先 assemble 将他想要的所有内容一起显示到一个字符串中并打印该字符串。 IDLE 为回溯执行此操作,这就是它们显示 'all at once'.
的原因