该问题源自 StackOverflow 上一名网友提出的问题:
Why is copying a shuffled list much slower?
简单地描述下该问题,复制一个未打乱的list要比复制同样一个但是打乱的list要快很多:
测试代码:
from timeit import timeit
import random
a = range(10**6)
random.shuffle(a) # Remove this for the second test.
a = list(a) # Just an attempt to "normalize" the list.
for _ in range(5):
print timeit(lambda: list(a), number=10)
未打乱时:
0.058402235973
0.0505464636856
0.0509734306934
0.0526022752744
0.0513324916184
打乱后:
0.175597017661
0.173731403198
0.178601711594
0.180330912952
0.180811964451
造成这个现象的主要原因是Python的内存机制,总结相关文章,要点如下:
- 所有的Python对象都在堆中分配,甚至是interger对象
- list列表中保存着对分配在堆中的对象的指针的数组(array of pointers to the objects).
- 复制list只是一个浅操作
- 对象被一个新容器引用时,然而python需要增加引用计数,而不是仅仅复制引用。因此,Python必须访问该对象。
- 在shuffle前,在堆中分配时,相邻的index的对象在内存中是相邻的,访问时内存命中率很高;而shuffle后,新的list的相邻index的对象在内存中并不是相邻的,命中率非常差。