TL; DR - ISSUE 21118
漫长的故事
Josh Rosenberg发现bytes的功能与dict相比非常慢,他提出了一个问题,并指出:
在Python 3中,bytes通常是性能悲观,而不是优化。
为什么bytes慢?
bytes非常慢的主要原因是查找曾经在Python字典中。
bytes的使用使这个问题变得更糟。 使用bytes的类似方法构建了256个项目的C数组以进行快速表查找。 因此,使用更高级别的Python dict使得Python 3.4中的str.translate()非常慢。
现在发生什么事?
第一种方法是添加一个小补丁,translate_writer,然而速度提升并不令人满意。 很快又测试了另一个补丁fast_translate,它产生了高达55%加速的非常好的结果。
从文件中可以看出主要的变化是Python字典查找被更改为C级查找。
现在的速度几乎与bytes相同
unpatched patched
str.translate 4.55125927699919 0.7898181750006188
str.translate from bytes trans 1.8910855210015143 0.779950579000797
这里的一个小注意事项是性能增强仅在ASCII字符串中很突出。
正如J.F.Sebastian在下面的评论中提到的,在3.5之前,翻译曾经以相同的方式用于ASCII和非ASCII情况。 但是从3.5 ASCII情况下要快得多。
早期的ASCII与非ascii过去几乎相同,但是现在我们可以看到性能的巨大变化。
如本答案所示,它可以从71.6μs改善到2.33μs。
以下代码演示了这一点
python3.5 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
100000 loops, best of 3: 2.3 usec per loop
python3.5 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 117 usec per loop
python3 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 91.2 usec per loop
python3 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
10000 loops, best of 3: 101 usec per loop
制表结果:
Python 3.4 Python 3.5
Ascii 91.2 2.3
Unicode 101 117