Go 1.26 Green Tea GC, 무엇이 빨라졌나

2026. 10. 1. 13:00·IT
728x90
반응형

Go 1.26이 2026년 2월 10일에 나왔고, 이 릴리스의 주인공은 문법이 아니라 가비지 컬렉터다. 실험 단계였던 Green Tea GC가 기본값으로 켜졌다. GC 부하가 큰 프로그램에서 오버헤드가 10%에서 40%까지 줄어든다는 수치가 함께 나왔다. 이 글은 그 숫자가 어디서 나오는지, 그리고 지연 시간에 민감한 서비스를 운영한다면 무엇을 확인해야 하는지를 정리한다.

객체 단위에서 메모리 블록 단위로 바꿨다

기존 Go GC는 오래된 동시 마크 앤 스윕 방식이었다. 살아 있는 객체를 따라가며 표시하고, 표시되지 않은 것을 회수한다. 교과서적인 방식이고 오랫동안 잘 동작했다.

문제는 메모리 접근 패턴이다. 객체를 하나씩 따라가면 힙 여기저기를 무작위로 건드리게 된다. 현대 CPU에서 이건 최악의 접근 패턴이다. 캐시가 계속 빗나가고, 그때마다 메모리에서 읽어오느라 기다린다. 계산량이 아니라 대기 시간이 병목이 된다.

Green Tea는 이 지점을 바꿨다. 객체 중심이 아니라 메모리 블록 중심으로 간다. 8KiB 페이지를 작업 큐에 올려두고, 한 페이지 안의 여러 객체를 순차적으로 훑는다. 같은 페이지를 연달아 읽으므로 캐시에 들어온 데이터를 최대한 쓴다.

여기에 더해 최신 amd64 플랫폼(인텔 아이스레이크, AMD Zen 4 이후)에서는 벡터 명령을 써서 작은 객체를 스캔한다. 이 부분에서 약 10%가 더 나온다고 보고됐다.

이름이 왜 Green Tea인지는 설계 문서를 읽어야 알겠지만, 요점은 분명하다. 알고리즘의 계산 복잡도를 줄인 게 아니라 하드웨어에 맞게 데이터 접근 순서를 바꾼 것이다.

두 방식의 차이를 그림으로 보면 왜 빨라지는지가 분명하다.

10~40%라는 범위를 읽는 법

숫자를 볼 때 범위가 넓으면 조건을 봐야 한다. 10~40%는 "GC를 많이 쓰는 실제 프로그램"에서의 GC 오버헤드 감소폭이다.

여기서 두 가지를 구분해야 한다. GC 오버헤드가 줄어드는 것과 전체 처리량이 그만큼 늘어나는 것은 다르다. 프로그램 전체 시간에서 GC가 차지하는 비중이 5%였다면, 그중 30%가 줄어도 전체로는 1.5%다. 반대로 GC가 20%를 차지하던 프로그램이라면 체감이 크다.

즉 이득의 크기는 내 프로그램이 GC를 얼마나 쓰느냐에 비례한다. 작은 객체를 대량으로 만들고 버리는 코드, 요청마다 구조체를 잔뜩 할당하는 API 서버, 파싱과 변환이 많은 데이터 파이프라인이 여기 해당한다. 반대로 할당을 거의 안 하는 계산 중심 코드라면 차이가 안 보인다.

지연 시간 관점에서는 이야기가 조금 다르다. GC 일시 정지가 줄면 꼬리 지연(p99, p999)이 개선된다. 평균 응답 시간은 그대로인데 가장 느린 요청들이 빨라지는 식이다. SLO를 꼬리 지연으로 잡고 있는 서비스라면 이쪽이 더 중요하다.

1.26에서 개선된 항목들을 폭으로 비교하면 이렇다. GC는 범위의 중간값을 썼다.

GC 항목이 10~40%의 범위를 가진다는 점을 기억해야 한다. 내 프로그램이 어디에 놓이는지는 직접 재봐야 안다.

확인은 벤치마크가 아니라 내 서비스에서 해야 한다

릴리스 노트의 숫자를 그대로 기대하지 말고 직접 재는 게 맞다. Go는 이걸 위한 도구가 잘 갖춰져 있다.

GODEBUG=gctrace=1을 켜고 돌리면 GC가 돌 때마다 한 줄씩 로그가 나온다. 사이클 시간, 일시 정지 시간, 힙 크기가 찍힌다. 1.25와 1.26에서 같은 워크로드를 돌려 이 로그를 비교하면 차이가 바로 보인다.

runtime/metrics 패키지로 GC 관련 지표를 프로그램 안에서 수집할 수도 있다. 프로메테우스 같은 곳으로 내보내고 있다면 배포 전후 그래프를 겹쳐 보는 것이 가장 확실하다.

