Datadog, Go 바이너리 크기 77% 감축 성공!

by DD
3개월 전
조회수 12

Datadog는 Go 바이너리 크기 증가 문제를 해결하기 위해 의존성 분석(Dependency Auditing), 링커 최적화(Linker Optimization), 그리고 코드 리팩토링(Code Refactoring)을 진행함.

불필요한 의존성 제거를 위해 빌드 태그(Build Tags)패키지 분리(Package Isolation) 전략을 활용하여 바이너리 크기를 대폭 줄임.

리플렉션(Reflection) 사용으로 인한 링커 최적화 비활성화 문제를 해결하기 위해, whydeadcode 툴을 활용하여 문제점을 파악하고 패치를 적용함.

Datadog의 노력은 Kubernetes를 포함한 다른 Go 프로젝트에도 영향을 미쳐, 커뮤니티 전반의 바이너리 크기 감소에 기여함.

의존성 분석 및 제거를 통한 바이너리 크기 감축

Datadog는 Go 바이너리 크기 증가의 주요 원인으로 불필요한 의존성을 지목하고, 이를 해결하기 위해 체계적인 분석을 수행했다. go listgoda 툴을 활용하여 바이너리에 포함된 패키지를 식별하고, 빌드 태그(Build Tags)를 사용하여 조건부로 의존성을 포함하거나, 패키지 분리(Package Isolation)를 통해 필요한 경우에만 의존성을 가져오도록 코드를 구조화했다. 이러한 노력으로 인해, trace-agent 바이너리에서 570개의 패키지를 제거하고 36MB의 크기를 줄이는 성과를 거두었다.

리플렉션(Reflection) 사용으로 인한 링커 최적화 문제 해결

Datadog는 리플렉션(Reflection) 패키지 사용으로 인해 링커의 데드 코드 제거(Dead Code Elimination) 최적화가 비활성화되는 문제를 발견했다. whydeadcode 툴을 사용하여 문제의 근본 원인을 파악하고, text/template 및 html/template 패키지 등에서 리플렉션 사용을 수정하는 패치를 적용했다. 이러한 노력은 평균 20%의 바이너리 크기 감소를 가져왔으며, Kubernetes 프로젝트에도 영향을 미쳐 커뮤니티 전체의 성능 향상에 기여했다.

플러그인(Plugin) 사용으로 인한 링커 동작의 차이점

amd64 아키텍처에서 플러그인 패키지(plugin package)를 import하면 링커가 동적으로 링크된 바이너리로 취급하여 데드 코드 제거(Dead Code Elimination) 최적화를 비활성화하는 문제를 발견했다. Datadog는 goda를 사용하여 의존성 그래프를 분석하고, containerd 패키지에서 플러그인 import를 제거하는 빌드 태그를 추가하는 방식으로 문제를 해결했다. 이로 인해 Linux amd64 바이너리에서 245MB의 크기를 추가적으로 줄이는 성과를 거두었다.

커뮤니티의 반응 및 파급 효과

레딧(Reddit) 댓글에서는 리플렉션(Reflection), text/template, html/template 패키지로 인한 데드 코드 제거 비활성화가 Go 바이너리 크기 증가의 주요 원인 중 하나이며, 많은 프로젝트에서 이 문제를 겪고 있다는 점을 지적했다. Datadog, Uber 등에서 이 문제를 해결하기 위해 노력하고 있으며, 커뮤니티 기여(Community Contribution)를 통해 해결책을 공유하고 있다는 점을 강조했다. 특히, datadog-lambda-go 패키지에서 발생하는 문제에 대한 언급도 있었다.

Reducing the size of Go binaries by up to 77%