TL; DR - ВИПУСК 21118
Довга історія
Джош Розенберг з'ясував, що str.translate()
функція дуже повільна в порівнянні з функцією bytes.translate
, він порушив питання , заявивши, що:
У Python 3 str.translate()
зазвичай песимізація продуктивності, а не оптимізація.
Чому str.translate()
повільно?
Основна причина str.translate()
бути дуже повільною була в тому, що пошук знаходився в словнику Python.
Використання maketrans
зробило цю проблему ще гірше. Аналогічний підхід з використанням bytes
створює масив С з 256 елементів для швидкого пошуку таблиць. Отже, використання Python вищого рівня dict
робить str.translate()
в Python 3.4 дуже повільним.
Що сталося зараз?
Перший підхід полягав у тому, щоб додати невеликий патч, 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.
Як згадує JFSebastian у коментарі нижче, до 3.5, переклад використовувався для роботи однаково і для ASCII, і для випадків, що не належать до ASCII. Однак з 3.5 ASCII справа йде набагато швидше.
Раніше ASCII проти non-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
dict.fromkeys(ord(c) for c in '@#$')
:?