首页 > 解决方案 > 为什么 Python3.6 显示出比 3.7 更好的结果?

问题描述

我有以下代码(它没用,仅用于性能测试)

class A:
    def __init__(self, i):
        self.i = i

start = datetime.now()
foo = {}
for i in range(10000000):
    foo[i] = A(i)

print('\nSpent: [ {} ] seconds!'.format((datetime.now()-start).total_seconds()))

问题是,当我使用 Python3.7 运行它时,我得到以下结果

Spent: [ 7.644764 ] seconds!

但是当我用 Python3.6 运行它时

Spent: [ 6.521555 ] seconds!

所以问题是,我是否误解了某些东西,或者旧的 python 更快,我应该使用旧的?

UPD:正如评论中所建议的,我使用timeit了模块,这里是结果

python3.7 -m timeit '"-".join(str(n) for n in range(2000000))'
1 loop, best of 5: 499 msec per loop

python3.6 -m timeit '"-".join(str(n) for n in range(2000000))'
10 loops, best of 3: 405 msec per loop

3.7的结果timeit仍然很糟糕,真的比 3.6 慢吗?

标签: pythonpython-3.xperformanceperformance-testing

解决方案


你的计时方法有缺陷。在 6-7 秒内,现代操作系统不会让 Python 独占访问 CPU,其他事情也在发生,因为操作系统在进程之间切换,为正在写入的文件刷新磁盘缓冲区,执行预定的网络事件等。

您还生成了很多都加载到内存中的对象,因此 Python 必须向操作系统询问要分配的额外内存页面。这取决于您的计算机当时正在执行的其他内容,可以提供多快的内存。您似乎第二次运行 Python 3.6,因此很容易释放并重新分配给 Python 3.7 运行的内存仍可用于 3.6 运行,并且最近释放的内存更容易为操作系统重新分配。

接下来,您使用了一个相当不精确的挂钟计时器来计时您的表演。datetime.now()对于想要知道当前时间的人来说很好,但对于测量性能来说并不好。对于后一项任务,Python 可以使用更好、更专业的时钟。Python 本身也有一个称为垃圾收集器的后台进程,它也需要一些时间来完成它的工作,这会影响 Python 执行你给它的任务的方式。

相反,您需要将 Python 必须在此处解决的不同问题分离到单独的测试中。在受控情况下运行这些单独的测试,使用准确的时钟,并尽可能多地禁用分心。多次运行这些测试,然后取平均时间(如果你只有一个可用的聚合)或多次重复的最佳时间。

Python为此提供了一个库,名为timeit. 使用它只创建实例,而不是将它们全部存储在字典中。如前所述,内存分配取决于操作系统的时间,而不是 Python 的。确保不断重复您的测试;如果仅您真的无法信任时间时-m timeit运行测试,请减少在基准测试中完成的工作。

接下来,如果您的目标是在一般性能方面比较 Python 3.6 和 3.7,而不是特定的微基准,那么您将需要进行广泛的测试。从 3.x 到 3.x+1 版本,东西一直在变化。不要基于单个字符串连接或实例创建测试。并且知道 Python 开发人员已经完成了所有这些工作。请参阅https://speed.python.org/了解核心团队用于监控性能的一整套基准测试和计时,或参阅PyPerformance 套件了解另一个此类基准测试。


推荐阅读