为什么Python3.6的结果比3.7好?

时间:2018-09-27 10:28:16

标签: python python-3.x performance performance-testing

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

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速度更快,应该使用旧版本的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

timeit的结果对于3.7来说仍然不好,真的比3.6慢吗?

1 个答案:

答案 0 :(得分:7)

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

您还会生成很多都已加载到内存中的对象,因此Python必须向OS询问要分配的其他内存页面。这取决于您的计算机在当时还能执行多快的速度。看来您运行了Python 3.6秒,因此很可能是释放并重新分配给Python 3.7运行的内存仍可用于3.6运行,并且最近释放的内存更易于为OS重新分配。 >

接下来,您使用了一个不太精确的挂钟计时器来对演奏进行计时。 datetime.now()对于想知道当前时间的人来说是不错的选择,而对性能的衡量则不合适。对于后者,Python有更好,更专业的时钟可用。 Python本身也有一个称为垃圾收集器的后台进程,该进程还将希望花一些时间来完成其工作,从而影响Python执行给您的任务的方式。

相反,您需要将Python必须在此处解决的不同问题分成单独的测试。在受控的情况下,使用准确的时钟并在尽可能多的干扰下禁用它们,来运行这些单独的测试。 多次运行这些测试,然后花费平均时间(如果您只有可用的汇总)或多次重复的最佳时间。

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

接下来,如果您的目标是比较一般性能条件上的Python 3.6与3.7,而不是特定的微基准,那么您将需要进行广泛的测试。 Stuff始终从3.x更改为3.x + 1版本。不要以单个字符串连接或实例创建测试为基础。并且知道Python开发人员已经已经完成了所有工作。有关核心团队用来监控性能的全套基准测试和时间安排,请参见https://speed.python.org/,或参见PyPerformance suite以获取其他此类基准测试。