개발이야기

python의 GC, 가비지 콜렉션

gaelim 2024. 2. 20. 02:56
반응형

Garbage Collection

Python의 GC는 기본적으로 암묵적으로 진행된다. 

어떻게 암묵적으로 진행되는지는, PEP 556에 따르면 기회주의적으로 따른다고 한다. 새로운 allocation이 진행될 때, allocation을 통계적으로 연산하여 휴리스틱하게 진행된다고 한다. 이를 보고 implicitly opportunistic 이라고 한다. GC를 명시적으로 collect 하기 위해선 다음 코드를 수행해야한다.

gc.collect()

자, 그럼 어떻게 암묵적으로 또는 명시적으로, 어떤 GC를 진행하고 있는 것일까? 

Reference Counting

Python GC는 기본적으로 reference count로 수행된다. reference count 란 C++ 의 shared ptr과 동작방식이 같다고 보면되는데, 아래 그림을 살펴보자.

http://assets.iosappsdev.org/objective-c/tutorials/objective-c/memory-management.html

해당 객체를 참조하는 개수가 0개가 될 때 GC가 수집하게 된다.

이는 납득가능하지만, 순환참조일 때 발생하게 된다. 순환참조란, A와 B가 서로 참조하고 있는 상태를 말한다. 간단한 예는 다음과 같다.

l = []
l.append(l)
del l

l의 참조 횟수는 2이고, del l 을 호출 하므로 삭제되었으나 순환참조가 되고 있는 l은 순환참조 로직만으로는 수거되지 않는다. 이를 수집되지 않는 Dead reference cycle이라 한다. 

https://devguide.python.org/internals/garbage-collector/#gc-oldest-generation

Cyclic Garbage Collector

이를 위해 Python의 GC는 위에서 말한 몇 가지 heuristic한 알고리즘을 수행하는데 그 것을 cyclic-garbage collector이다.

단순히 순환 참조가 아닌 경우, 앞선 레퍼런스 카운팅으로 모든 것을 해결할 수 있다. 순환 참조인 경우 gc는 다음과 같이 동작할 수 있다.

예로, 레퍼런스 카운팅의 동작 방식의 시작은, 시스템의 root 오브젝트로부터 접근 가능한 모든 객체를 탐색하여 해제하는 방식이다. 이와 반대로, cyclic-garbage collector는 시스템으로 부터 접근 가능하지 않은 객체를 탐색하는 것을 방식으로 삼는다. 이를 위해 python 의 객체에서는 내부적으로 gc_ref라는 것을 둬서, 레퍼런스 사이클이 있는지 참조한다.

더 이상의 내용은 python의 심연으로 나가는 내용이라 짧게 여기까지만 하겠다. 인터뷰때도 자세히 안나올것 같아서... 좀 더 자세한것은 http://www.arctrix.com/nas/python/gc/ 을 참조하는 것을 추천한다.

cyclic garbage collector의 특징 중 하나는 generation 이다. 

Optimization: Generation (Feature of Cyclic Garbage Collector)

가비지 콜렉터가 작업을 수행할 때 횟수를 줄일 수 있도록, python의 GC는 generations라는 유명한 최적화 기법을 사용한다. 이 아이디어의 핵심은, 대부분의 객체들은 굉장히 짧은 수명을 가지고 있고 그래서 그 객체의 생성 후에 빠르게 수집될 수 있다는 것에 착안했다. 많은 python 프로그래머들의 실제 행동에서도 일시적인 많은 객체들을 만들고 없애기를 매우 빠르게 했다.

이 사실로부터 이점을 얻기위해, 모든 객체들은 3 개의 세대로 나눠진다.

- 새로 생성된 객체 (generation 0)
- 이전 GC 알고리즘이 수행되고, 살아남은 객체인 경우 (generation 1). 여기서는 GC에서 덜 자주 조사된다.
- 또 같은 객체가 다른 GC 알고리즘에서 생존한 경우 (generation 2). 여기서도 GC에서 덜 자주 조사된다.

GC가 호출되는 빈도수는 다음과 같이 확인할 수 있다.

import gc
gc.get_threshold()
(700, 10, 10)

threshold의 700, 10, 10 의 수치는 개수를 뜻하는 것인데, 각 산식이 다르다.

- threshold_0인 경우 number of allocation - number of deallocation 이 700개를 넘기면 GC가 수행된다는 것이다. 
- threshold_1인 경우 generation_0 GC가 10번 수행되면 GC가 수행된다는 것이다.
- threshold_2인 경우 generation_1 GC가 10번 수행되고, long_lived_pending / long_lived_total 이 25%를 넘긴경우에만 수행된다.

 

 

참고 문서 

https://documentation.help/Python-PEP/node24.html

 

2.1.3 Supporting cyclic garbage collection - Python PEP Documentation

Python has a cyclic-garbage collector that can identify unneeded objects even when their reference counts are not zero. This can happen when objects are involved in cycles. For example, consider: >>> l = [] >>> l.append(l) >>> del l In this example, we cre

documentation.help

https://hyperconnect.github.io/2023/05/30/Python-Performance-Tips.html#1-%EC%83%81%ED%99%A9%EC%97%90-%EB%94%B0%EB%9D%BC-gc%EA%B0%80-%EB%B3%91%EB%AA%A9%EC%9D%BC-%EC%88%98-%EC%9E%88%EB%8B%A4-%EC%9D%B4%EB%9F%B0-%EA%B2%BD%EC%9A%B0-gc-%EB%B0%9C%EB%8F%99-%EC%A1%B0%EA%B1%B4%EC%9D%84-%ED%8A%9C%EB%8B%9D%ED%95%A0-%EC%88%98-%EC%9E%88%EB%8B%A4

 

고성능 ML 백엔드를 위한 10가지 Python 성능 최적화 팁

다량의 데이터를 사용하는 ML 워크로드에 특화된 최적화 기법들과, ML 백엔드에서 자주 사용되는 third-party 라이브러리를 효과적으로 사용하는 방법들을 실제 하이퍼커넥트의 사례와 함께 공유합

hyperconnect.github.io

https://peps.python.org/pep-0556/#gc-module

 

PEP 556 – Threaded garbage collection | peps.python.org

PEP 556 – Threaded garbage collection Author: Antoine Pitrou Status: Deferred Type: Standards Track Created: 08-Sep-2017 Python-Version: 3.7 Post-History: 08-Sep-2017 Table of Contents This PEP is currently not being actively worked on. It may be revived

peps.python.org

http://www.arctrix.com/nas/python/gc/

 

Garbage Collection for Python

Garbage Collection for Python <!-- ugh, bad joke :) P: 'Ello, Miss? RC: What do you mean "miss"? P: I'm sorry, I have a cold. I wish to register a complaint! RC: We're closin' for lunch. P: Never mind that, my lad. I wish to complain about this object what

www.arctrix.com

https://www.winterjung.dev/python-gc/

 

Python GC가 작동하는 원리

보통 파이썬은 레퍼런스 카운팅 방식으로 가비지 컬렉션을 수행해 메모리를 관리하고, 레퍼런스 카운팅을 사용했을 때 발생할 수 있는 순환 참조 상황을 별도의 가비지 컬렉터로 해결한다고 알

www.winterjung.dev

https://devguide.python.org/internals/garbage-collector/#gc-oldest-generation

 

Garbage collector design

Abstract: The main garbage collection algorithm used by CPython is reference counting. The basic idea is that CPython counts how many different places there are that have a reference to an object. ...

devguide.python.org

 

반응형