GOGC와 GOMEMLIMIT 설정도 이 기회에 다시 볼 만하다. GC가 빨라지면 기존에 잡아둔 값이 더 이상 최적이 아닐 수 있다. 메모리를 여유 있게 주고 GC 횟수를 줄이는 식으로 튜닝해 둔 서비스라면, 설정을 원래대로 되돌려도 괜찮아지는 경우가 있다.

1.26의 나머지 변화들

GC에 가려졌지만 다른 개선도 있다.

cgo 호출의 기본 오버헤드가 약 30% 줄었다. C 라이브러리를 많이 부르는 코드라면 이쪽이 더 크게 와닿을 수 있다. Go에서 cgo는 "되도록 피하라"는 조언이 따라다닐 만큼 비쌌는데, 그 비용이 내려간 것이다.

컴파일러가 슬라이스의 백킹 스토어를 스택에 할당하는 경우를 늘렸다. 힙 할당이 줄면 GC 부담도 함께 준다. 앞의 Green Tea와 방향이 같다. 쓰레기를 빨리 치우는 것과 애초에 덜 만드는 것을 동시에 한 셈이다.

할당을 줄이는 쪽이 여전히 먼저다

GC가 빨라졌다고 해서 할당을 마음껏 해도 된다는 뜻은 아니다. 가장 싼 GC는 돌지 않는 GC다.

Go에서 할당을 줄이는 방법은 몇 가지가 정해져 있다. 슬라이스를 미리 make([]T, 0, n)으로 용량을 잡아두면 재할당이 사라진다. 반복문 안에서 문자열을 +로 이어붙이는 대신 strings.Builder를 쓴다. 같은 크기의 버퍼를 반복해서 쓰면 sync.Pool에 넣어 재사용한다.

어디서 할당이 일어나는지는 컴파일러가 알려준다.

go build -gcflags='-m' ./... 2>&1 | grep 'escapes to heap'

이 출력이 "이 변수가 스택에 못 남고 힙으로 갔다"는 기록이다. 핫 패스에 있는 항목부터 보면 된다. 1.26에서 슬라이스 백킹 스토어를 스택에 두는 경우가 늘었으므로, 이전 버전에서 힙으로 갔던 것 중 일부는 이제 스택에 남는다. 같은 코드로 다시 돌려보면 목록이 줄어 있을 수 있다.

순서로 정리하면 이렇다. 할당을 줄이고, 그다음에 GC를 튜닝하고, 마지막으로 런타임 개선을 얻는다. Green Tea는 세 번째에 해당한다. 첫 번째를 건너뛰고 세 번째만 기대하면 효과가 작다.

Go의 릴리스 방식에서 배울 점

나는 이번 릴리스에서 기술보다 방식이 인상적이었다. Green Tea는 여러 버전에 걸쳐 실험 플래그 뒤에서 개발됐고, 충분히 검증된 뒤에 기본값이 됐다. 사용자가 코드를 고칠 필요는 없다. 올리면 그냥 빨라진다.

이게 당연해 보이지만 당연하지 않다. 많은 언어와 프레임워크가 성능 개선을 새 API와 함께 내놓는다. 그러면 이득을 보려면 코드를 고쳐야 하고, 결국 대부분의 사용자는 이득을 못 본다.

반대 의견도 가능하다. 런타임이 알아서 처리하는 방식은 세밀한 제어를 원하는 사용자에게 답답하다. Go는 GC 튜닝 노브가 GOGC와 GOMEMLIMIT 정도로 의도적으로 적은데, JVM처럼 수십 개의 플래그로 조율하고 싶은 사람에게는 부족하다.

그래도 나는 Go 쪽 선택이 옳다고 본다. 노브가 적으면 대부분의 사용자가 기본값으로 좋은 성능을 얻는다. 튜닝할 수 있다는 것은 튜닝해야 한다는 뜻이기도 하고, 실제로 제대로 튜닝하는 팀은 소수다. 기본값을 좋게 만드는 데 노력을 쏟는 쪽이 전체 이득이 크다.

다른 언어의 GC 와 견줘 보면

Go의 선택이 어떤 위치인지는 다른 런타임과 비교하면 잘 드러난다.

JVM은 정반대 방향이다. G1, ZGC, Shenandoah 등 여러 수집기를 제공하고 각각 수십 개의 플래그로 조율한다. 잘 튜닝하면 Go보다 낮은 일시 정지를 얻을 수 있지만, 그 튜닝을 할 줄 아는 사람이 팀에 있어야 한다.

.NET은 중간이다. 워크스테이션과 서버 모드를 나누고 몇 가지 스위치를 제공한다.

Go는 노브를 GOGC와 GOMEMLIMIT 둘로 좁혔다. GOGC는 힙이 얼마나 커지면 GC를 돌릴지를 비율로 정하고, GOMEMLIMIT는 메모리 상한을 준다. 컨테이너 환경에서는 GOMEMLIMIT를 컨테이너 메모리 한도의 80% 정도로 잡아두는 것이 흔한 권장인데, 이걸 안 하면 GC가 여유를 오판해서 OOM으로 죽는 일이 생긴다. 노브가 적어도 알아야 할 것은 있다는 뜻이다.

