読者です 読者をやめる 読者になる 読者になる

破棄されたブログ

このブログは破棄されました。

Counter と defaultdict のパフォーマンス比較

TL;DR;

イテレータの要素をカウントするだけであれば、 defaultdict の方が高速で、 Counter の 60% から 70% くらいの時間で処理が完了する。どっかにも書いてあった気がするけど。

検証内容

os.urandom() でランダムに生成した文字列をカウントした。また、 defaultdictCounterコンストラクタシグネチャが異なり扱いにくいので、だいたい同じようなシグネチャのサブクラスを作成して用いた。また、ベンチマークには Benchmarker を利用した。

サブクラス化によるオーバヘッドで微妙にパフォーマンスが低下しているかもしれないが、こちらは未検証。

ベンチマークコード

import os
from collections import Counter, defaultdict
from benchmarker import Benchmarker


class DefaultdictCounter(defaultdict):

    def __init__(self, iterable):
        defaultdict.__init__(self, int)
        self.update(iterable)

    def update(self, iterable):
        for key in iterable:
            self[key] += 1


with Benchmarker(10000^2) as bench:
    iterable = os.urandom(2048).encode('hex')

    @bench('defaultdict')
    def _(bm):
        for _ in bm:
            DefaultdictCounter(iterable)

    @bench('Counter')
    def _(bm):
        for _ in bm:
            Counter(iterable)

結果

所要時間 (s) 比率 (%)
defaultdict 17.3687 61.3
Counter 28.3542 100.0

結論

単純にカウントしたいのであれば、 defaultdict を使ったほうが速い。Counter の機能が必要でなく、defaultdict を選択したほうがいいだろう。ただし、 defaultdict(int) よりも Counter の方が意味が自明なので、そのあたりの考慮も必要かもしれない。

あと、そういえば Pandas とかだとどうなんだろ。そもそもパフォーマンスを気にする程度のデータ量なら、Python で処理するの微妙なのではというのがある。

追記

Pandas を使ったベンチマークも追加した。

@bench('pandas')
def _(bm):
    for _ in bm:
        Series(data=(x for x in iterable)).value_counts()

まずは、文字列長 2048 でベンチマークを取った。 Pandas が defaultdict より遅いという結果になった。

## Ranking       real
defaultdict    0.7002  (100.0) ********************
pandas         1.0572  ( 66.2) *************
Counter        1.1051  ( 63.4) *************

次に、文字列長を 204,800 にしてベンチマークを取った。圧倒的じゃない我が軍は。Pandas がずば抜けて速い。もはや Counter は使い物にならない。

## Ranking       real
pandas        41.7975  (100.0) ********************
defaultdict   71.3314  ( 58.6) ************
Counter      112.4663  ( 37.2) *******

したがって、パフォーマンスを気にする程度のデータ量を扱う必要がある場合は、 Pandas を使ったほうがよい。 なんかグラフとか出したほうがいいのかもしれないけど、ベンチマーク時間かかるから誰かやって。

読みたい

Python High Performance Programming

Python High Performance Programming

広告を非表示にする