일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 알고리즘
- git 기본명령어
- 앙상블
- eda
- Spark jdbc parallel read
- Python
- 배깅
- SQL
- git stash
- 랜덤포레스트
- Collaborative filtering
- Spark 튜닝
- 오라클 데이터 처리방식
- airflow 정리
- Oracle ASSM
- Linux
- Oracle 논리적 저장 구조
- Decision Tree
- 데이터분석
- CF
- 네트워크
- 추천시스템
- BFS
- 의사결정나무
- 리눅스 환경변수
- git init
- enq: FB - contention
- 데이터 분석
- Spark Data Read
- 통계분석
- Today
- Total
[Alex] 데이터 장인의 블로그
[JVM] JVM의 Garbage Collector (Feat. 튜닝을 위해서..) 본문
저번 글에 이어서 GC에 대해 공부해보고자 한다.
2022.12.19 - [Hadoop & Spark] - [JVM] 기본 개념 정리
Garbage Collector
Heap 영역에서 동적으로 할당된 객체 중 사용하지 않은 객체을 탐지하여 해제하는 기능.
한정된 Heap 메모리를 효율적으로 사용하기 위한 방법. 자바 이전에는 프로그래머가 모든 프로그램 메모리를 관리했다고 한다. 하지만 자바에서는 JVM이 가비지 컬렉션이라는 프로세스를 통해 프로그램 메모리를 관리한다. 가비지 컬렉션은 자바 프로그램에서 사용되지 않는 메모리를 지속적으로 찾아내서 제거하는 역할을 한다.
단점 : GC 작업은 순수 오버헤드로 프로그램이 해야할 일을 하지 못하도록 하는 순간이다.
Mark and Sweep
Java가 채택하고 있는 Mark & Sweep 방식은 루트에서부터 해당 객체에 접근이 불가능한 (Unreachable)지를 확인한 후에, 모두 삭제한다.
단점 : 의도적으로 GC를 실행시켜야 한다. 어플리케이션 실행과 GC의 실행이 병행된다.
Stop-the-world
GC를 실행하기 위해 JVM이 애플리케이션 실행을 멈추는 것. 이 시간을 최소화 하는 것이 GC를 최적화하는 방법.
어떤 GC 알고리즘을 사용하더라도 stop-the-world 는 발생하게 되는데, 대개의 경우 GC 튜닝은 이 stop-the-world 시간을 줄이는 것이다. GC를 해도 더 이상 사용 가능한 메모리 영역이 없는데 계속 메모리를 할당하려고 하면, OutOfMemoryError가 발생하여 WAS가 다운될 수도 있다.
행(Hang)
서버가 요청을 처리 못하고 있는 상태
Stack vs Heap
Stack : 정적으로 할당된 메모리 영역
원시 타입의 데이터가 값과 함께 할당, Heap 영역에 생성된 Object 타입의 데이터의 참조 값 할당
Heap : 동적으로 할당된 메모리 영역
모든 Object 타입의 데이터가 할당. Heap영역의 Object를 가리키는 참조 변수가 Stack에 할당
Reachable, Unreachable
HEAP 메모리의 ROOT SPACE
- 1. STACK의 로컬 변수
- 2. Method Area의 Static 변수
- 3. Native Method Stack의 JNI 참조
의도적으로 GC를 실행시키는 기준
Young VS Old generation
두개를 나누어서 관리하는 이유 : 대부분의 객체가 수명이 짧기 때문에 짧은 객체를 minor GC로 따로 관리하는 것이 더욱 효율적.
Young generation에서 발생하는 GC : Minor GC
- Minor GC : 비교적 시간이 짧고 간단.
Old generation에서 발생하는 GC : Major GC
- Major GC : 비교적 시간이 길고 복잡. 더 오랜시간 소요.
어플리케이션 실행과 GC 실행 병행
GC를 실행하는 동안은 애플리케이션 동작이 멈춤 (Stop the world)
- GC의 역사 : Serial GC -> Parallel GC (java 8) -> CMS GC (메모리, CPU 과도사용) -> G1 GC
Serial GC
- 하나의 쓰레드로 GC를 실행
- Stop The World 시간이 긺
- 싱글 쓰레드 환경 및 Heap이 매우 작을 때 사용
Parallel GC (java 8)
- 여러 개의 쓰레드로 GC를 실행
- 멀티 코어 실행.
CMS GC (메모리, CPU 과도사용)
- 애플리케이션 쓰레드와 함께 구동
- 메모리 파편화 해결 모듈 기본 탑재 X
G1 GC
- Heap을 Region 으로 나누어 사용.
- 자동으로 Young generation 과 Old generation 비율을 최적화
- Java 9 부터 채택
GC 튜닝을 위한 기초 내용 [참고]
GC 튜닝을 위해서는!
1. Old Generation 으로 넘어가는 객체 최소화
2. Major GC 시간을 짧게 유지.
이 두가지가 필요하다.
GC 상태 모니터링
어떤 GC를 채택하는지, 기본 Heap 사이즈 등 확인할 수 있는 방법.
java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=2147483648
-XX:MaxHeapSize=32210157568
-XX:+PrintCommandLineFlags
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:+UseParallelGC
openjdk version "1.8.0_322"
OpenJDK Runtime Environment (Zulu 8.60.0.21-CA-linux64) (build 1.8.0_322-b06)
OpenJDK 64-Bit Server VM (Zulu 8.60.0.21-CA-linux64) (build 25.322-b06, mixed mode)
지금 구동되고 있는 GC상태를 확인하고자 한다면, jstat 사용.
jstat -gcutil -t [PID] 1000 10 # 1초씩 10번
Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
60078.0 3.01 0.00 61.75 27.47 88.89 87.78 26072 305.462 37 12.251 317.713
60079.0 0.00 99.88 98.99 27.49 88.89 87.78 26073 305.471 37 12.251 317.722
60080.0 64.52 0.00 17.61 27.50 88.90 87.79 26074 305.482 37 12.251 317.733
60081.0 64.52 0.00 37.78 27.50 88.90 87.79 26074 305.482 37 12.251 317.733
60082.0 64.52 0.00 61.54 27.50 88.90 87.79 26074 305.482 37 12.251 317.733
60083.0 64.52 0.00 92.99 27.50 88.90 87.79 26074 305.482 37 12.251 317.733
60084.0 0.00 64.69 24.66 27.51 88.90 87.79 26075 305.494 37 12.251 317.745
60085.0 0.00 64.69 48.97 27.51 88.90 87.79 26075 305.494 37 12.251 317.745
60086.0 0.00 64.69 68.36 27.51 88.90 87.79 26075 305.494 37 12.251 317.745
60087.0 0.00 64.69 88.96 27.51 88.90 87.79 26075 305.494 37 12.251 317.745
Young generation 영역부터
s0 : Servivor-0
s1 : Servivor-1
E : Eden
O : Old generation
YGC : Young generation 이벤트 수
YGCT : Young generation GC Time
즉, YGCT/YGC = minor GC 한번에 0.011초 소요
FGC : Full GC 이벤트 수
FGCT : Full GC Time
즉, FGCT/FGC = major GC 한번에 0.32초 소요
GCT : 모든 가비지 컬렉션 총 시간
만약 MAJOR GC의 시간이 오래걸려 DB Connection 시간이 일정시간을 넘어가게 된다면? : DB Connection timeout 시간초과로 장애의 원인이 될 수 있다.
마찬가지로 GC가 할당받은 Heap Memory 를 확인하고자 한다면, jstat -gccapacity -t 924307 1000 10
jstat -gccapacity -t 924307 1000 10
Timestamp NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC
61073.5 698880.0 5592064.0 793088.0 265216.0 266240.0 257024.0 1398272.0 11185152.0 2602496.0 2602496.0 0.0 1171456.0 139776.0 0.0 1048576.0 18176.0 26552 37
61074.5 698880.0 5592064.0 805888.0 267776.0 266240.0 257024.0 1398272.0 11185152.0 2602496.0 2602496.0 0.0 1171456.0 139776.0 0.0 1048576.0 18176.0 26553 37
61075.5 698880.0 5592064.0 805888.0 267776.0 266240.0 257024.0 1398272.0 11185152.0 2602496.0 2602496.0 0.0 1171456.0 139776.0 0.0 1048576.0 18176.0 26553 37
61076.5 698880.0 5592064.0 805888.0 267776.0 266240.0 257024.0 1398272.0 11185152.0 2602496.0 2602496.0 0.0 1171456.0 139776.0 0.0 1048576.0 18176.0 26553 37
61077.5 698880.0 5592064.0 805888.0 267776.0 266240.0 257024.0 1398272.0 11185152.0 2602496.0 2602496.0 0.0 1171456.0 139776.0 0.0 1048576.0 18176.0 26553 37
61078.5 698880.0 5592064.0 800768.0 266240.0 265216.0 256000.0 1398272.0 11185152.0 2602496.0 2602496.0 0.0 1171456.0 139776.0 0.0 1048576.0 18176.0 26555 37
61079.5 698880.0 5592064.0 800768.0 266240.0 265216.0 256000.0 1398272.0 11185152.0 2602496.0 2602496.0 0.0 1171456.0 139776.0 0.0 1048576.0 18176.0 26555 37
61080.5 698880.0 5592064.0 803328.0 266240.0 266752.0 267776.0 1398272.0 11185152.0 2602496.0 2602496.0 0.0 1171456.0 139776.0 0.0 1048576.0 18176.0 26556 37
61081.5 698880.0 5592064.0 803328.0 266240.0 266752.0 267776.0 1398272.0 11185152.0 2602496.0 2602496.0 0.0 1171456.0 139776.0 0.0 1048576.0 18176.0 26556 37
61082.5 698880.0 5592064.0 803328.0 266240.0 266752.0 267776.0 1398272.0 11185152.0 2602496.0 2602496.0 0.0 1171456.0 139776.0 0.0 1048576.0 18176.0 26556 37
NG : Young generation
OG : Old generation
793MB / 2602MB
CMN : 최소 할당
CMX : 최대 할당
C : 현재 할당
GC 메모리 튜닝을 위해서는 위 내용을 확인한 후 진행.
1. Heap 크기 설정
- JVM 시작 시 힙 영역의 크기
- 최대 힙 영역 크기
2. New 영역 크기 설정
-XX:NewRatio
new 영역과 old영역의 비율
-XX:NewRatio=1 NEW : OLD == 1:1
-XX:NewRatio=2 NEW : OLD == 1:2
-XX:NewSize : New 영역의 크기
-XX:SurvivorRatio : Eden 영역과 Survivor 영역의 비율
'Hadoop & Spark' 카테고리의 다른 글
[Spark] 성능 튜닝(1) - Data Ingestion (Feat. JDBC Parallel Read) (0) | 2023.01.05 |
---|---|
[JVM] 기본 개념 정리 (0) | 2022.12.19 |
Spark 프로그래밍 - RDD, DataFrame (0) | 2021.05.01 |
Spark 프로그래밍 환경 구성 - 1. 로컬모드 설치 (0) | 2021.04.22 |
Hadoop 기본 (0) | 2021.02.27 |