Garbage collection (GC)은
Programming에서 memory를 관리하는 기법 중의 하나임.
Dynamical Memory Allocation에서
더 이상 사용되지 않는 object 또는 data에 할당된 memory를 자동으로 회수하는
Process를 의미한다.
GC
를 지원하지않는 C, C++ 등의 프로그래밍 언어에서는
- 일반적으로 programmer가 memory의 할당과 해제를 explicitly(명시적으로) 처리해야하며,
- 이를 잘못 수행하여 발생하는 memory leakage는 100% programmer의 책임이었음.
Pointer와 함께 이 명시적인 memory 관리 는
- Programmer에게 강력한 권한을 주면서
- 동시에 미숙한 programmer들의 잘못된 처리로 인해
- 프로그램의 성능 저하 또는 예기치 않는 다운이 자주 발생케 되는 원인이 됨.
이에 대한 해결책으로
Pointer를 대체하는reference
가,
명시적 동적메모리 관리에 대해선GC
가 제안됨.
GC
는
LISP
프로그래밍 언어에서 처음으로 도입(1959, McCarthy)되었으며
Java
에서 사용되면서
최신의 High-level Programming Language에서 일반적으로 지원하는 기능으로 받아들여지게 됨.
GC
는
- runtime 중 memory를 모니터링하여
- 더이상 필요하지 않은 memory 영역을 자동으로 회수함으로서 programmer의 부담을 덜어줌.
Reference Counting and Generation
GC
에서
더이상 필요치 않은 memory 영역을 찾기 위해
다양한 algorithm과 method들이 제안되었음.
대표적인 것으로는
Reference Counting
과Tracing
,Generation
등이 있음.
가장 기본적인 Reference counting
은
해당 memory 영역을 참고하고 있는 reference의 숫자를 counting하여
해당 숫자가 0이 되면 해당 memory영역을 회수하는 방식임
(단, Circular referencing에서 메모리누수가 발생하는 단점이 있음).
Python
에서는 sys.getrefcount
를 통해 refence들의 숫자를 확인 가능함.
import sys
x = [1, 2, 3]
# Reference Counting
ref_count = sys.getrefcount(x) - 1 # getrefcount의 argument로
# 넘겨져서 ref. counting이
# 하나 더 증가하여 출력되어 -1을 처리.
print(ref_count)
해당 구현의 CPython
코드를 보려면 다음 URL을 참고 : cpython/Include/object.h
다음의 내용은 일반적인 경우에는 생략해도 됨.
Python
의 GC
는 3개의 generation (0,1,2)별로 reference들을 관리하며,
각 세대별로 정해진 threshold에 따라 해당 임계치를 넘은 generation에 대해 GC가 수행됨.
- 새로운 객체가 만들어질때 파이썬은 객체를 메모리와 0세대에 할당한다.
- 만약 0세대의 객체 수가 threshold 0보다 크면
collect_generations()
를 실행. collect_generations()
메서드가 호출되면 모든 세대(기본적으로 3개의 세대)를 검사하는데 가장 오래된 세대(2세대)부터 역으로 확인- 해당 세대에 객체가 할당된 횟수가 각 세대에 대응되는
threshold n
보다 크면collect()
를 호출해 GC 수행.- 0세대에 대해 GC가 수행되면 1세대의 count가 1 증가함.
- 즉,
threshold 0
가 700이고,threshold 1
이 10이면, 1세대는 $700\times 10=7000$번만에 GC가 수행됨.
다음 코드는 각 genration별로 할당된 threshold의 수를 확인할 수 있음.
import gc
print(gc.get_threshold())
Trade-off
- GC는 Memory를 monitor하는데 필요한 연산과 자원을 소비함: 이는 전체 시스템의 수행속도를 느리게 할 수 있음.
- Programmer가 GC를 제어하지 못하기 때문에, 매우 중요한 작업을 수행해야하는 시점에 GC가 수행되어 문제가 발생할 수도 있음.
- GC의 경우, 잘못된 memory 회수는 program이 죽는 문제를 발생시키기 때문에 가급적 memory 회수를 하지 않는 경향성이 있음. 때문에 능숙한 programmer가 명시적으로 관리하는 경우보다 많은 memory를 사용하는 경향성을 가지게 됨.
- 불필요한 reference등의 존재로 인해 debugging이 보다 어려워진다는 단점이 있음.
참고자료.
보다 자세한 내용을 위해서 다음 URL들을 참조하라.
'Programming' 카테고리의 다른 글
[Python] List Comprehension (0) | 2023.06.06 |
---|---|
[Python] Assignment와 Shallow Copy, Deep Copy (0) | 2023.06.05 |
[Python] Interpreter and PVM (Python Virtual Machine) (1) | 2023.06.05 |
[Python] recursive call : Fibonacci Sequence (0) | 2023.05.24 |
[ML] Levenshtein distance (1) | 2023.05.17 |