기타 Lobsters · 2일 전

Go 1.28 신기능 적용해보니 유휴 연결 메모리가 40% 증발한 이유

핵심 요약
  • Go 1.28 개발 코드에 유휴 HTTP/2 연결의 고루틴을 종료시켰다 필요할 때 다시 띄우는 '파킹(Parking)' 기능이 추가되었습니다.
  • 5,000개의 유휴 연결 벤치마크 결과 고루틴 5,000개가 줄어들며 프로세스 RSS 메모리가 약 40%(최대 92MiB) 절감되었습니다.
  • 스택 메모리 점유가 99MiB에서 21MiB로 급감해 유휴 연결이 많은 대규모 서버 환경에서 실질적인 리소스 이점이 확인되었습니다.
요약 Go 언어의 차기 버전인 Go 1.28 개발 빌드에서 HTTP/2 서버의 고루틴(goroutine) 관리 방식이 대폭 개선되는 이른바 'HTTP/2 파킹(Parking)' 기능이 도입되었습니다. 기존 Go 서버에서는 HTTP/2 연결이 열려 있을 때 활성 스트림이 없더라도 `serveLoop`를 담당하는 고루틴이 종료되지 않고 대기 상태로 남아 메모리를 점유했습니다. 반면 새로 추가된 파킹 메커니즘은 처리할 작업이 없고 안전 조건이 충족되면 해당 고루틴을 완전히 종료시키고, 새로운 작업이 들어올 때 새 고루틴이 이어받도록 동작합니다. 한 개발자가 이 변화가 수천 개의 유휴(Idle) 연결 환경에서 실제 메모리를 얼마나 아껴주는지 직접 벤치마크를 수행했습니다. 동일한 리눅스 머신에서 Go 1.27.2, 그리고 Go 1.28 개발 빌드에서 파킹을 켠 상태와 `GODEBUG=http2serveparking=0` 플래그로 파킹을 끈 상태를 비교 측정했습니다. 측정 결과 5,000개의 유휴 연결 상태에서 파킹 기능을 활성화했을 때 프로세스 실사용 메모리(RSS)가 218~223MiB 수준에서 약 129~133MiB로 급감했습니다. 약 85~92MiB(약 39~41%)의 메모리가 절감된 것입니다. 고루틴 개수 역시 10,007개에서 5,007개로 정확히 5,000개 줄어들었으며, 고루틴 스택 메모리(StackInuse) 또한 약 99MiB에서 21MiB로 약 78MiB 감소한 것이 확인되었습니다. 반면 힙 할당량(HeapAlloc)은 실행 회차에 따라 다소 불규칙한 양상을 보여, 이번 개선의 핵심 효과는 유휴 고루틴 및 스택 메모리 회수에서 비롯된 것으로 분석되었습니다.
Sponsored · 광고