2012-12-09 5 views
1

메모리 소비가 꾸준히 증가하는 파이썬 코드가 있습니다. 합법적으로 상당히 커질 수있는 몇 가지 객체가 있지만, 내가 관찰하고있는 메모리 발자국이 이러한 객체로 인한 것인지 아니면 제대로 폐기되지 않은 임시 객체를 가진 메모리를 낭비하고 있는지를 이해하려고 노력하고 있습니다. 최근 수작업 메모리 관리의 세계에서 최근의 변환으로, 나는 파이썬 런타임이 임시 객체를 다루는 방법의 아주 기본적인 측면을 정확히 이해하지 못한다고 생각합니다.임시 메모리의 메모리 소비 및 수명

def tweak_list(lst): 
    new_lst = copy.deepcopy(lst) 
    if numpy.random.rand() > 0.5: 
     new_lst[0] += 1 # in real code, the operation is a little more sensible :-) 
     return new_lst 
    else: 
     return lst 


lst = [1, 2, 3] 
cache = {} 

# main loop 
for step in xrange(some_large_number): 

    lst = tweak_list(lst) # <<-----(1) 

    # do something with lst here, cut out for clarity 

    cache[tuple(lst)] = 42 # <<-----(2) 

    if step%chunk_size == 0: 
     # dump the cache dict to a DB, free the memory (?) 
     cache = {}   # <<-----(3) 

질문 :

  1. tweak_list에서 만든 new_list의 수명은 무엇입니까

    는 약이 일반 구조 (생략하고 관련없는 세부 사항)와 코드를 생각해? 출구에서 파손될 것인가 아니면 가비지 수집 될 것인가? tweak_list에 반복적으로 전화를 걸면 오랜 기간 동안 소량의 목록이 반복적으로 생성됩니까?
  2. listtuple으로 변환하면 dict 키로 사용 되나요?
  3. dict을 공백으로 설정하면 메모리가 해제됩니까?
  4. 아니면 완전히 잘못된 관점에서 직접 문제에 접근하고 있습니까?
+1

여기에 표시된 코드를 실행해도 시간이 지남에 따라 메모리가 증가합니까? – interjay

+0

Q : 왜''deepcopy()''를 사용하고 있습니까? 귀하의 목록에 더 복잡한 객체가 포함되어 있습니까? 그렇지 않다면 얕은 사본을 사용하거나''list()''만을 사용하십시오. 그렇다면 누수가 복사되어 키로 캐시에 저장 될 가능성이 가장 높습니다. – lqc

+0

@lqc : 여기에 (어쩌면 어리석은) 예제에서,'tweak_list'는 대략 50 %의 호출에서 그것의 인수를 수정합니다; 나머지 50 %에서는 목록을 그대로 두어야합니다. 물론, 나는 단지 'lst [:]'뷰를 조작 할 수 있었지만 실제로는 다를 것인가? –

답변

4
  1. new_lst이 정리되어있다. 그것은 참조 카운트가 0으로 떨어지며 가비지 수집 될 수 있습니다. 즉시 발생하는 현재의 cpython 구현.

    그것은 new_lst에 의해 참조 값이 lst 대체 반환하는 경우; lst에 의해 참조되는 목록은 참조 카운트가 1 씩 감소한다고보고 있지만 원래 new_lst에 의해 참조 된 값은 여전히 ​​다른 변수에 의해 참조되고 있습니다.

  2. tuple() 키는 dict에 저장된 값이므로 임시 키가 아닙니다. 해당 튜플 이외의 추가 객체는 생성되지 않습니다.

  3. 이전 cache dict를 새 것으로 바꾸면 참조 횟수가 1 회로 줄어 듭니다. cache이 dict에 대한 유일한 참조 인 경우 가비지 수집됩니다. 그러면 포함 된 모든 튜플 키에 대한 참조 횟수가 하나씩 감소합니다. 다른 것들이 쓰레기 수거 될 것입니다.

  4. 파이썬이 메모리를 해제 할 때 운영 체제가 메모리를 즉시 해제한다는 의미는 아닙니다. 대부분의 운영 체제는 프로그램이 필요할 때만 메모리를 다시 요구할 수도 있습니다. 대신 프로그램에서 해당 메모리의 일부 또는 전부를 곧 다시 필요로한다고 가정합니다.

+0

@lqc : 명확하게; 항상 반환되는 것은 아닙니다. –

0

메모리 사용을 프로파일 링하는 방법으로 Heapy을 살펴볼 수 있습니다. 나는 또한 PySizer이 어떤 경우에는 이것을 사용한다고 생각하지만 익숙하지 않다. ObjGraph도 강력한 도구입니다. 반환하지 않을 경우 함수가 존재하는 경우