Conversation
Co-authored-by: Ilya Egorov <0x42005e1f@gmail.com>
|
cc @x42005e1f @ZeroIntensity @picnixz Here is the data (based on unittests, bm_nbody, bm_fannkuch), why I choose this way.
And here is the microbenchmark Free-threadingmain vs this PR
Benchmark hidden because not significant (4): extend+del[S:] S=8, extend+del[S:] S=1024, extend+del[S:] S=4096, copy only N=1024 main vs #158602 alone
Default buildmain vs this PR
Benchmark hidden because not significant (9): extend+del[S:] S=4, S=8, S=32, S=64, S=256, S=1024, copy only N=64, N=1024, N=4096 main vs #158602 alone
Benchmark hidden because not significant (17): append+pop size=1, 3, 15, 100; append+del[-1] size=15; extend+del[S:] S=4, 16, 64, 256, 1024, 4096; copy only N=32, 64, 256, 1024, 4096, 65536 Notes on the default build: Scriptimport pyperf
INNER = 1000
def append_del_last(obj, inner=INNER):
for _ in range(inner):
obj.append(None)
del obj[-1]
def append_pop(obj, inner=INNER):
for _ in range(inner):
obj.append(None)
obj.pop()
def extend_del_slice(obj, blk, size, inner):
for _ in range(inner):
obj.extend(blk)
del obj[size:]
def copy_only(blk):
obj = blk[:]
return obj
def del_last_repeatedly(blk, r):
obj = blk[:]
for _ in r:
del obj[-1]
return obj
def del_first_repeatedly(blk, r):
obj = blk[:]
for _ in r:
del obj[0]
return obj
def main():
runner = pyperf.Runner()
for size in (0, 1, 3, 7, 15, 100):
obj = [None] * size
runner.bench_func(f"append+del[-1] size={size}", append_del_last,
obj, inner_loops=INNER)
obj = [None] * size
runner.bench_func(f"append+pop size={size}", append_pop,
obj, inner_loops=INNER)
for size in (1, 2, 4, 8, 16, 32, 64, 256, 1024, 4096):
inner = 100 if size <= 64 else 10
obj = [None] * size
blk = [None] * size
runner.bench_func(f"extend+del[S:] S={size}", extend_del_slice,
obj, blk, size, inner, inner_loops=inner)
for n in (32, 64, 256, 1024, 4096, 65536):
blk = list(range(n))
r = range(n - 1)
runner.bench_func(f"copy only N={n}", copy_only, blk)
runner.bench_func(f"del[-1] x N N={n}", del_last_repeatedly, blk, r)
for n in (256, 4096):
blk = list(range(n))
r = range(n - 1)
runner.bench_func(f"del[0] x N N={n}", del_first_repeatedly, blk, r)
if __name__ == "__main__":
main()A nice side effect of this approach is that |
del list[index]never reallocates the array #158592