2011-01-25 4 views
8

파이썬에서 멀티 스레드 프로그램의 메모리를 프로파일 링하는 방법이 있습니까?어떻게 파이썬에서 멀티 스레드 프로그램의 메모리를 프로파일 링 할 수 있습니까?

CPU 프로파일 링의 경우 각 스레드에 대해 별도의 프로파일 러 통계를 작성하고 나중에 결합하기 위해 cProfile을 사용하고 있습니다. 그러나 메모리 프로파일 러를 사용하여이를 수행 할 수있는 방법을 찾지 못했습니다. 나는 heapy를 사용하고있다.

힙에서 stats를 cProfile과 결합하는 방법이 있습니까? 또는이 작업에 더 적합한 다른 메모리 프로파일 러를 제안하십시오.

이와 관련된 질문은 멀티 스레드 프로그램을 통해 CPU 사용량을 프로파일 링에 대한 질문을 받았다 : How can I profile a multithread program in Python?

또한 메모리 프로파일 러에 대한 또 다른 질문 : Python memory profiler

+0

다른 질문에서 해결책에 대해 무엇을 좋아하지 않으세요? – Falmarri

+0

@Falmarri, '메모리'프로파일 러를 찾고 있습니다. 첫 번째는 주로 CPU 프로파일 러입니다. 두 번째 것은 단일 스레드에서만 작동합니다. –

+1

스레드의 주요 특징은 프로세스와 달리 메모리를 공유한다는 것입니다. 같은 메모리를 공유하는 스레드에 대해 서로 다른 메모리 통계를 어떻게 프로파일 링 할 것으로 예상합니까? – scoffey

답변

7

원시 메모리가 아닌 오브젝트를 프로파일 링하면 gc.get_objects() 기능을 사용할 수 있으므로 사용자 정의 메타 클래스가 필요하지 않습니다. 최근의 Python 버전에서는 sys.getsizeof()을 사용하여 이러한 객체가 기본 메모리의 사용량을 파악할 수 있습니다.

+0

이것은 아주 좋습니다. 내 접근 방식보다 훨씬 깔끔해. –

3

파이썬 프로그램의 메모리 프로파일 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를 시험해 보았습니다. 제 생각에는 라인별로 실행 시간을 줄 수는 없다고 생각합니다. 내가 놓친 게 있니? –