Ilhwanee's Devlog
로그인
Ilhwanee's Devlog
로그인
GC(Garbage Collection)란? + GC 기법에 대해
Ilhwanee
·
2022년 7월 6일
팔로우
0
CS
GC
0
CS
목록 보기
7/27
GC(Garbage Collection)란?
메모리 관리 기법 중 하나로 프로그램이 동적으로 할당했던
메모리 영역 중에서 필요없게 된 영역을 해제하는 기능
이다.
더 이상 필요없게 된 영역이란
어떤 변수도 가리키지 않게 된 영역
을 의미한다.
Java의 경우 처음부터 GC 기법을 염두에 두고 설계되어 언어 정의에 쓰레기 수집이 포함되어 있다.
다음과 같은 버그들을 줄이거나 완전히 막을 수 있다는 장점을 가진다.
유효하지 않은 포인터 접근 방지
이미 해제된 메모리에 접근하는 버그로 만약 이 포인터가 해제되고 새로운 값이 할당되었다면 잘못된 값을 읽어온다.
이중 해제
이미 해제된 메모리를 또다시 해제하는 것이다.
메모리 누수
더이상 필요하지 않은 메모리가 해제되지 않고 남아있으면 메모리 고갈로 프로그램이 중단될 수 있다.
반면에 다음과 같은 단점들도 존재한다.
어떤 메모리를 해제할지 결정하는 비용이 들어
오버헤드
가 된다.
GC가 일어나는 타이밍이나 점유 시간을
예측하기 어렵다
.
할당된 메모리가
해제되는 시점을 알 수 없다
.
대부분의 GC 기법인 포인터 추적 방식
한 개 이상의 변수가 접근 가능한 메모리는 앞으로 사용할 수 있는 메모리로 간주
하고, 그 밖의 메모리를 해제하는 방식이다.
포인터 추적 방식을 사용하는 여러가지 기법이 존재한다.
표시하고 쓸기
가장 단순한 기법
이다.
각 메모리 할당 영역을 표시하기 위해 1비트의 메모리를 남겨 둔다.
표시 단계에서
모든 변수가 가리키는 영역을 "사용 중"으로 표시
하고, 그 영역에서 가리키는 또다른 영역 또한 "사용 중"으로 표시한다.
표시되지 않은 영역을 접근 불가능한 메모리 영역으로 간주
하고 쓸기 단계에서 모두 해제한다.
표시 단계에서 메모리 내용이 변경되지 않아야 하기 때문에 전체 시스템의 실행이 정지되는 단점이 존재한다.
또한 전체 메모리 영역을 검사해야 하므로 메모리 페이징을 사용하는 운영체제에서 프로그램의 성능이 저하될 수 있다.
삼색 표시 기법
표시하고 쓸기와 같은 기법이지만, 표시 단계에서 2가지가 아닌
3가지(흰색, 회색, 검은색)정보 중 하나로 메모리를 표시
한다.
흰색은 더 이상 접근 불가능한 객체, 회색은 접근 가능한 객체이지만 이 객체에서 가리키는 객체들은 아직 검사되지 않음, 검은색은 이 영역에서 가리키는 객체들이 흰색 객체를 가리키지 않음을 의미한다.
순서는 다음과 같다.
각각의 객체를 흰색, 회색, 검은색으로 분류한다.
회색으로 표시된 객체 가운데 하나를 선택하여 검은색으로 표시하고 이 객체가 가리키는 모든 객체를 회색으로 표시한다.
회색 객체가 하나도 남지 않을 때까지 위 과정을 반복한다.
남은 흰색 객체는 접근 불가능한 객체이므로 모두 해제한다.
프로그램이 실행 중에도 병행하여 수행할 수 있으며 메모리가 고갈되었을 때 쓰레기 수집을 실행하는 것이 아닌,
주기적으로 수집하는 것도 가능
하다.
객체 이동 기법
해제할 객체 표시가 완료된 후 해제되지 않은 객체를 그대로 두는 것이 아닌
다른 영역으로 복사
하는 기법이다.
다음과 같은 장점을 가지고 있다.
해제된 후 재사용 가능한 영역과 사용 중인 영역을 표시하기 위해
추가적인 작업을 할 필요가 없다
.
할당된 메모리들이 단편화되는 것을 막을 수 있다.
서로 연결된 객체들이 메모리 상에서 가까운 위치에 할당될 확률이 높으므로
캐시와 관련하여 성능이 향상
된다.
하지만 주기적으로 포인터의 내용이 바뀌므로
포인터 연산을 사용할 수 없는 단점
이 있다.
세대 단위 쓰레기 수집
새롭게 할당된 영역일수록 금방 해제될 확률이 높다는 특성을 이용
하였다.
각각의 객체를
할당된 시간에 따라 세대별로 구분
하여, 각 세대별로 서로 다른 메모리 영역에 객체를 할당한다.
만약 한 세대의 메모리 영역이 꽉 차면, 이 메모리 영역에서
살아남은 객체들을 더 오래된 메모리 영역으로 옮긴다
.
Java가 이 기법을 사용한다.
참조 횟수 계산 방식
일부 GC 기법은 참조 횟수 계산 방식을 사용한다.
다음과 같은 장점을 가지고 있다.
객체가 접근 불가능해지는 즉시 메모리가 해제
되므로 객체의 해제 시점을 어느정도 예측할 수 있다.
객체가 사용된 직후에 메모리를 해제하므로 이미
캐시에 저장되어 있는 객체를 빠르게 메모리에서 해제
할 수 있다.
반면, 다음과 같은 단점들이 존재한다.
두 개 이상의 객체가 서로를 가리키고 있을 경우
에 참조 횟수가 0이 되지 않기 때문에 메모리 누수가 발생한다. 참조 횟수를 증가시키지 않는 약한 참조를 사용하게 해결할 수 있다.
멀티 스레드 환경에서 스레드 간에 공유하는 객체
의 참조 횟수를 계산하려면 락을 걸어야할 수 있다. 이 문제를 피하기 위해 스레드 단위 지역변수로 참조 횟수를 따로 관리하면서 스레드 단위에서 참조 횟수가 0이 될 때 전역 참조 횟루를 확인하는 방식을 사용할 수 있다.
참조 횟수가 0이 될 때 해당 객체가 가리키는
다른 객체들 또한 동시에 0으로 만드는 작업
이 일어나는데, 이 과정에서 많은 시간이 걸릴 수 있어 실시간 시스템에는 적합하지 않을 수 있다.
Ilhwanee
블로그 이전 -> https://pppp0722.github.io
팔로우
이전 포스트
이더넷(Ethernet)이란?
다음 포스트
OOP의 특징과 SOLID에 대하여
0개의 댓글
댓글 작성