TL; DR - MASALAH 21118
Cerita yang panjang
Josh Rosenberg menemukan bahwa str.translate()
fungsinya sangat lambat dibandingkan dengan bytes.translate
, dia mengangkat masalah , menyatakan bahwa:
Dalam Python 3, str.translate()
biasanya merupakan pesimisasi kinerja, bukan pengoptimalan.
Mengapa str.translate()
lambat?
Alasan utama untuk str.translate()
menjadi sangat lambat adalah karena pencariannya menggunakan kamus Python.
Penggunaan maketrans
memperburuk masalah ini. Pendekatan serupa menggunakan bytes
membangun larik C yang terdiri dari 256 item untuk pencarian tabel cepat. Karenanya penggunaan Python level yang lebih tinggi dict
membuat str.translate()
dalam Python 3.4 sangat lambat.
Apa yang terjadi sekarang?
Pendekatan pertama adalah menambahkan patch kecil, translate_writer , Namun peningkatan kecepatannya tidak begitu menyenangkan. Segera patch lain fast_translate diuji dan menghasilkan hasil yang sangat bagus dengan speedup hingga 55%.
Perubahan utama seperti yang dapat dilihat dari file ini adalah pencarian kamus Python diubah menjadi pencarian tingkat C.
Kecepatannya sekarang hampir sama dengan bytes
unpatched patched
str.translate 4.55125927699919 0.7898181750006188
str.translate from bytes trans 1.8910855210015143 0.779950579000797
Catatan kecil di sini adalah bahwa peningkatan kinerja hanya menonjol dalam string ASCII.
Seperti yang disebutkan JFSebastian dalam komentar di bawah, Before 3.5, translate digunakan untuk bekerja dengan cara yang sama untuk kasus ASCII dan non-ASCII. Namun dari kasus 3.5 ASCII jauh lebih cepat.
Sebelumnya ASCII vs non-ascii biasanya hampir sama, namun sekarang kita dapat melihat perubahan besar dalam performanya.
Ini bisa menjadi peningkatan dari 71,6μs menjadi 2,33μs seperti yang terlihat dalam jawaban ini .
Kode berikut menunjukkan ini
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
Tabulasi hasil:
Python 3.4 Python 3.5
Ascii 91.2 2.3
Unicode 101 117
dict.fromkeys(ord(c) for c in '@#$')
?