issue,它发现 Python 2.7 中 sum 的速度比 Python。万万没想到,除了香农计划,Python3.11竟还有这么多性能提升!( 二 )。" />

万万没想到,除了香农计划,Python3.11竟还有这么多性能提升!( 二 )


——Mark Dickinson(全文)
优化了数字 PyLongs 求和这里有一个 python/cpython/issues/68264" rel="external nofollow noreferrer">issue,它发现 Python 2.7 中 sum 的速度比 Python 3 快得多 。不幸的是,在某些条件下,3.11.0 似乎仍然如此 。
Python 2.7:
$ python -m pyperf timeit -s 'd = [0] * 10000' -- 'sum(d)'.....................Mean +- std dev: 37.4 us +- 1.1 usPython 3.10:
$ python -m pyperf timeit -s 'd = [0] * 10000' -- 'sum(d)'.....................Mean +- std dev: 52.7 us +- 1.3 usPython 3.11:
$ python -m pyperf timeit -s 'd = [0] * 10000' -- 'sum(d)'.....................Mean +- std dev: 39.0 us +- 1.0 usPython3.10 和 3.11 之间的区别在于,通过在 sum 函数的快速加法分支中内联对单个数字 PyLongs 的解包,可以提升在单个数字 PyLongs 上调用 sum 的性能 。这样做可以避免在解包时python/blob/125cdcf504a5d937b575cda3552b233dd44ba127/Python/bltinmodule.c#L2485-L2490" rel="external nofollow noreferrer">调用 python/cpython/blob/de6981680bcf6496e5996a853b2eaa700ed59b2c/Objects/longobject.c#L489" rel="external nofollow noreferrer">PyLong_AsLongAndOverflow 。
值得注意的是,python/cpython/issues/68264#issuecomment-1285351158" rel="external nofollow noreferrer">在某些情况下,Python 3.11 在整数求和时仍然明显慢于 Python 2.7 。我们希望在 Python 中通过python/ideas/discussions/147" rel="external nofollow noreferrer">实现更高效的整数,获得更多的改进 。
精简列表的扩容操作,提升了 list.append 性能在 Python 3.11 中,list.append 有了显著的性能提升(大约快 54%) 。
Python 3.10 的列表 append:
$ python -m pyperf timeit -s \'x = list(map(float, range(10_000)))' -- '[x.append(i) for i in range(10_000)]'.....................Mean +- std dev: 605 us +- 20 usPython 3.11 的列表 append:
$ python -m pyperf timeit -s \'x = list(map(float, range(10_000)))' -- '[x.append(i) for i in range(10_000)]'.....................Mean +- std dev: 392 us +- 14 us对于简单的列表推导式,也有一些小的改进:
Python 3.10:
$ python -m pyperf timeit -s \'' -- '[x for x in list(map(float, range(10_000)))]'.....................Mean +- std dev: 553 us +- 19 usPython 3.11:
$ python -m pyperf timeit -s \'' -- '[x for x in list(map(float, range(10_000)))]'.....................Mean +- std dev: 516 us +- 16 us译注:记得在 3.9 版本的时候,Python 优化了调用 list()、dict() 和 range() 等内置类型的速度,在不起眼处,竟还能持续优化!
减少了全 unicode 键的字典的内存占用这项优化令 Python 在使用全为 Unicode 键的字典时,缓存的效率更高 。这是因为使用的内存减少了,那些 Unicode 键的哈希会被丢弃,因为那些 Unicode 对象已经有哈希了 。
例如,在 64 位平台上,Python 3.10 运行结果:
>>> sys.getsizeof(dict(foo="bar", bar="foo"))232在 Python 3.11 中:
>>> sys.getsizeof(dict(foo="bar", bar="foo"))184(译注:插个题外话,Python 的 getsizeof 是一种“浅计算”,这篇《Python在计算内存时应该注意的问题?》区分了“深浅计算”,可以让你对 Python 计算内存有更深的理解 。)
提升了使用asyncio.DatagramProtocol 传输大文件的速度asyncio.DatagramProtocol 提供了一个用于实现数据报(UDP)协议的基类 。有了这个优化,使用asyncio UDP 传输大文件(比如 60 MiB)将比 Python 3.10 快 100 多倍 。
这是通过计算一次缓冲区的大小并将其存储在一个属性中来实现的 。这使得通过 UDP 传输大文件时,asyncio.DatagramProtocol 有着数量级的提速 。
PR msoxzw 的作者提供了以下的 测试脚本 。

经验总结扩展阅读