2011-01-25 1 views
8

Pythonでマルチスレッドプログラムのメモリをプロファイリングする方法はありますか?Pythonでマルチスレッドプログラムのメモリをプロファイリングするにはどうすればよいですか?

CPUプロファイリングでは、cProfileを使用して各スレッドのプロファイラ統計情報を作成し、後でそれらを結合します。しかし、私はメモリプロファイラでこれを行う方法を見つけることができませんでした。私はheapyを使用しています。

cProfileのようにheapyで統計情報を結合する方法はありますか?または、このタスクに適している他のメモリプロファイラーをお勧めします。

関連の質問は、マルチスレッドプログラム上でCPU使用率をプロファイリングするために頼まれた:メモリプロファイラに関するHow can I profile a multithread program in Python?

はまた別の質問:Python memory profiler

+0

これらの他の質問の解決策について、あなたはどう思われますか? – Falmarri

+0

@Falmarri、私は 'メモリ'プロファイラを探しています。最初は主にCPUプロファイラです。 2番目のスレッドは、1つのスレッドに対してのみ機能します。 –

+1

スレッドの主な特徴は、(プロセスとは対照的に)メモリを共有することです。同じメモリを共有するスレッドに対して、どのように異なるメモリ統計をプロファイルすると思いますか? – scoffey

答えて

7

生のメモリではなくオブジェクトをプロファイルすることができたら、gc.get_objects()関数を使用して、カスタムメタクラスを必要としないようにすることができます。より最近のPythonバージョンでは、sys.getsizeof()は、それらのオブジェクトによって使用されている基本メモリの量を把握するのにも役立ちます。

+0

これは素晴らしいことです。私のアプローチよりもはるかにクリーンです。 –

3

Pythonプログラムのメモリをプロファイルするvalgrindのを取得する方法があります。 http://www.python.org/dev/faq/#can-i-run-valgrind-against-python

+0

前にvalgrindについて聞いたことはありません。間違いなくそれをチェックします。 –

+0

@funktkuこれは、メモリ使用量をプロファイリングしてメモリリークを検出するための標準的なツールです。 –

1

私が正確に探していたものは存在していないようです。だから、私は解決策を見つけました。この問題の回避策です。

メモリをプロファイリングする代わりに、私はオブジェクトをプロファイルします。このようにして、プログラムの特定の時間にいくつのオブジェクトが存在するかを見ることができます。私の目標を達成するために、既存のコードを最小限に変更してメタクラスを使用しました。

次のメタクラスは、クラスの__init____del__関数に非常に単純なサブルーチンを追加します。 __init__のサブルーチンは、そのクラス名を持つオブジェクトの数を1つ増やし、__del__を1つ減らします。

class ObjectProfilerMeta(type): 
    #Just set metaclass of a class to ObjectProfilerMeta to profile object 
    def __new__(cls, name, bases, attrs): 
     if name.startswith('None'): 
      return None 

     if "__init__" in attrs: 
      attrs["__init__"]=incAndCall(name,attrs["__init__"]) 
     else: 
      attrs["__init__"]=incAndCall(name,dummyFunction) 

     if "__del__" in attrs: 
      attrs["__del__"]=decAndCall(name,attrs["__del__"]) 
     else: 
      attrs["__del__"]=decAndCall(name,dummyFunction) 

     return super(ObjectProfilerMeta, cls).__new__(cls, name, bases, attrs) 

    def __init__(self, name, bases, attrs): 
     super(ObjectProfilerMeta, self).__init__(name, bases, attrs) 


    def __add__(self, other): 
     class AutoClass(self, other): 
      pass 
     return AutoClass 

incAndCallとdecAndCall機能

は、それらが存在するモジュールのグローバル変数を使用する使用します。

counter={} 
def incAndCall(name,func): 
    if name not in counter: 
     counter[name]=0 

    def f(*args,**kwargs): 
     counter[name]+=1 
     func(*args,**kwargs) 

    return f 

def decAndCall(name,func): 
    if name not in counter: 
     counter[name]=0 

    def f(*args,**kwargs): 
     counter[name]-=1 
     func(*args,**kwargs) 

    return f 

def dummyFunction(*args,**kwargs): 
    pass 

dummyFunctionは単なる非常に簡単な回避策です。私はそれを行うより良い方法があると確信しています。

最後に、存在するオブジェクトの数を確認したいときは、カウンタディクショナリを参照するだけです。例;

>>> class A: 
    __metaclass__=ObjectProfilerMeta 
    def __init__(self): 
     pass 


>>> class B: 
    __metaclass__=ObjectProfilerMeta 


>>> l=[] 
>>> for i in range(117): 
    l.append(A()) 


>>> for i in range(18): 
    l.append(B()) 


>>> counter 
{'A': 117, 'B': 18} 
>>> l.pop(15) 
<__main__.A object at 0x01210CB0> 
>>> counter 
{'A': 116, 'B': 18} 
>>> l=[] 
>>> counter 
{'A': 0, 'B': 0} 

私はこれがあなたを助けてくれることを願っています。私の場合は十分でした。

0

私はYappiを使用しましたが、これはいくつかの特殊なマルチスレッドのケースで成功しました。偉大なドキュメンテーションがあるので、設定するのが面倒ではありません。

メモリ固有のプロファイリングについては、Heapyを参照してください。警告すると、これまでに見た中で最大のログファイルがいくつか作成される可能性があります。

+0

残念ながら、私はこれらのプロファイラーの両方を認識しており、特にYappiとHeapyについて話している関連する質問にリンクしています。問題は、yappiはメモリをプロファイリングせず、heapyは主スレッドのメモリ使用量(正確には呼び出されたスレッド)のみをプロファイルすることです。 –

+0

@ KushalP。私はYaapiを試しました、私はそれが私の行ごとの実行時間を与えることはできないと思う。私は何かが恋しいですか? –

関連する問題