TL; DR-
ISSUE 21118
长篇故事
Josh Rosenberg发现str.translate()函数与bytes.translate相比非常慢,他提出了一个issue,说明:
In Python 3, str.translate() is usually a performance pessimization, not optimization.
为什么str.translate()慢?
str.translate()非常慢的主要原因是,查找过去是在一个Python字典。
maketrans的使用使这个问题更糟。使用bytes的类似方法构建256个项目的C数组以进行快速表查找。因此,使用更高级别的Python dict使得Python 3.4中的str.translate()非常慢。
现在发生了什么?
第一种方法是添加一个小补丁,translate_writer,但速度增加不是那么令人愉快。很快,另一个补丁fast_translate测试,它产生非常好的结果高达55%的加速。
从文件可以看出,主要的改变是Python字典查找被更改为C级别查找。
现在的速度几乎与字节相同
unpatched patched
str.translate 4.55125927699919 0.7898181750006188
str.translate from bytes trans 1.8910855210015143 0.779950579000797
这里需要注意的一点是,性能增强仅在ASCII字符串中显着。
正如J.F.Sebastian在下面的一段comment中提到的,在3.5之前,translate对于ASCII和非ASCII的情况都以相同的方式工作。但是从3.5 ASCII的情况下要快得多。
早期的ASCII和非ascii几乎相同,但是现在我们可以看到性能的巨大变化。
它可以是从71.6μs到2.33μs的改进,如在这个answer中看到的。
下面的代码演示了这一点
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