Pythonで要素検索の高速化
Pythonでデータ型による要素検索の性能について調べてみました
リスト型、マップ型、セット型による要素の存在確認 (in
オペレーション)の性能を比較
- 1から1億の間の整数値を持つサイズ10万のリストをそれぞれ作成 (マップ型、セット型は値の重複ができないので、若干サイズが小さくなる)
- それぞれランダムに生成した1から1億の間の整数を1000回検索し、その時間を計測
(*) 実際のコードはブログ末に掲載
上記ベンチマークを実行すると、以下のような結果になりました。listが約1.3秒、dictとsetが約0.1ミリ秒とlistが圧倒的に遅いです。
list search (size:100000) ... 1.339225
dict search (size: 99947) ... 0.000178
set search (size: 99947) ... 0.000139
また、リストのサイズを10万から100万にすると
list search (size:1000000) ... 12.171807
dict search (size: 995006) ... 0.000237
set search (size: 995006) ... 0.000169
となり、listは10倍、dictとsetはほぼ同値となっていることから、listのin
オペレーションはO(N)、dictとsetはO(1)であることがわかります。
こちらによるとCPythonではdictとsetは実際に同様の実装のようです
ベンチマークコード
import time
import random
class count_scope:
"""時間計測用クラス"""
def __init__(self, name):
self.name = name
def __enter__(self):
self.start = time.perf_counter()
def __exit__(self, *args):
print(f'{self.name} ... {time.perf_counter() - self.start:.6f}')
def main():
r = random.Random(1) # 実行毎の結果をそろえるためにシードを指定
d_list = [r.randrange(100000000) for x in range(100000)]
d_dict = {x: 'a' for x in d_list}
d_set = set(d_list)
search_value = [r.randrange(100000000)
for k in range(1000)]
with count_scope(f"list search (size:{len(d_list)})") as p:
for x in search_value:
t = x in d_list
with count_scope(f"dict search (size:{len(d_dict)})") as p:
for x in search_value:
t = x in d_dict
with count_scope(f"set search (size:{len(d_set)})") as p:
for x in search_value:
t = x in d_set
return
if __name__ == "__main__":
main()
最近のコメント