Python의 Garbage Collection (GC): 이해와 레벨별 관리
Python에서 메모리 관리는 자동화되어 있지만, 그 이면에는 Garbage Collection(GC) 이라는 중요한 프로세스가 작동하고 있습니다. GC는 사용하지 않는 메모리를 자동으로 회수하여 메모리 누수나 비효율적인 자원 관리를 방지하는 역할을 합니다. 이 글에서는 Python 3.11 기준으로 GC의 동작 방식, GC의 다양한 레벨, 그리고 각 레벨별 특징과 GC 설정 방법에 대해 설명하겠습니다.
1. Garbage Collection(GC)의 기본 개념
Python에서의 GC는 주로 참조 카운팅과 주기적인 주기적 수거(Generational GC)로 이루어집니다.
- 참조 카운팅(Reference Counting): 객체가 참조될 때마다 참조 카운트를 증가시키고, 더 이상 참조되지 않으면 해당 객체를 즉시 메모리에서 제거합니다.
- 주기적 수거(Generational Garbage Collection): 참조 카운팅만으로는 처리하기 어려운 순환 참조를 다루기 위해, 세대별 수집기(Generational Collector)가 추가됩니다.
GC는 이러한 두 방식이 협력하여 메모리 관리를 최적화하려고 합니다.
2. GC의 레벨과 특징
Python의 GC는 세 가지 주요 레벨로 나뉘며, 각 레벨은 특정 목적을 가지고 객체의 메모리를 효율적으로 관리합니다. 각 레벨은 객체를 세대별(Generation) 으로 분류하여 관리하며, 이는 각 객체의 생애 주기와 관련이 있습니다.
2.1. Generation 0 (0세대)
- 특징: 이 레벨은 가장 새로운 객체들이 속하는 세대입니다. 객체가 처음 생성되면 Generation 0에 배치됩니다. 이 세대의 객체는 주로 매우 짧은 생애를 가지며, 더 이상 필요 없을 때 바로 수거됩니다.
- GC 동작: 주기적인 GC가 일어날 때마다 Generation 0에서 unreachable 객체가 수거됩니다. 새로운 객체들은 주로 이 세대에서만 존재하고, 수거가 잘 이루어집니다.
2.2. Generation 1 (1세대)
- 특징: Generation 0을 통과한 객체들은 Generation 1로 승격됩니다. 이 세대는 Generation 0보다 더 오래 살아남은 객체들이 모입니다. 보통 조금 더 긴 생애를 가지는 객체들이 속합니다.
- GC 동작: 이 레벨에서도 주기적인 수거가 일어납니다. 하지만 Generation 1의 객체들은 Generation 0보다는 수거 주기가 길어집니다. 이 세대에서는 객체가 살아남을 확률이 상대적으로 높습니다.
2.3. Generation 2 (2세대)
- 특징: 가장 오래된 객체들이 속하는 세대로, Generation 2는 Python에서 가장 오래 살아남은 객체들로 구성됩니다. 일반적으로 객체의 생애가 길거나 프로그램 종료 시까지 살아남는 객체들이 여기에 속합니다.
- GC 동작: Generation 2의 객체들은 최후의 보루와 같은 세대입니다. 이 세대에서의 GC는 비교적 덜 빈번하게 발생하며, 객체들이 살아남은 기간이 길기 때문에 메모리 수거가 어려운 경우가 많습니다.
3. GC의 Threshold와 설정
GC는 각 세대별로 수거의 임계값(threshold)을 설정하여 언제 GC를 실행할지 결정합니다. 이 임계값은 세대별로 객체가 생성된 수를 기준으로 설정됩니다. 각 세대의 임계값을 조정하면 GC의 동작을 보다 세밀하게 관리할 수 있습니다.
3.1. Threshold 설정 방법
Python의 gc
모듈을 사용하면 GC의 임계값을 쉽게 조정할 수 있습니다. 기본적으로 각 세대는 다음과 같은 기본 임계값을 가지고 있습니다:
- Generation 0: 700
- Generation 1: 10
- Generation 2: 10
이 값들은 GC가 세대별로 몇 개의 객체를 생성했을 때 GC를 실행할지를 결정합니다. 예를 들어, Generation 0에서 700개의 객체가 생성되면 GC가 실행됩니다.
3.2. Threshold 조정 코드 예시
gc
모듈의 get_threshold()
와 set_threshold()
메서드를 사용하여 현재 임계값을 확인하고, 변경할 수 있습니다.
import gc
# 현재 GC의 임계값 확인
current_threshold = gc.get_threshold()
print("Current Threshold:", current_threshold)
# GC 임계값 변경 (0세대: 500, 1세대: 20, 2세대: 20)
gc.set_threshold(500, 20, 20)
print("New Threshold Set!")
위 코드에서는 gc.get_threshold()
로 현재 GC 임계값을 출력하고, gc.set_threshold()
로 새로운 임계값을 설정합니다. 이처럼 GC의 임계값을 조정하여, 더 자주 또는 덜 자주 GC가 실행되도록 할 수 있습니다.
3.3. Threshold 변경의 효과
Threshold 값을 조정하면 프로그램의 성능에 영향을 미칠 수 있습니다. 예를 들어, GC를 너무 자주 실행하게 설정하면, CPU 자원을 과도하게 소비할 수 있습니다. 반대로, GC를 너무 드물게 실행하면 메모리가 과다하게 사용될 수 있습니다. 따라서 GC의 임계값을 적절하게 조정하는 것이 중요합니다.
4. GC 튜닝의 사례
GC는 자동으로 관리되지만, 특정 상황에서는 성능 향상을 위해 직접 튜닝이 필요할 수 있습니다. 예를 들어, 큰 데이터를 처리하는 애플리케이션에서는 GC가 과도하게 동작하여 성능에 영향을 줄 수 있습니다. 이 경우, 임계값을 높여 GC를 덜 자주 실행하도록 설정하거나, 필요에 따라 수동으로 GC를 호출하는 방법도 고려할 수 있습니다.
import gc
# 필요 시 수동으로 GC 실행
gc.collect()
이렇게 수동으로 GC를 호출하면 메모리 사용량을 줄일 수 있지만, GC가 자동으로 동작할 때보다 성능에 미치는 영향이 있을 수 있습니다.
5. 결론
Python의 Garbage Collection은 객체의 생애 주기를 관리하고, 불필요한 메모리를 자동으로 회수하여 효율적인 메모리 관리를 지원합니다. Python 3.11에서 GC는 Generational GC 방식을 사용하여 메모리 관리를 최적화하며, 각 세대별로 임계값을 설정하여 GC 동작을 제어할 수 있습니다. 성능 최적화를 위해 GC의 임계값을 조정하거나, 수동으로 GC를 호출하는 방법을 활용할 수 있습니다.
이를 통해 Python에서 효율적인 메모리 관리와 성능 튜닝을 할 수 있으며, 특히 메모리 사용이 중요한 대규모 애플리케이션에서 더욱 유용하게 활용할 수 있습니다.
이 글이 Python의 GC 메커니즘과 그 설정 방법에 대해 이해하는 데 도움이 되기를 바랍니다. Python의 자동화된 메모리 관리가 어떻게 작동하는지 이해하고, 필요에 맞게 조정하면 더 나은 성능을 얻을 수 있습니다.
'Computer Science > Python' 카테고리의 다른 글
[Python3] "[Errno 2] No such file or directory: 'gs'" 해결방법 (0) | 2022.11.19 |
---|---|
[Django] no such table 에러 해결법 (0) | 2022.08.15 |
[Python] 파이썬 XML을 사전(dict/json)으로 변환하는 방법 (xmltodict) (0) | 2022.07.27 |
[Python] nested json(dict) 플랫화(flatten) (0) | 2022.07.26 |
[python] poetry 설치 (0) | 2022.07.21 |