티스토리 뷰

Python & Flask & Django

Python Garbage Collection

weicome weicome 2017.02.10 20:39


digi.com/wiki에 게시된 Python Garbage Collection 이라는 글을 번역하였습니다. 





Python 메모리 관리


파이썬의 메모리 할당과 해제는 자동으로 이뤄진다. C나 C++과 같은 언어에서 동적으로 메모리 할당을 해야하는 방식과는 반대로 파이썬 사용자는 메모리를 할당하거나 해제할 필요가 없다. 파이썬은 메모리 할당을 위해 reference couninggarbage collection 두가지 방식을 사용한다. 


파이썬 2.0 이전에는 메모리 관리를 위해 인터프리터에서 reference counting 방식만 사용했다. Reference counting 은 시스템에서 어떠한 객체에 다른 객체의 참조의 개수를 통해 동작한다. 객체에 참조가 사라졌을 때 객체의 reference count는 감소된다. 그리고 객체의 reference count가 0이 되었을때 객체는 메모리에서 해제된다. 


Reference Counting은 굉장히 효율적이지만 몇가지 주의할사항이 있다. 주의사항 첫 번재는 Reference Counting은 reference cycle을 관리할수 없다. reference cycle 객체에 접근할수 있는 방법은 없지만 reference count가 0보다 큰 경우를 말한다. reference cycle을 만드는 가장 쉬운 방법은 자기자신을 참조하는 객체를 맨드는 것이다. 아래의 예시를 보자.


def make_cycle():

    l = [  ]

    l.append(l)


make_cycle()


make_Cycle이 자기 자신을 참조하는 l 객체를 만들었기 때문에 객체 l은 함수가 retune 될때 자동으로 해제되지 않는다. 이와 같은경우 python GC가 동작할 때까지 l은 메모리를 점유하게 된다. 



 

자동 Garbage Collection 주기


reference cycle 들을 발견하기 위해서는 프로그래밍적 동작이 수행되어야 하기 때문에 Garbage Collection은 반드시 동작의 스케쥴이 정해져야한다. 파이썬은 Garbage Collection을 객체의 할당과 해제의 한계치를 기준으로 계획한다. 메모리 할당값에서 메모리 해제값을 뺀 값이 한계치 값보다 크다면 Garbage Collection이 동작한다. gc 모듈을 로딩하고 gc의 한계치 값을 호출하여 새로운 객체에 대한 한계치를 확인해볼 수 있다.


import gc

print "Garbage collection thresholds: %r" % gc.get_threshold()


> Garbage collection thresholds: (700, 10, 10)


위 시스템의 기본 한계치 값은 700인것을 확인할 수 있다. 메모리 할당과 해제를 비교해서 700 이상이라면 GC가 실행될수 있다는 것을 의미한다.


하지만 Python을 구동하는 장비의 메모리가 부족하다면 자동 GC는 실행되지  않을 것이다. 대신에 Python Application은 반드시 처리되어져야 할 오류를 발생시키며 application은 종료된다. 이는 GC가 메모리 해제시 객체가 차지하는 메모리가 얼마나 큰지가 아니라, 참조되지 않는 객체의 숫자에 가중치를 부여한다는 사실에 때문에 더 악화된다. 따라서 큰 메모리 블록을 비우는 코드 부분은 수동으로 GC 수집을 실행하기에 좋은 대상이다.




수동 Garbage Collection


오랜시간 동작하는 서버 Application이나 전자 장비에서 구동되는 Application 과 같은 몇몇 프로그램들에서는 자동 GC만으로는 충분하지 않을 수 있다. Application이 reference cycle 로부터 가능한 자유롭도록 작성되었더라도 reference cycle 을 어떻게 다룰지에 대한 대책을 갖는 것이 좋다. 프로그램 실행 중에 적절한 시간동안 GC를 실행시키는 것은 reference cycle로 점유되는 메모리를 관리하는 방법으로 좋은 생각이다.


GC를 수동으로 동작시키는 코드는 다음과 같다.


import gc

gc.collect()


gc.collect() 를 호출하면 점유된 객체 숫자와 메모리가 해제된 객체 숫자를 반환한다. 이 정보들은 아래의 코드와 같이 프린트 할수 있다.


import gc

collected = gc.collect()

print (collected)


아래의 코드는 reference cycle를 생성하고 수동으로 gc를 실행하는 코드이다. 


import sys, gc


def maek_cycle():

    l = { }

    l[0] = l


def main():

    collected = gc.collect()

    print (collected)

    for i in range(10):

        make_cycle()

    collected = gc.collect()

    print(collected)


if __name__ == "__main__":

    ret = main()

    sys.exit(ret)


일반적으로 수동으로 gc를 수행하는 추천되는 방법은 Time-based, Event-based 두가지가 있다. Time-based gc는 단순하다 고정된 시간간경으로 gc가 실행된다. Event-based gc는 event 발생시 gc가 호출된다. 예를들어 사용자가 application의 접속이 끊어졌을때나 Application의 상태가 ideal 해졌을때 Event를 감지해서 호출한다는듯...

 


'Python & Flask & Django' 카테고리의 다른 글

Django Settings - INSTALLED_APPS, MIDDLEWARE  (0) 2017.03.20
Django Settings  (0) 2017.03.15
Python Garbage Collection  (0) 2017.02.10
SQLAlchemy Tutorial  (0) 2017.02.02
SQLAlchemy 시작하기 - Part 2  (0) 2017.02.01
SQLAlchemy 시작하기 - Part 1  (0) 2017.01.31
댓글
«   2018/06   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Total
62,431
Today
32
Yesterday
95