JavaRush /Java Blog /Random-KO /커피 브레이크 #210. 알아야 할 Java의 모든 유형의 가비지 수집기

커피 브레이크 #210. 알아야 할 Java의 모든 유형의 가비지 수집기

Random-KO 그룹에 게시되었습니다
출처 : Hackernoon 이 게시물을 통해 Java 개발에 사용되는 가비지 컬렉터 유형별 장단점을 알아보겠습니다. 커피 브레이크 #210.  알아야 할 Java의 모든 유형의 가비지 수집기 - 1거의 모든 인터뷰에서 GC(Garbage Collector)에 대한 질문을 들을 수 있습니다. 그래서 저는 제가 가장 좋아하는 짧고 간단한 원칙을 사용하여 필요한 모든 정보를 수집하기로 결정했습니다. 먼저 CG의 목적과 여러 유형의 가비지 수집기가 필요한 이유부터 시작하겠습니다. C와 같은 언어에서는 객체 정보를 메모리에 저장하고 그 메모리를 확보하기 위해 많은 상용구 코드를 작성해야 합니다. 물론 이러한 프로그램에서는 메모리 누수가 흔히 발생합니다. Java는 가비지 수집기를 사용하여 메모리 누수 문제를 해결합니다. 그리고 개발자로서 어떤 가비지 수집기가 사용하기에 가장 좋은지 알아야 합니다. 프로그램이 실행되는 위치와 방법에 따라 많은 것이 달라집니다. 약한 하드웨어나 많은 개체에서 실행될 수 있으며, 그렇지 않으면 프로그램이 매우 빨라야 합니다. 이러한 조건에 따라 가비지 수집기를 조정하여 원하는 성능을 달성해야 합니다. 그럼 시작해 보겠습니다.

JVM이 메모리를 처리하는 방법

JVM(Java Virtual Machine)은 메모리를 애플리케이션 데이터를 저장하는 힙(heap)과 프로그램 코드 및 기타 데이터를 저장하는 비힙(non-heap)의 두 영역으로 나눕니다. 이제 힙 영역에 주목해 보겠습니다. 이곳은 우리 프로그램이 새로운 객체를 생성하는 곳입니다. 모든 가비지 수집기는 많은 프로그램이 임시 개체를 사용한다는 사실을 기반으로 합니다. 즉, 이러한 객체는 생성된 후 해당 기능을 수행했으며 더 이상 필요하지 않습니다. 그러한 개체의 대부분. 그러나 일부 개체는 프로그램 전체 기간 동안 훨씬 더 오래 살 수 있습니다. 사물을 젊은 세대와 노년층으로 나누는 아이디어가 나오는 곳이다. 그리고 우리는 젊은 세대를 매우 자주 점검해야 합니다. 사실 가비지 수집 프로세스는 젊은 세대에게만 영향을 미치는 간단한 청소와 두 세대 모두에 영향을 미칠 수 있는 전체 청소로 구분됩니다. 가비지 수집기는 프로그램이라는 점을 기억하세요. 그리고 컴퓨터가 작동하려면 시간과 리소스가 필요합니다. 이는 우리의 응용 프로그램에도 영향을 미칩니다. 어떤 영향을 미치나요? 예를 들어 가비지 수집을 수행하기 위해 JVM은 애플리케이션을 일시 중지합니다. 이를 STW(Stop-The-World) 일시 중지라고 합니다. 이 시간 동안 모든 애플리케이션 스레드가 일시 중지됩니다. 그러나 내부의 애플리케이션은 이를 전혀 인식하지 못합니다. 애플리케이션의 경우 시간이 고르게 흐릅니다. 이것이 왜 그렇게 나쁜가요? 당신이 일종의 교환 신청서나 비행기 자동 조종 장치를 위한 신청서를 작성하고 있다고 상상해 보십시오. 애플리케이션이 1초 동안 절전 모드로 전환되어 문제의 성격이 극적으로 바뀔 수 있습니다. 즉, 일시 중지는 모든 가비지 수집기의 중요한 매개 변수입니다. 가비지 수집기의 다음 기본 속성은 프로그램의 총 실행 시간과 관련하여 가비지 수집에 소비된 총 시간입니다. 이것이 무엇을 의미하며 왜 그렇게 중요한가요? 하나의 큰 "Stop-The-World" 단계 대신 작은 일시 중지가 많은 알고리즘을 선택할 수 있습니다. 짧은 휴식이 바람직하지만, 공짜는 없습니다. 이 경우 프로그램의 총 실행 시간을 늘려 비용을 지불합니다. 그리고 우리는 이것도 고려해야 합니다. 다음 매개변수는 하드웨어 리소스의 양입니다. 각 수집기에는 개체 정보를 저장하기 위한 메모리와 정리를 수행하기 위한 프로세서가 필요합니다. 마지막 매개변수는 속도입니다. 가비지 수집 효율성은 GC(가비지 수집기)가 프로그램에서 더 이상 사용하지 않는 메모리를 얼마나 빠르고 효율적으로 회수하는지를 나타냅니다. 이러한 모든 매개변수는 최소한의 리소스를 소비하면서 가능한 한 빨리 메모리를 확보할 수 있는 알고리즘에 영향을 미칩니다. 우리가 사용할 수 있는 가비지 수집기를 살펴보겠습니다. 인터뷰를 위해서는 처음 5가지를 알아야 합니다. 나머지 두 가지는 훨씬 더 어렵습니다.

