새로운 내용을 공부할 때
새로운 내용의 공부를 시작할 때 용어의 정의를 이해하지 못하거나 정확하게 알지 못한다면 그 용어가 포함된 문장을 이해하지 못합니다.
작은 단어 하나가 내용을 이해하지 못하게 하기 때문에 용어를 정확하게 이해하는 것이 중요합니다.
가비지 컬렉션 심화 질문 정리
가비지 컬렉션에 대해서 질문에 대한 대답을 정리해보았습니다.
1. Young generation 과 Old Generation 의 차이가 무엇인가요?
- 첫번째 차이는 동작하는 GC가 다릅니다.
Young Generation에서 동작하는 GC는 Minor GC가 동작하며, Old Generation에서 동작하는 GC는 Major GC가 동작합니다.
- 두번째 차이는 저장 조건이 다르다.
YounGeneration 영역에 저장되는 객체는 생성 된지 얼마 안되는 객체가 저장이 되지만 OldGeneration 영역에 저장되는 객체는 다음과 같은 조건을 만족해야합니다.
- YoungGeneration 에서 여러 번의 GC를 거쳐 Age가 증가한 객체
- 매우 큰 객체가 YoungGeneration에 맞지 않은 경우
- 세번째 차이는 구조가 다르다.
Young Generation은 Eden, Survivor0 , Survivor1 으로 나누어 관리가 되지만 Old Generation 하나로 관리가 됩니다.
2. Eden 과 Survivor 의 차이는 무엇인가요?
- 첫번째 차이는 단방향이라고 생각합니다.
Eden에서 GC가 동작하여 살아있는 참조 객체는 Survivor로 이동은 가능하지만, Survivor에서 GC가 동작한다고 해도 Eden으로 갈 수 없습니다.
- 두번째 차이는 생성 조건입니다.
Eden 영역은 개발자의 코드로 추가가 됩니다. 따라서 개발자의 코드로 Eden 영역에 생성되는 참조 객체를 조절할 수 있습니다. Survivor 영역에 저장이 되려면 강제로 GC를 실행하는 방법과 GC 알고리즘에 의해 자동으로 실행이 되어 GC가 동작해야 Survivor 영역에 생성이 가능합니다. 강제로 GC를 실행하는 건 서버에 문제가 발생할 수 있으므로 사용하지 않기 때문에 Survivor은 개발자가 코드 레벨에서 제어할 수 없는 영역입니다.
3. Survivor 영역은 왜 두개인가요?
이유는 GC 동작을 메모리 정리 최적화와 age 관리 영역을 집중할 수 있습니다. 만약 Survior 영역이 하나 일 경우와 두 개일 경우를 비교해보겠습니다.
- 힙 메모리는 동적 메모리 할당으로 메모리 크기가 고정적이지 않습니다.
- GC가 동작하여 메모리를 정리하면 메모리 파편화로 사용하지 못하는 메모리 영역이 발생됩니다.
- 해결 방법은 여러가지가 있지만 2가지로 정리해보겠습니다
- Mark And Sweep - Compaction 으로 데이터를 정렬하는 방법
- Copy And Remove 방식으로 사용하는 객체만 다른 메모리 영역에 복사하고 나머지를 모두 지우기
- GC가 자주 발생하는 YoungGeneration은 데이터를 정렬하는 방식보다 Copy후 삭제하는 방식이 효율적일 수 있습니다.
- 다른 Servivor 영역으로 이동하는 객체만 age를 신경쓰면 되므로 관리하기도 용이해집니다.
- 따라서 Survivor 영역은 두 개로 나누어 관리하는 것이 메모리를 효율적으로 관리할 수 있습니다.
4. 트래픽이 무지 많이 몰리는 이벤트가 예정되어있습니다. 이때 Young generation과 Old Generation 의 비율은 어떻게 할 것인가요?
저는 트래픽이 몰릴 경우 서비스는 느릴 수 있지만 서버가 터지지 않는 것을 목표로 정해보겠습니다. GC가 오래 걸릴 경우 데이터베이스 연결이나 그외 다른 연결에 문제가 발생할 수 있습니다. GC를 자주 동작하도록 하여 STW의 빈도수를 높이는 대신 지연 시간을 감소하는 방향으로 하려고합니다. 요청 트래픽의 종류에 따라 비율을 다르게 하려고 합니다.
- 요청당 데이터가 커서 Old Generation에 저장되는 경우
저는 Young Generation의 비율을 높이고 Old Generation의 비율을 줄이겠습니다. STW 시간을 줄이기 위해서 Old Generation 영역이 자주 GC가 동작하도록 합니다. Major GC가 오래 걸리는 이유중 하나는 Old Generation의 참조 그래프가 복잡하여 GC대상 탐색이 오래걸리기 때문입니다. 바로 Old Generation으로 저장되는 이 환경에서는 기존 방식보다 더 짧게 탐색이 될 것이라고 예상되기 때문에 STW 시간은 평소보다 짧을 것이고 자주 GC를 동작하기 위해서 Old Generation 영역의 비율을 낮추겠습니다. 만약 Old Generation의 영역이 높인다면 기존에 관리 대상이였던 참조 객체가 존재하게 되고 많은 새로 생성된 참조 객체까지 탐색해야하다 보니 STW 시간이 길어지게 되고 혹시 네트워크 장애로 이어질 수 있다고 생각하기 때문에 Old Generation의 비율을 높이는것보다 줄이는 것이 더 나은 판단이라고 생각됩니다.
- 요청당 단순한 요청으로 Young Generation에 저장되는 경우
마찬가지로 Young Generation의 비율을 높이고 Old Generation의 비율을 줄이겠습니다. 이유는 GC가 자주 동작하게 된다면 불필요한 메모리 이동이 발생하게 됩니다. 1번의 경우와 다르게 Young Generation은 GC가 동작할 때마다 최적화를 위해 참조 객체를 복사하고 메모리를 비우게 됩니다. 그렇다면 자주 GC가 발생하게 되면 그만큼 복사와 삭제과정이 불필요하게 증가하여 오버헤드가 발생되기때문입니다. 이를 방지하고자 Young Generation의 비율을 높여 GC가 자주 발생되지 않도록 합니다. 또 다른 이유는 GC가 자주 동작하게 되면 객체의 AGE도 금방 올라가게 되어 뜻하지 않게 Old Generation으로 이동이 된다면 트래픽이 몰리는 경우 Old Generation이 금방 채워지게 되고 Major GC가 동작하기 때문에 이를 방지하고자 하는 뜻도 있습니다. (편집됨)
댓글남기기