[解決済み] 辞書とオブジェクト - どちらがより効率的か、そしてその理由は?
質問
Pythonでは、メモリ使用量とCPU消費量の観点から、DictionaryとObjectのどちらがより効率的ですか?
背景 Pythonに膨大な量のデータを読み込まなければならない。私は、単なるフィールドコンテナであるオブジェクトを作成しました。4Mのインスタンスを作り、辞書に入れるのに10分程度、メモリは6GB程度で完了しました。辞書が出来上がると、アクセスは瞬きするほど簡単です。
例です。 パフォーマンスを確認するために、同じことをする2つの簡単なプログラムを書きました。1つはオブジェクトを使い、もう1つは辞書を使っています。
オブジェクト(実行時間約18秒)。
class Obj(object):
def __init__(self, i):
self.i = i
self.l = []
all = {}
for i in range(1000000):
all[i] = Obj(i)
辞書(実行時間〜12秒)。
all = {}
for i in range(1000000):
o = {}
o['i'] = i
o['l'] = []
all[i] = o
質問です。 私は何か間違ったことをしているのでしょうか、それとも辞書の方がオブジェクトよりも速いのでしょうか?もし本当に辞書の方が性能が良いのなら、誰かその理由を説明してください。
どのように解決するのですか?
あなたは
__slots__
?
から ドキュメント :
デフォルトでは、新旧両方のスタイルのクラスのインスタンスは、属性ストレージのための辞書を持ちます。これは、非常に少数のインスタンス変数を持つオブジェクトのためにスペースを浪費します。大量のインスタンスを作成する場合、スペースの消費は深刻になる可能性があります。
デフォルトを上書きするには
__slots__
を定義することで上書きできます。この場合__slots__
宣言は一連のインスタンス変数を受け取り、各インスタンスに各変数の値を保持するのに十分なスペースを確保します。スペースが節約されるのは__dict__
は各インスタンスに作成されないため、スペースが節約されます。
では、これはメモリだけでなく時間も節約できるのでしょうか?
私のコンピュータで3つのアプローチを比較したところ。
test_slots.pyを実行します。
class Obj(object):
__slots__ = ('i', 'l')
def __init__(self, i):
self.i = i
self.l = []
all = {}
for i in range(1000000):
all[i] = Obj(i)
test_obj.pyです。
class Obj(object):
def __init__(self, i):
self.i = i
self.l = []
all = {}
for i in range(1000000):
all[i] = Obj(i)
test_dict.pyです。
all = {}
for i in range(1000000):
o = {}
o['i'] = i
o['l'] = []
all[i] = o
test_namedtuple.py (2.6でサポート):
import collections
Obj = collections.namedtuple('Obj', 'i l')
all = {}
for i in range(1000000):
all[i] = Obj(i, [])
ベンチマークを実行する(CPython 2.5を使用)。
$ lshw | grep product | head -n 1
product: Intel(R) Pentium(R) M processor 1.60GHz
$ python --version
Python 2.5
$ time python test_obj.py && time python test_dict.py && time python test_slots.py
real 0m27.398s (using 'normal' object)
real 0m16.747s (using __dict__)
real 0m11.777s (using __slots__)
CPython 2.6.2 を使用し、名前付きタプルのテストを含む。
$ python --version
Python 2.6.2
$ time python test_obj.py && time python test_dict.py && time python test_slots.py && time python test_namedtuple.py
real 0m27.197s (using 'normal' object)
real 0m17.657s (using __dict__)
real 0m12.249s (using __slots__)
real 0m12.262s (using namedtuple)
というわけで、そうです(別に驚くことではありませんが)。
__slots__
を使うことはパフォーマンスの最適化です。名前付きタプルを使うと、同じようなパフォーマンスで
__slots__
.
関連
-
[解決済み】Flask ImportError: Flask という名前のモジュールがない
-
[解決済み] JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?
-
[解決済み] 割り当て後にリストが予期せず変更されました。その理由と防止策を教えてください。
-
[解決済み] オブジェクト名の前のシングルアンダーコアとダブルアンダーコアの意味は何ですか?
-
[解決済み] Pythonのクラスはなぜオブジェクトを継承するのですか?
-
[解決済み] オブジェクトの現在のプロパティと値をすべて表示する組み込み関数はありますか?
-
[解決済み] mixinとは何か、なぜ有用なのか?
-
[解決済み] nullはなぜオブジェクトなのか、nullとundefinedの違いは何ですか?
-
[解決済み] Scalaのオブジェクトとクラスの違い
-
[解決済み】どちらがより効率的か。ディクショナリ TryGetValue と ContainsKey+Item のどちらが効率的ですか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
opencvとpillowを用いた顔認証システム(デモあり)
-
Pythonによるjieba分割ライブラリ
-
[解決済み] [Solved] sklearn error ValueError: 入力に NaN、infinity または dtype('float64') に対して大きすぎる値が含まれている。
-
[解決済み】DataFrameのコンストラクタが正しく呼び出されない!エラー
-
[解決済み】TypeError: re.findall()でバイトのようなオブジェクトに文字列パターンを使用することはできません。)
-
[解決済み】syntaxError: 'continue' がループ内で適切に使用されていない
-
[解決済み] 'int'オブジェクトに'__getitem__'属性がない。
-
[解決済み】 AttributeError("'str' object has no attribute 'read'")
-
[解決済み】LogisticRegression: Pythonでsklearnを使用して、未知のラベルタイプ: '連続'を使用しています。
-
[解決済み] PythonでMutableな名前付きタプルは存在するのか?