직렬 GC

Serial GC는 Java Virtual Machine의 가비지 수집기이며 Java 시작부터 사용되었습니다. 힙이 작고 성능이 낮은 시스템에서 실행되는 프로그램에 유용합니다. 이 가비지 수집기는 힙을 Eden 및 Survivor를 포함하는 영역으로 나눕니다. Eden 영역은 대부분의 개체에 대한 메모리가 처음 할당되는 풀입니다. Survivor는 Eden 지역의 가비지 수집에서 살아남은 개체를 포함하는 풀입니다. 힙이 채워지면 객체는 Eden과 Survivor 영역 사이에서 이동됩니다. JVM은 Survivor 영역으로의 객체 이동을 지속적으로 모니터링하고 이러한 이동 횟수에 대해 적절한 임계값을 선택한 후 객체를 Tenured 영역으로 이동합니다. Tenured 영역에 공간이 충분하지 않으면 전체 가비지 수집이 대신되어 두 세대의 개체에 대해 작업합니다. 이 가비지 수집기의 가장 큰 장점은 리소스 요구 사항이 낮다는 점입니다. 따라서 저전력 프로세서만으로도 수집을 수행할 수 있습니다. 직렬 GC의 주요 단점은 특히 대용량 데이터의 경우 가비지 수집 중에 오랜 일시 중지가 발생한다는 것입니다.

평행 CG

병렬 가비지 수집기(병렬 CG)는 순차 생성자와 유사합니다. 여기에는 일부 작업의 병렬 처리와 성능 설정을 자동으로 조정하는 기능이 포함됩니다. 병렬 GC는 직렬 GC의 아이디어를 기반으로 하지만 병렬성과 지능이 추가된 Java Virtual Machine 가비지 수집기입니다. 컴퓨터에 둘 이상의 프로세서 코어가 있는 경우 이전 버전의 JVM은 자동으로 병렬 GC를 선택합니다. 여기의 힙은 직렬 GC와 동일한 영역(Eden, Survivor 0, Survivor 1 및 Old Gen(Tenured))으로 나뉩니다. 그러나 여러 스레드가 가비지 수집에 병렬로 참여하고 수집기는 필요한 성능 매개변수에 맞게 조정할 수 있습니다. 각 수집기 스레드에는 지워야 하는 메모리 영역이 있습니다. 병렬 GC에는 필요한 가비지 수집 효율성을 달성하기 위한 설정도 있습니다. 수집기는 이전 가비지 수집의 통계를 사용하여 향후 수집에 대한 성능 설정을 조정합니다. 병렬 GC는 성능 매개변수의 자동 조정과 낮은 빌드 일시 중지 시간을 제공하지만 일부 메모리 조각화 형태의 사소한 단점이 하나 있습니다. 대부분의 애플리케이션에 적합하지만 더 복잡한 프로그램의 경우 고급 가비지 수집기 구현을 선택하는 것이 좋습니다. 장점: 많은 경우 직렬 GC보다 빠릅니다. 속도가 좋습니다. 단점: 더 많은 리소스를 소비하고 일시 중지 시간이 상당히 길어질 수 있지만 Stop-The-World의 최대 일시 중지 기간을 조정할 수 있습니다.

