[解決済み] なぜ[]はlist()よりも速いのですか?
質問
の処理速度を比較しました。
[]
と
list()
を発見して驚きました。
[]
実行
3倍以上速い
よりも
list()
. 同じテストを
{}
と
dict()
と、ほぼ同じ結果になりました。
[]
と
{}
は約0.128秒/100万サイクルであるのに対し
list()
と
dict()
は、それぞれ約0.428秒/100万サイクルかかりました。
これはなぜでしょうか?はたして
[]
と
{}
(そしておそらく
()
と
''
も)は直ちに空のストック・リテラルのコピーを返すのに対し、明示的に名前を付けた対応するもの(
list()
,
dict()
,
tuple()
,
str()
) が、実際に要素を持っているかどうかにかかわらず、オブジェクトを作成するために完全に行くのですか?
この2つの方法がどう違うのか、まったくわからないのですが、ぜひ調べてみたいです。 ドキュメントやSOで答えを見つけることができず、空のブラケットを検索すると、予想以上に問題があることがわかりました。
を呼び出して、タイミング結果を得ました。
timeit.timeit("[]")
と
timeit.timeit("list()")
および
timeit.timeit("{}")
と
timeit.timeit("dict()")
で、それぞれリストと辞書を比較します。Python 2.7.9を使用しています。
最近、"を発見しました。
なぜ if True は if 1 よりも遅いのですか?
のパフォーマンスを比較したものです。
if True
から
if 1
というような、リテラル対グローバルのシナリオに触れているようで、こちらも検討する価値がありそうです。
どのように解決するのか?
なぜなら
[]
と
{}
は
リテラルシンタックス
. Pythonはリストや辞書オブジェクトを作成するためだけにバイトコードを作成することができます。
>>> import dis
>>> dis.dis(compile('[]', '', 'eval'))
1 0 BUILD_LIST 0
3 RETURN_VALUE
>>> dis.dis(compile('{}', '', 'eval'))
1 0 BUILD_MAP 0
3 RETURN_VALUE
list()
と
dict()
は別のオブジェクトです。それらの名前は解決される必要があり、スタックは引数をプッシュするために関与しなければならず、フレームは後で取り出すために保存されなければならず、そして呼び出しが行われなければなりません。その分、時間がかかります。
空の場合、最低でも
LOAD_NAME
(これはグローバル名前空間だけでなく
builtins
モジュール
) に続いて
CALL_FUNCTION
これは、現在のフレームを保持する必要があります。
>>> dis.dis(compile('list()', '', 'eval'))
1 0 LOAD_NAME 0 (list)
3 CALL_FUNCTION 0
6 RETURN_VALUE
>>> dis.dis(compile('dict()', '', 'eval'))
1 0 LOAD_NAME 0 (dict)
3 CALL_FUNCTION 0
6 RETURN_VALUE
名前検索は、別途
timeit
:
>>> import timeit
>>> timeit.timeit('list', number=10**7)
0.30749011039733887
>>> timeit.timeit('dict', number=10**7)
0.4215109348297119
そこでの時間のズレは、おそらく辞書のハッシュの衝突です。これらのオブジェクトを呼び出す時間からその時間を差し引き、その結果をリテラルを使用した場合の時間と比較してみてください。
>>> timeit.timeit('[]', number=10**7)
0.30478692054748535
>>> timeit.timeit('{}', number=10**7)
0.31482696533203125
>>> timeit.timeit('list()', number=10**7)
0.9991960525512695
>>> timeit.timeit('dict()', number=10**7)
1.0200958251953125
そのため、オブジェクトを呼び出すには、さらに
1.00 - 0.31 - 0.30 == 0.39
1,000万回の呼び出しで数秒。
グローバル名をローカル名としてエイリアスすることで、グローバル検索コストを回避することができます (
timeit
を設定すると、名前にバインドされているものはすべてローカルになります)。
>>> timeit.timeit('_list', '_list = list', number=10**7)
0.1866450309753418
>>> timeit.timeit('_dict', '_dict = dict', number=10**7)
0.19016098976135254
>>> timeit.timeit('_list()', '_list = list', number=10**7)
0.841480016708374
>>> timeit.timeit('_dict()', '_dict = dict', number=10**7)
0.7233691215515137
しかし、それを克服することはできない
CALL_FUNCTION
のコストがかかります。
関連
-
[解決済み】 'numpy.float64' オブジェクトは反復可能ではない
-
[解決済み] リストのリストからフラットなリストを作るには?
-
[解決済み] リスト内のアイテムのインデックスを検索する
-
[解決済み] リストが空かどうかを確認するにはどうすればよいですか?
-
[解決済み] Pythonのリストメソッドであるappendとextendの違いは何ですか?
-
[解決済み] 割り当て後にリストが予期せず変更されました。その理由と防止策を教えてください。
-
[解決済み] B "の印刷が "#"の印刷より劇的に遅いのはなぜですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] なぜlist.join(string)ではなくstring.join(list)なのでしょうか?
-
[解決済み] <は<=より速いのか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
ピローによる動的キャプチャ認識のためのPythonサンプルコード
-
[解決済み】RuntimeWarning: invalid value encountered in double_scalars で numpy の除算ができない。
-
[解決済み] データ型が理解できない
-
[解決済み】Pythonスクリプトで「Expected 2D array, got 1D array instead: 」というエラーが発生?
-
[解決済み】インポートエラー。モジュール名 urllib2 がない
-
[解決済み】 AttributeError("'str' object has no attribute 'read'")
-
[解決済み】Flask ImportError: Flask という名前のモジュールがない
-
[解決済み】cアンダースコア式`c_`は、具体的に何をするのですか?
-
[解決済み] pythonでゼロのリスト [重複].
-
[解決済み] []と{} vs list()とdict()、どっちがいい?