참고 자료

  • Go 1.26 is released — The Go Blog — 릴리스 일자와 주요 변경 요약
  • Go 1.26 Release Notes — Green Tea GC 기본값 전환, cgo 오버헤드 감소, 컴파일러 개선의 공식 기술
  • Go 1.26 unleashes performance-boosting Green Tea GC — InfoWorld — 설계 배경과 성능 수치에 대한 외부 정리
728x90
반응형

'IT' 카테고리의 다른 글

자바 버전 지금 뭘 써야 하나, LTS와 Valhalla  (0) 2026.10.03
Node.js 26의 Temporal, Date를 대체할까  (0) 2026.10.02
Python 3.15와 GIL, 무엇이 실제로 바뀌나  (0) 2026.09.30
TypeScript 7 출시, Go 컴파일러로 10배 빨라졌다  (0) 2026.09.29
Rust 근황, 리눅스 커널이 실험을 끝냈다  (0) 2026.09.28
'IT' 카테고리의 다른 글
  • 자바 버전 지금 뭘 써야 하나, LTS와 Valhalla
  • Node.js 26의 Temporal, Date를 대체할까
  • Python 3.15와 GIL, 무엇이 실제로 바뀌나
  • TypeScript 7 출시, Go 컴파일러로 10배 빨라졌다
밍글링글링
밍글링글링
mingling - 밍글링, 밍글밍글링. 코드와 어우러지다. IT/ 프로그래밍/소스
    반응형
    250x250
  • 밍글링글링
    mingling
    밍글링글링
  • 전체
    오늘
    어제
    • 밍글링글링 (451) N
      • Flutter (2)
      • 일상생활 (8)
        • 리뷰 (1)
        • 생활정보 (4)
        • 맛집 (0)
        • 여행 (0)
        • 모든정보 (3)
      • JAVA (126)
        • 개념 (6)
        • 예제 (115)
        • Exception (2)
      • C (1)
        • C (1)
        • C++ (0)
        • C# (0)
      • JS (29)
        • JavaScript (18)
        • JQuery (5)
        • AJax (0)
        • NODE.JS (6)
        • Angular.JS 2.0 (0)
      • WEB (87)
        • HTML (6)
        • CSS (61)
        • JSP (20)
        • JSTL (0)
      • FrameWork (8)
        • Spring (8)
        • BootStrap (0)
        • MyBATIS (0)
        • JUnit (0)
      • 외부 라이브러리 (5)
      • 공유 소스 관리 (5)
        • Git (5)
        • SVN (0)
      • 빅데이터 프로그래밍 (37)
        • Python (37)
        • R Programming (0)
      • DB (7)
        • ORACLE (0)
        • MySql (6)
      • Development Tools (7)
        • StarUML (0)
        • eXERD (0)
        • Eclipse (4)
      • SKILL (6)
        • Migration (0)
        • Security (6)
      • MicroSoft (0)
        • Excel (0)
        • Word (0)
      • Android (0)
      • Server (21)
        • Ubuntu (5)
        • Linux (15)
      • IOS (0)
      • XML (0)
      • 미디어 (0)
      • 공지사항 (3)
      • NETWORK (1)
      • 게임 (4)
        • 피파 (1)
        • 리니지M (0)
        • 배틀그라운드 (1)
        • 듀랑고 (2)
      • 세상 이슈 (6)
      • 일렉트론 (0)
      • 대회 소식 (4)
      • 업무 (2)
      • Express, Vue (6)
      • docker (11)
      • svelte (3)
      • 블록체인 (1)
      • IT (54) N
      • Rust (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 미디어로그
    • 위치로그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    css table
    css float
    rust linux
    AI 반도체
    nginx
    클론코딩
    자바 exception
    자바 배열
    vue 설치
    ubuntu
    프런트엔드
    servlet class
    nginx ssl 적용
    에디터 팁
    자바 객체 지향
    React Compiler
    SSL 인증서
    러스트
    java casting
    Java Array
    spring java
    Extension Bisect
    제미나이
    css perspective
    gitlab 설치
    ssl 인증서 발급
    자바 생성자
    svelte
    proxy pass
    티스토리 자동화
    자바 for문
    Rust lang
    VS Code 팁
    Node
    브라우저 자동화
    vscode
    nginx ssl 설정
    jsp parameter
    vue cli
    jsp include
    lang rust
    css transition
    mysql db
    AI 코딩 에이전트
    자바 클래스
    오류
    docker
    css tb
    API 설계
    리눅스 설치
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
밍글링글링
Go 1.26 Green Tea GC, 무엇이 빨라졌나
상단으로

티스토리툴바