동시 마크 스윕

CMS(Concurrent Mark Sweep) 가비지 수집기는 일부 가비지 수집 작업을 애플리케이션 스레드와 동시에 실행하여 최대 일시 중지 시간을 줄이는 것을 목표로 합니다. 이 가비지 컬렉터는 메모리의 대용량 데이터를 관리하는 데 적합합니다. CMS(Concurrent Mark Sweep)는 JVM(Java Virtual Machine)의 병렬 GC에 대한 대안입니다. 이는 여러 프로세서 코어에 대한 액세스가 필요하고 Stop-The-World 일시 중지에 민감한 애플리케이션을 위한 것입니다. CMS는 기본 프로그램과 병렬로 가비지 수집 단계를 수행하므로 중단 없이 실행할 수 있습니다. 직렬 및 병렬 수집기와 동일한 메모리 구성을 사용하지만 이전 세대 제거를 실행하기 전에 Tenured 영역이 채워질 때까지 기다리지 않습니다. 대신, 백그라운드에서 실행되며 Tenured 영역을 컴팩트하게 유지하려고 합니다. 동시 표시 스윕은 애플리케이션의 기본 스레드를 잠시 중지하고 루트에서 액세스할 수 있는 모든 객체를 표시하는 초기 표시 단계로 시작됩니다. 그러면 응용 프로그램의 기본 스레드가 다시 시작되고 CMS는 표시된 루트 개체의 링크를 통해 액세스할 수 있는 모든 활성 개체를 검색하기 시작합니다. 모든 살아있는 개체를 표시한 후 수집기는 여러 병렬 스레드를 통해 죽은 개체의 메모리를 지웁니다. CMS의 이점 중 하나는 가동 중지 시간을 최소화하는 데 중점을 두고 있다는 점입니다. 이는 많은 애플리케이션에 매우 중요합니다. 그러나 CPU 리소스와 전체 대역폭 측면에서 희생이 필요합니다. 또한 CMS는 이전 세대의 개체를 압축하지 않으므로 조각화가 발생합니다. 병렬 모드 오류로 인한 긴 일시 중지는 예상치 못한 일이 될 수 있습니다(자주 발생하지는 않지만). 메모리가 충분하면 CMS는 이러한 일시 중지를 방지할 수 있습니다. 장점: 빠르다. 작은 Stop-The-World 일시 중지가 있습니다. 단점: 더 많은 메모리를 소비합니다. 메모리가 부족하면 일부 일시 중지가 길어질 수 있습니다. 응용 프로그램이 많은 개체를 생성하는 경우에는 별로 좋지 않습니다.

쓰레기 우선

G1(Garbage-First)은 특히 다중 프로세서 서버에서 실행되고 대규모 데이터 세트를 관리하는 서버 애플리케이션의 경우 CMS의 대안으로 간주됩니다. G1 가비지 수집기는 거대한 영역(대량 개체를 수용하기 위해 일반 영역을 병합하여 생성됨)을 제외하고 메모리를 동일한 크기의 여러 영역으로 변환합니다. 지역은 연속적으로 구성될 필요가 없으며 세대 소속을 변경할 수 있습니다. 젊은 세대에 대해 주기적으로 소규모 퍼지를 수행하고 개체를 Survivor 영역으로 이동하거나 이전 세대로 업그레이드하여 Tenured로 전송합니다. 청소는 원하는 시간을 초과하지 않는 것이 필요한 지역에서만 수행됩니다. 수집가가 직접 청소할 쓰레기가 가장 많은 지역을 예측하고 선택합니다. 전체 스윕은 표시 루프를 사용하여 기본 애플리케이션과 병렬로 실행되는 라이브 개체 목록을 만듭니다. 마킹 주기 후에 G1은 제거할 젊은 세대 영역 집합에 이전 세대 영역을 추가하는 혼합 제거 실행으로 전환합니다. G1 가비지 수집기는 일시 중지 크기를 예측하는 데 CMS 수집기보다 더 정확한 것으로 간주되며 시간이 지남에 따라 가비지 수집을 더 잘 분산하여 특히 힙 크기가 큰 경우 긴 애플리케이션 가동 중지 시간을 방지합니다. 또한 CMS 수집기처럼 메모리를 조각화하지 않습니다. 그러나 G1 수집기는 기본 프로그램과 병렬로 실행하려면 더 많은 CPU 리소스가 필요하므로 애플리케이션 처리량이 줄어듭니다. 장점: CMS보다 더 잘 작동합니다. 일시 중지 시간이 더 짧습니다. 단점: 더 많은 CPU 리소스를 소비합니다. 또한 매우 큰 개체(500KB 이상)가 많은 경우 이러한 개체를 하나의 영역(1~32MB)에 저장하므로 더 많은 메모리를 소비합니다.

