5

プログラムのメモリ フットプリントを制御しようとしています。PyObjCかなり大きなライブラリから 3 ~ 4 個の関数しか使用していないため、インポートから始めようと思いました。しかし、より大きなモジュールの特定の部分をインポートしても、実際にメモリにロードされたものとはまったく関係がないことに少し驚きました。

メモリ プロファイラーの出力

OSX で Quartz.CoreGraphics ライブラリ全体をロードします。

Line #    Mem usage    Increment   Line Contents
================================================
    77                             @profile 
    78     7.953 MB     0.000 MB   def test_import_all():
    79    26.734 MB    18.781 MB    import Quartz.CoreGraphics as CG

ライブラリ全体をほぼ 19MB で取り込みます。

必要なものだけを取り込もうとすると、同じ 19MB の結果が得られます。

Line #    Mem usage    Increment   Line Contents
================================================
    82                             @profile
    83     7.941 MB     0.000 MB   def test_import_some():
    84    26.727 MB    18.785 MB    from Quartz.CoreGraphics import CGImageGetWidth 

したがって、特定のインポートは、実際にロードされるものとは関係がないようです。

それ以外の場合は巨大なモジュールからほんの一握りの機能しか必要としないのは、一般的なユースケースのようです。モジュールから必要なものだけをメモリにロードする方法はありますか、それとも外部ライブラリを使用した結果ですか?

4

2 に答える 2

5

それがモジュールのロードの仕組みです。ランタイムはロードされたモジュールのコレクションを保持するため、いくつかのシンボルをインポートしただけでもモジュール全体にアクセスできます。これには、次の 2 つの望ましい結果があります。

  • 同じモジュールの将来のインポートは高速です。
  • 副作用のあるモジュールレベルのコードは、モジュールのどのビットがどの場所にインポートされるかに応じて可変回数実行されるのではなく、(モジュールのリロードを除いて) 1 回だけ実行されます。

globals()また、モジュール内の任意の関数が、モジュールの名前を使用して直接、または、sys.modules[__name__]、などを介して間接的にモジュールの名前空間にアクセスできると考えると、これはかなり避けられませんeval。したがって、特定の関数がこれを行わないことを証明するための巧妙な最適化 (Python の実装では一般的に気にしない) を除いて、モジュールの名前空間全体がメモリ内にある必要があります。

于 2013-09-16T19:42:57.217 に答える