Python(2.6)で、辞書をデータストアとして使用する必要があるアプリケーションを作成しています。
1つの大きな辞書を使用する方がメモリ効率が高いかどうか、またはそれを多くの(はるかに)小さな辞書に分割してから、すべての小さな辞書への参照を含む「インデックス」辞書を作成する方がメモリ効率が高いかどうかについて知りたいです。
リストや辞書には、一般的に多くのオーバーヘッドがあることを私は知っています。 pythonは、辞書/アイテムのリスト数が2の累乗になるのに十分なスペースを内部的に割り当てることをどこかで読みました。
私はpythonのように十分に新しいので、そのような他の予期しない内部の複雑さ/驚きがあるかどうかはわかりません。それは私が考慮に入れるべき平均的なユーザーには明らかではありません。
難しさの1つは、2つのシステムの力が「アイテム」をどのようにカウントするかを知ることです。各key:pairは1つのアイテムとしてカウントされますか? 100アイテムのモノリシック辞書がある場合、スペース100 ^ 2アイテムが割り当てられるため、これを知っておくことが重要です。 100個の単一アイテム辞書(1キー:ペア)がある場合、各辞書は割り当て1 ^ 2のみになります(別名、追加の割り当てはありません)?
明確にレイアウトされた情報は非常に役立ちます!
3つの提案:
1つの辞書を使用します。
それはより簡単で、より簡単であり、他の誰かがすでにこの問題をあなたのために最適化しています。実際にコードを測定し、パフォーマンスの問題をコードのこの部分まで追跡するまでは、単純で単純なことを行わない理由はありません。
後で最適化してください。
パフォーマンスが本当に心配している場合は、問題を抽象化して、最終的に使用するルックアップメカニズムをラップするクラスを作成し、このクラスを使用するコードを記述します。パフォーマンスを向上させるために他のデータ構造が必要な場合は、後で実装を変更できます。
ハッシュテーブルを読んでください。
辞書は ハッシュテーブル であり、時間やスペースのオーバーヘッドが心配な場合は、それらがどのように実装されているかを確認する必要があります。これは基本的なコンピュータサイエンスです。要するに、ハッシュテーブルは次のとおりです。
それらがO(n ^ 2)スペースであるとあなたがどこで読んだかはわかりませんが、もしそうなら、それらは広く実用的ではないでしょう今日のほとんどの言語でそのまま使用します。ハッシュテーブルのこれらのNiceプロパティには、次の2つの利点があります。
役立つ可能性のあるその他のリソースは次のとおりです。
辞書の実装を実際に最適化する必要があると思われる場合は、次のことを検討してください。
Pythonを使用している場合は、そもそもこの種のことを心配する必要はありません。コンピュータではなく、yourのニーズに最適な方法でデータ構造を構築するだけです。
これは、パフォーマンスの向上ではなく、時期尚早の最適化のスマックです。何かが実際にボトルネックになっている場合はコードのプロファイルを作成しますが、それまでは、Pythonに実行させて、基礎となるメカニズムではなく、実際のプログラミングタスクに焦点を合わせてください。
特に「シンプル」を超える理由がテストされていない場合は、「シンプル」の方が「賢い」よりも一般的に優れています。とにかく、「メモリ効率」はあいまいな用語であり、永続化、シリアル化、キャッシュ、スワッピング、および他の誰かがすでに考えている他の多くのものを検討するとき、トレードオフがあります。ほとんどの場合、あなたはそうしません。する必要があります。
「それを適切に処理する最も簡単な方法」は、ずっと後で最適化することを考えてください。
時期尚早の最適化何とか何とか、それを何とかしないでください。
私はあなたが2つの余分な割り当ての力について間違っていると思います。私はそれがちょうど2の乗数 2だと思います。 x ^ 2ではなくx * 2。
私はこの質問をさまざまなpythonメーリングリストで数回見ました。
メモリに関して、これはそのような議論の1つの言い換えバージョンです(問題の投稿は数億の整数を格納したかった):
したがって、オブジェクトが少ないほど、使用するメモリも少なくなり、実行するルックアップも少なくなります(インデックスでルックアップしてから、実際の値で2回目のルックアップを行う必要があるため) 。
他の人と同じように、プロファイルを作成してボトルネックを確認します。メンバーシップset()と値dict()を維持する方が速いかもしれませんが、より多くのメモリを使用することになります。
また、これをpython comp.lang.pythonなどの特定のリストに再投稿することをお勧めします。このリストには、私よりもはるかに知識が豊富で、あらゆる種類の有用な情報が提供されます。
辞書が大きすぎてメモリに収まらない場合は、Python用の非常に成熟したオブジェクトデータベースである [〜#〜] zodb [〜#〜] を確認することをお勧めします。
データベースの「ルート」は辞書と同じインターフェースを持っており、データ構造全体を一度にメモリにロードする必要はありません。開始キーと終了キーを指定することで、構造の一部のみを反復処理できます。
また、トランザクションとバージョン管理も提供します。
正直なところ、パフォーマンスまたはメモリ使用量のいずれの点でも、どちらの方法でも違いを区別することはできません。数千万以上のアイテムを扱っているのでない限り、パフォーマンスやメモリへの影響は単なるノイズです。
2番目の文の言い方からすると、1つの大きな辞書が最初の傾向であり、解決しようとしている問題とより密接に一致しているように見えます。それが本当なら、それで行きなさい。 Pythonについてわかることは、誰もが「正しい」と考えるソリューションは、ほとんどの場合、可能な限り明確で単純なソリューションであることが判明するということです。
多くの場合、辞書の辞書はパフォーマンス上の理由以外に役立ちます。つまり、オブジェクト自体に追加のフィールドを持たずにデータに関するコンテキスト情報を格納し、データのサブセットのクエリを高速化できます。
メモリ使用量の観点から、1つの大きな辞書が複数の小さな辞書よりも少ないRAMを使用するのは当然のことです。辞書をネストしている場合は、ネストのレイヤーを追加するたびに、割り当てる必要のある辞書の数が約2倍になることを忘れないでください。
クエリ速度に関しては、必要なルックアップの数が増えるため、複数のdictの方が時間がかかります。
したがって、この質問に答える唯一の方法は、独自のコードをプロファイリングすることだと思います。ただし、私の提案は、コードを最もクリーンで保守しやすい方法を使用することです。 Pythonのすべての機能の中で、辞書はおそらく最適なパフォーマンスのために最も大幅に調整されています。