9

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

CPU プロファイリングでは、cProfile を使用してスレッドごとに個別のプロファイラー統計を作成し、後でそれらを結合しています。ただし、メモリ プロファイラーでこれを行う方法が見つかりませんでした。ヒープを使用しています。

cProfile のようにヒーピーで統計を組み合わせる方法はありますか? または、このタスクにより適した他のメモリプロファイラーを提案してください。

関連する質問が、マルチスレッド プログラムでの CPU 使用率のプロファイリングについて尋ねられました: How can I profile a multithread program in Python?

メモリ プロファイラに関する別の質問: Python メモリ プロファイラ

4

4 に答える 4

8

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

于 2011-02-14T02:00:22.220 に答える
3

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

于 2011-02-07T05:12:13.187 に答える
1

Ok。私がまさに探していたものは存在しないようです。そこで、この問題の回避策である解決策を見つけました。

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

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

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}

これがお役に立てば幸いです。私の場合はそれで十分でした。

于 2011-02-13T23:36:12.833 に答える
-1

私はいくつかの特別なマルチスレッドのケースで成功したYappiを使用しました。優れたドキュメントが用意されているため、セットアップにそれほど苦労する必要はありません。

メモリ固有のプロファイリングについては、Heapyを確認してください。これまでに見たことのない最大のログ ファイルが作成される可能性があることに注意してください。

于 2011-02-18T17:31:46.760 に答える