엡실론 GC

Epsilon GC는 가비지 수집이 필요하지 않은 상황을 위해 설계되었습니다. 가비지 수집을 수행하지 않지만 TLAB(스레드 로컬 할당 버퍼)를 사용하여 새 객체(힙의 개별 스레드가 요청하는 작은 메모리 버퍼)를 할당합니다. 버퍼 요청 메모리 블록에 맞지 않는 거대한 개체는 자체적으로 메모리 블록을 요청합니다. Epsilon GC에 리소스가 부족해지면 OutOfMemoryError가 생성되고 프로세스가 종료됩니다. Epsilon GC의 이점에는 시작 시 필요한 모든 개체를 생성하거나 할당된 메모리를 모두 사용하지 않는 단기 애플리케이션을 실행하는 애플리케이션에 대한 더 낮은 리소스 요구 사항과 더 빠른 메모리 할당이 포함됩니다. Epsilon GC는 다른 가비지 수집기가 애플리케이션에 추가하는 리소스 요구 사항을 분석하는 데도 도움이 될 수 있습니다. 장점: 매우 빠릅니다. 단점: 개체를 지우지 못합니다 :) 다음 두 수집기는 동종 중에서 가장 진보된 것이지만 가장 복잡합니다. 그러므로 우리는 그것들을 간략하게 고려할 것입니다.

ZGC

ZGC는 엄청난 양의 데이터를 처리하는 경우에도 밀리초 미만의 대기 시간을 유지할 수 있습니다. ZGC는 Oracle이 Java용으로 개발한 가비지 수집기로, 대규모 힙(최대 16TB)을 처리할 때 높은 처리량과 낮은 대기 시간을 제공하도록 설계되었습니다. ZGC는 가상 메모리 원칙을 기반으로 하며 다양한 색상 표시를 사용하여 가비지 수집 중에 객체의 상태를 추적합니다. 장점: 일시 중지는 큰 힙에서도 1밀리초 미만이므로 짧은 쿼리 처리 시간이 필요한 애플리케이션에 매우 유용합니다. 처리량이 좋은 매우 큰 힙에서 작동합니다. ZGC는 가비지 수집 중에 힙 메모리를 압축할 수 있습니다. 단점: 높은 CPU 사용량과 상당한 성능 요구 사항으로 인해 애플리케이션 시작 시간이 느려질 수 있습니다.

셰넌도어 G.C.

Shenandoah GC는 힙 크기에 관계없이 잠시 중지되는 또 다른 가비지 수집기입니다. 이 가비지 수집기는 Red Hat에서 개발했습니다. 이는 애플리케이션이 가비지 수집에 소비하는 시간을 최소화하도록 설계되었습니다. ZGC와 마찬가지로 병렬 수집기입니다. 즉, 애플리케이션이 실행되는 동안 실행되어 일시 중지를 최소화합니다. Shenandoah GC는 "전달 포인터"를 사용하여 가비지 수집 중에 개체를 이동합니다. 성능을 향상시키기 위해 "로드 배리어 제거"라는 기술도 있습니다. 장점: Shenandoah GC는 대규모 힙의 경우에도 종종 10ms 미만의 짧은 일시 중지 시간을 달성할 수 있습니다. 좋은 처리량. 단점: 프로세서 로드가 높고 로드가 많은 경우 작업이 어렵습니다.

결론

가비지 수집기는 프로그래밍에서 가장 어려운 작업 중 하나입니다. 이 방향으로 새로운 개발이 지속적으로 수행되고 있습니다. 프로그래머가 GC를 조정하는 경우는 드물지만 가비지 수집 도구의 작동 방식에 대해 최소한의 지식이 있어야 합니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION