일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- kotlin coroutine
- kotlin
- MySQL
- 공부
- CloudWatch
- 기록으로 실력을 쌓자
- 코틀린 코루틴의 정석
- kotlin querydsl
- Linux
- aws
- 티스토리챌린지
- minikube
- 오블완
- CKA 기출문제
- PETERICA
- 정보처리기사 실기
- AWS EKS
- Kubernetes
- IntelliJ
- Elasticsearch
- Spring
- CKA
- AI
- Java
- 정보처리기사실기 기출문제
- 정보처리기사 실기 기출문제
- APM
- Pinpoint
- mysql 튜닝
- kotlin spring
- Today
- Total
피터의 개발이야기
[GO] Go 애플리케이션 메모리 사용량 증가 문제 해결 방법 본문
ㅁ 들어가며
Go 언어로 개발된 애플리케이션에서 메모리 사용량이 지속적으로 증가하는 문제는 흔히 발생할 수 있다. 이 글에서는 Go GC를 너무 믿지 마세요 - 메모리 누수 탐지와 GC 주기 조절이란 글을 읽고 메모리 문제의 원인을 분석하고 해결하는 데 도움이 되는 정보와 방법을 정리해 보았다.
ㅁ 문제 정의
Go 애플리케이션의 메모리 사용량이 시간이 지남에 따라 점진적으로 증가하는 현상은, GC가 있는 Go 언어에서도 발생할 수 있다. 이는 애플리케이션의 안정성과 성능에 영향을 미칠 수 있으므로, 문제 해결을 위한 체계적인 접근이 필요하다.
ㅁ 원인 분석
ㅇ cgo 관련 메모리 누수: cgo를 사용하여 C 코드를 Go에서 호출하는 경우, C 코드에서 메모리 누수가 발생할 수 있다.
ㅇ GC 성능: GC가 메모리 회수 속도를 따라가지 못하는 경우, 메모리 사용량이 증가할 수 있다.
ㅇ 메모리 단편화: 작은 객체들이 빈번하게 할당 및 해제되면서 메모리 공간이 단편화될 수 있다.
ㅁ RES와 Heap 분석
RES(Resident Set Size)와 Heap 크기를 비교하여 Go가 관리하지 않는 메모리 영역에서 문제가 발생하는지 확인한다. RES는 프로세스가 실제로 사용하고 있는 물리 메모리 크기를 나타내며, Heap은 Go 런타임이 관리하는 메모리 영역을 의미한다.
- RES 확인:
top
명령어 사용 - Heap 크기 확인:
runtime
패키지 또는GODEBUG=gctrace=1
환경 변수 사용
RES와 Heap 크기 간의 차이가 크다면 cgo 관련 메모리 누수를 의심해 볼 수 있다.
ㅁ valgrind를 이용한 cgo 메모리 누수 탐지
cgo를 사용하는 경우, valgrind 도구를 사용하여 C 코드에서 메모리 누수가 발생하는지 탐지한다. cgo 코드만 사용하는 테스트 코드를 별도로 빌드하여 valgrind를 적용하면 더 정확한 결과를 얻을 수 있다.
ㅁ Go 버전별 커널 메모리 동작 확인
Go 버전에 따라 커널이 메모리를 관리하는 방식이 다를 수 있다.
- Go 1.12 ~ 1.15:
MADV_FREE
사용 (메모리 압력이 없는 한 커널이 메모리 할당 해제를 미룸) - 그 외 버전:
MADV_DONTNEED
사용 (커널의 메모리 할당 해제를 유도)
사용 중인 Go 버전에 따라 RES 값이 다르게 나타날 수 있으므로, 해당 내용을 고려하여 분석해야 한다.
ㅁ GOGC와 GOMEMLIMIT를 이용한 GC 튜닝
GC 주기를 조절하여 메모리 사용량을 최적화합니다.
- GOGC: 목표 Heap 크기를 조절 (기본값: 100)
- GOGC를 높이면 GC 주기가 길어짐
- GOGC를 낮추면 GC 주기가 짧아짐
- GOMEMLIMIT: 목표 Heap 크기의 상한값 설정
테스트 환경에서 다양한 GOGC 및 GOMEMLIMIT 값을 적용하여 최적의 값을 찾아 적용한다.
ㅁ 프로파일러를 이용한 과다 메모리 사용 탐지
Go의 heap 프로파일링을 통해 불필요한 메모리 사용이 있는 코드 부분을 탐지한다. heap 프로파일링을 통해 각 함수가 사용하는 객체의 개수와 메모리 크기를 분석하여 메모리 사용량이 많은 부분을 식별한다.
더 자세한 건 이 글 참조: 프로파일링 적용기 - 당신의 Go 애플리케이션은 좀 더 나아질 수 있다
ㅁ 메모리 단편화 분석
Go의 메모리 할당 방식은 객체의 크기에 따라 달라지며, 내부 단편화가 발생할 가능성이 있다. 특히 크기가 큰 객체를 다량으로 할당하는 경우 메모리 사용량에 영향을 줄 수 있다. heap 프로파일링을 통해 객체 크기의 평균을 계산하여 메모리 단편화 가능성을 확인한다.
ㅁ 개선 방법
- 객체 재사용: 객체를 매번 새로 할당하는 대신 재사용하는 방안을 고려한다.
- 데이터 구조 최적화: 메모리 사용량을 줄일 수 있는 데이터 구조를 선택한다.
- 불필요한 복사 방지: 메모리 복사를 최소화하여 불필요한 메모리 사용을 줄인다.
ㅁ 마무리
Go 애플리케이션의 메모리 사용량 증가 문제는 다양한 원인으로 발생할 수 있다. 이번 글을 통해 제시된 방법들을 활용하여 문제의 원인을 정확하게 파악하고, 애플리케이션에 맞는 최적화 전략을 수립하는 방법에 대해서 정리할 수 있었다.
ㅁ 함께 보면 좋은 사이트
ㅇ Go GC를 너무 믿지 마세요 - 메모리 누수 탐지와 GC 주기 조절
ㅇ 프로파일링 적용기 - 당신의 Go 애플리케이션은 좀 더 나아질 수 있다
'Programming > GO' 카테고리의 다른 글
[GO] Golang에서 Viper 사용하기: 설정 관리 도구 (0) | 2025.01.10 |
---|---|
[GO] Intel Xeon 프로세서 빌드 방법, GOOS, GOARCH 설정 (0) | 2024.12.06 |
[GO] Golang에서 http.Client를 이용한 프록시 설정방법 (0) | 2024.12.05 |
[GO] GO 언어란? 기본 문법 (2) | 2024.11.19 |
[GO] Goroutine과 Coroutine의 차이점 (0) | 2024.09.13 |