Python sys.intern字典查找无性能提升:用法有误还是测试有问题?
sys.intern对字典查找性能的测试疑问
我好奇Python的sys.intern对字典查找的性能提升效果,为此实现了两组测试代码:
未使用字符串驻留的测试
import random from uuid import uuid4 keys = [str(uuid4()) for _ in range(1_000_000)] values = [random.random() for _ in range(1_000_000)] my_dict = dict(zip(keys, values)) keys_sample = random.choices(keys, k=50_000) def get_values(d, ks): return [d[k] for k in ks]
使用IPython测试结果:
%timeit get_values(my_dict, keys_sample) 8.92 ms ± 17.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
使用字符串驻留的测试
import sys import random from uuid import uuid4 keys = [sys.intern(str(uuid4())) for _ in range(1_000_000)] values = [random.random() for _ in range(1_000_000)] my_dict = dict(zip(keys, values)) keys_sample = random.choices(keys, k=50_000) def get_values(d, ks): return [d[k] for k in ks]
测试结果:
%timeit get_values(my_dict, keys_sample) 8.83 ms ± 17.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
两种情况无显著差异,我尝试增大字典规模和采样量,结果仍持平。请问我是否错误使用了sys.intern,还是测试存在缺陷?
问题分析
你的测试没有体现出sys.intern的优势,核心问题出在测试用例的设计上:
你用来查找的
keys_sample是直接从字典已有的keys列表中选取的,不管有没有调用sys.intern,这些采样的key和字典中的key都是同一个内存对象。字典查找时,当哈希值匹配后,会先做对象身份比较(is),如果是同一个对象就直接命中,不需要再逐字符比较字符串内容。这种场景下,sys.intern完全没发挥作用。sys.intern的性能收益体现在:当你用内容相同但内存地址不同的字符串去字典中查找时,intern过的字符串会让这些重复内容的字符串指向同一个对象,此时查找时的身份比较会直接通过,避免了耗时的逐字符字符串相等校验。
修正后的测试方案
要验证sys.intern的效果,需要构造“内容相同但独立创建的字符串”作为查找键,比如:
# 未使用intern的测试修改版 import random from uuid import uuid4, UUID keys = [str(uuid4()) for _ in range(1_000_000)] values = [random.random() for _ in range(1_000_000)] my_dict = dict(zip(keys, values)) # 重新生成与原key内容相同但新的字符串对象 keys_sample = [str(UUID(k)) for k in random.choices(keys, k=50_000)] def get_values(d, ks): return [d[k] for k in ks]
# 使用intern的测试修改版 import sys import random from uuid import uuid4, UUID keys = [sys.intern(str(uuid4())) for _ in range(1_000_000)] values = [random.random() for _ in range(1_000_000)] my_dict = dict(zip(keys, values)) # 重新生成与原key内容相同但新的字符串对象,同时intern keys_sample = [sys.intern(str(UUID(k))) for k in random.choices(keys, k=50_000)] def get_values(d, ks): return [d[k] for k in ks]
此时再运行%timeit,就能看到两组测试的性能差异——使用sys.intern的版本会因为字符串身份直接匹配,避免逐字符比较,从而更快完成查找。
你没有错误使用sys.intern,只是测试场景没有触发它能发挥作用的条件。
内容的提问来源于stack exchange,提问作者Sergi
相关产品推荐
相关产品推荐

