[解決済み] なぜPython 3.5はPython 3.4に比べてstr.translateがずっと速いのですか?
質問
与えられた文字列から不要な文字を削除するために
text.translate()
を使い、文字列から不要な文字を削除しようとしていました。
最小限のコードは
import sys
s = 'abcde12345@#@$#%$'
mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$')
print(s.translate(mapper))
期待通りに動作しています。しかし、同じプログラムをPython 3.4とPython 3.5で実行すると、大きな違いが出てきます。
タイミングを計算するコードは
python3 -m timeit -s "import sys;s = 'abcde12345@#@$#%$'*1000 ; mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$'); " "s.translate(mapper)"
Python 3.4のプログラムでは 1.3ms 一方、Python 3.5で同じプログラムを実行すると、わずか 26.4μs .
Python 3.5では、Python 3.4と比べて何が改善され、より高速になったのでしょうか?
どのように解決するのですか?
TL;DR - ISSUE 21118
長い話
ジョシュ・ローゼンバーグが発見したのは
str.translate()
関数と比較すると非常に遅いことがわかりました。
bytes.translate
を発生させた。
問題
と述べています。
Python3では
str.translate()
は通常、最適化ではなく、性能の悲観化です。
なぜ
str.translate()
が遅かったのか?
の主な理由は
str.translate()
が非常に遅い主な理由は、ルックアップがPythonの辞書に使用されていたからです。
の使い方は
maketrans
の使用はこの問題を悪化させました。同様の手法で
bytes
を使うと、テーブルを高速に検索するために 256 項目の C 配列を構築します。そのため、より高レベルのPythonの
dict
は
str.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 と 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
関連
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] なぜC++はPythonよりもstdinからの行の読み込みが遅いのですか?
-
[解決済み] Pythonのクラスはなぜオブジェクトを継承するのですか?
-
[解決済み] なぜPythonのコードは関数の中でより速く実行されるのですか?
-
[解決済み] なぜ[]はlist()よりも速いのですか?
-
[解決済み】Python 3.5の型ヒントは何ですか?
-
[解決済み】('x',)の'x'は'x'=='x'よりも速いのはなぜか?
-
[解決済み] Python 3でx**4.0がx**4より速いのはなぜですか?
-
[解決済み] テンプレートファイル変更時にFlaskアプリを再読み込みする
-
[解決済み] Python のモック patch.object を使って、他のメソッド内で呼び出されたメソッドの戻り値を変更する。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Spyderを仮想環境で動作させるには?
-
[解決済み] pyvenv-3.4 は 0 ではない終了ステータス 1 を返しました。
-
[解決済み] PythonでSelenium WebDriverを使用してテキストを取得する方法
-
[解決済み] 巨大なテキストファイルから特定の行にジャンプするには?
-
[解決済み] Pythonでnumpy.linalg.eigを使用した後の固有値と関連する固有ベクトルのソート
-
[解決済み] re.sub置換パターンにおけるキャプチャグループの後方参照への対応
-
[解決済み] TypeError: can't multiply sequence by non-int of type 'float'」と表示されるのはなぜですか?
-
[解決済み] 条件を満たした場合にNumpyの要素を置き換える
-
[解決済み] 乱数の行列を作成する簡単な方法
-
[解決済み] ネストした辞書の項目からpandasのDataFrameを構築する