为何包含大量重复简单元素的Python列表复制速度更慢?
环境信息
$ python Python 3.8.10 (default, Nov 14 2022, 12:59:47) [GCC 9.4.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> quit() $ lscpu | grep "Model name" Model name: Intel(R) Core(TM) i5-4430 CPU @ 3.00GHz $ sudo dmidecode --type memory | grep -E "^\s+(Speed|Type):" - Type: DDR3 Speed: 1600 MT/s Type: DDR3 Speed: 1600 MT/s
整数列表复制计时(展开运算符
[*x]) 在我的机器上,持续得到如下计时结果:
$ python -m timeit -s "x = list(range(250)) * 4" "[*x]" 200000 loops, best of 5: 1.54 usec per loop $ python -m timeit -s "x = [0, 1, 2, 3] * 250" "[*x]" 200000 loops, best of 5: 1.48 usec per loop $ python -m timeit -s "x = [0, 1] * 500" "[*x]" 100000 loops, best of 5: 2 usec per loop $ python -m timeit -s "x = [0] * 1000" "[*x]" 100000 loops, best of 5: 3.84 usec per loop
(这里我刻意避免使用大于255的整数,因为了解small integers的缓存机制。)
单字符字符串列表复制计时(展开运算符
[*x]) 对于单字符字符串,结果类似:
$ python -m timeit -s "x = [chr(i) for i in range(250)] * 4" "[*x]" 200000 loops, best of 5: 1.81 usec per loop $ python -m timeit -s "x = [chr(0), chr(1), chr(2), chr(3)] * 250" "[*x]" 200000 loops, best of 5: 1.5 usec per loop $ python -m timeit -s "x = [chr(0), chr(1)] * 500" "[*x]" 100000 loops, best of 5: 2.03 usec per loop $ python -m timeit -s "x = [chr(0)] * 1000" "[*x]" 100000 loops, best of 5: 3.83 usec per loop
(同样,我刻意限制字符编码点,让Python的flexible string representation选择一致的单字节字符表示。)
现象总结
所有输入列表长度均为1000,且使用相同方法复制,理论上不应出现显著的计时差异。但我发现,由同一简单元素(单字符字符串或小整数)重复组成的列表,复制时间几乎是其他情况的两倍;使用少量不同元素的列表复制速度比两种交替元素的列表更快;而使用多种不同元素的列表复制速度又稍慢一些。
列表推导式复制计时
使用较慢的复制方法时,差异依然存在,但不那么显著:
$ python -m timeit -s "x = [chr(i) for i in range(250)] * 4" "[i for i in x]" 20000 loops, best of 5: 18.2 usec per loop $ python -m timeit -s "x = [chr(0), chr(1), chr(2), chr(3)] * 250" "[i for i in x]" 20000 loops, best of 5: 17.3 usec per loop $ python -m timeit -s "x = [chr(0), chr(1)] * 500" "[i for i in x]" 20000 loops, best of 5: 17.9 usec per loop $ python -m timeit -s "x = [chr(0)] * 1000" "[i for i in x]" 20000 loops, best of 5: 19.1 usec per loop
问题
出现这种现象的原因是什么?
内容的提问来源于Stack Exchange,提问作者Karl Knechtel
相关产品推荐
相关产品推荐

