12

を使用して、起動時に多数の大きなデータ ファイルを unpickle する Python ベースの Web サーバーがありますcPickle。データ ファイル ( を使用してピクルHIGHEST_PROTOCOL) は、ディスク上で約 0.4 GB であり、約 1.2 GB の Python オブジェクトとしてメモリに読み込まれます。これには約20 秒かかります。64 ビット Windows マシンで Python 2.6 を使用しています。

ボトルネックは確かにディスクではなく (実際に大量のデータを読み取るのに 0.5 秒もかかりません)、メモリの割り当てとオブジェクトの作成 (何百万ものオブジェクトが作成されています) です。起動時間を短縮するために 20 秒を短縮したいと考えています。

1GB を超えるオブジェクトを Python にデシリアライズする方法はありますかcPickle(5 ~ 10 倍など)。実行時間はメモリの割り当てとオブジェクトの作成によって制限されるため、JSON などの別の unpickle 手法を使用しても、ここでは役に立たないと思います。

一部のインタープリター言語には、メモリイメージ全体をディスクファイルとして保存する方法があるため、オブジェクトごとに割り当て/作成することなく、一度にメモリに読み込むことができます。Pythonでこれを行う方法、または同様のことを達成する方法はありますか?

4

6 に答える 6

17
  1. marshal モジュールを試してみてください - これは内部 (バイトコンパイラによって使用されます) であり、意図的にあまり宣伝されていませんが、はるかに高速です。pickle のような任意のインスタンスをシリアル化するのではなく、組み込み型のみをシリアル化することに注意してください (正確な制約は覚えていません。ドキュメントを参照してください)。また、フォーマットが安定していないことにも注意してください。

  2. 複数のプロセスを初期化する必要があり、1 つのプロセスが常にロードされることを許容できる場合は、洗練された解決策があります。1 つのプロセスにオブジェクトをロードし、オンデマンドでプロセスを fork する以外は何もしません。フォークは高速 (コピー オン ライト) であり、すべてのプロセス間でメモリを共有します。[免責事項: テストされていません。Ruby とは異なり、Python の参照カウントはページのコピーをトリガーするため、巨大なオブジェクトがある場合やそれらのごく一部にアクセスする場合、これはおそらく役に立たない.]

  3. オブジェクトに numpy 配列のような多くの生データが含まれている場合は、それらをメモリ マップして起動を高速化できます。pytables は、これらのシナリオにも適しています。

  4. オブジェクトのごく一部しか使用しない場合は、オブジェクト指向データベース (Zope など) が役立つ可能性があります。ただし、それらすべてをメモリに格納する必要がある場合は、わずかな利益のために多くのオーバーヘッドを浪費するだけです。(一度も使ったことがないので、これはナンセンスかもしれません)。

  5. 多分他のpython実装はそれを行うことができますか? わかりません、ただの考えです...

于 2010-11-16T15:32:07.207 に答える
7

ピクルス化されたデータをファイルから直接ロード()していますか? ファイルをメモリにロードしてからロードしてみてはどうでしょうか。cStringIO(); を試すことから始めます。あるいは、 buffer() を使用してメモリをスライスする独自のバージョンの StringIO を作成して、必要な copy() 操作を削減することもできます (cStringIO の方が高速な場合もありますが、試してみる必要があります)。

特に Windows プラットフォームでこの種の操作を行うと、大きなパフォーマンスのボトルネックが発生することがあります。UNIX は非常にうまく処理できるのに対し、Windows システムは大量の小さな読み取りを行うには最適化されていません。load() が多くの小さな読み取りを行う場合、または load() を数回呼び出してデータを読み取る場合、これは役立ちます。

于 2010-11-16T15:30:35.537 に答える
4

私はcPickle(またはPython)を使用していませんが、このような場合、オブジェクトが本当に必要になるまで不要なロードを避けることが最善の戦略だと思います-たとえば、別のスレッドでの起動後にロードすると、実際には通常は避ける方が良いです明らかな理由により、いつでも不必要なロード/初期化。Google の「遅延読み込み」または「遅延初期化」。サーバーの起動前にすべてのオブジェクトが何らかのタスクを実行する必要がある場合は、手動のカスタム逆シリアル化メソッドを実装してみることができます。それを処理するための一般的なツールよりも優れたパフォーマンスを「絞る」。

于 2010-11-16T14:43:04.717 に答える
3

HIGHEST_PROTOCOL を使用しないことで、酸洗いの効率を犠牲にしようとしましたか? このプロトコルの使用に関連するパフォーマンス コストは明らかではありませんが、試してみる価値はあります。

于 2010-11-16T15:09:31.320 に答える
2

ロードしているデータの種類とその使用方法について詳しく知らずに、これに答えるのは不可能です。

ある種のビジネス ロジックである場合は、コンパイル済みのモジュールに変換してみてください。

構造化データの場合、それをデータベースに委任して、必要なものだけをプルできますか?

データは規則的な構造を持っていますか? それを分割して、必要なものを決定してからロードする方法はありますか?

于 2010-11-16T15:17:52.700 に答える
2

役立つかもしれない別の回答を追加します。可能であれば、最も一般的に作成されるクラスで_スロット_ を定義してみてください。これは少し制限的で不可能かもしれませんが、私のテストでは初期化に必要な時間が約半分に短縮されたようです。

于 2010-11-16T16:29:56.227 に答える