성능 최적화

28 개의 포스트

discord3분 읽기큐레이션 요약

디스코드 업데이트:

2024년 Discord는 음성·채팅 이용 경험을 개선하기 위해 모바일 앱 안정성, 렌더링 속도, 서버 전환, GIF 검색, API 지연 시간 등을 집중적으로 최적화했다. iOS 충돌률은 84% 감소했고, 모바일 서버 전환 속도는 30% 이상 빨라졌으며, API 지연 시간은 약 25% 줄었다. 이 글은 이러한 연간 개선 사항을 연말 시 형식으로 정리한 회고다. ## iOS 안정성과 저장 공간 개선 - 장기간 발생하던 iOS 충돌 문제를 식별하고 계측·수정해 전체 충돌률을 **84% 감소**시켰다. - iOS 데이터 저장 방식을 개선해 기기 내 디스크 사용량을 줄였다. - 영향을 많이 받은 사용자 중 일부는 최대 **4GB의 저장 공간을 회복**했다. ## Android 채팅 및 콘텐츠 렌더링 최적화 - Android 채팅 렌더러를 개선해 기기별로 느린 프레임을 최대 **60% 감소**시켰다. - 채팅 목록의 메모리 사용량도 약 **12% 줄이는 효과**를 측정했다. - 이모지, GIF, 스티커가 포함된 Expression Picker를 최적화해 Android에서 렌더링 프레임 드롭 빈도를 최대 **50% 감소**시켰다. - 관련 테스트에서 메모리 사용량은 약 **7.5% 감소**했다. ## 폴더블 기기와 모바일 화면 대응 - 다양한 화면 비율과 형태를 가진 모바일 기기에 맞춰 앱 레이아웃 적응성을 강화했다. - 폴더블 기기에서 멀티태스킹과 화면 전환 경험을 크게 개선했다. - 작은 화면부터 접히는 대형 화면까지 Discord UI가 더 자연스럽게 동작하도록 지원 범위를 넓혔다. ## 서버 탐색과 전환 속도 향상 - 모바일 서버 목록에 **가상화(virtualization)** 를 적용했다. - 현재 화면에 보이는 서버만 로드해 대규모 서버 목록을 스크롤할 때 성능과 메모리 효율을 개선했다. - 모바일에서 서버 전환 속도를 기기와 네트워크 환경에 따라 **30% 이상 향상**시켰다. ## GIF와 미디어 공유 성능 개선 - 모바일 GIF Picker의 로딩 시간을 최대 **80% 단축**했다. - GIF 검색과 게시 과정이 더 빠르고 부드럽게 동작하도록 최적화했다. - 이미지 변환 과정에서 **ICC 색상 프로필 데이터**를 보존하도록 미디어 프록시를 개선했다. - WebP로 변환된 이미지에서도 원본에 가까운 색상과 품질을 유지할 수 있게 됐다. ## API 및 백엔드 인프라 개선 - Google Cloud의 **GCE C3 인스턴스**로 이전하고 nginx 계층을 제거하는 등 인프라를 변경했다. - 그 결과 p90 이상 구간의 API 지연 시간이 약 **25% 감소**했다. - API를 사용하는 Discord 앱과 Activities의 응답성이 전반적으로 향상됐다. ## 연말 프로모션 - 글의 마지막에는 Nitro 선물 기능을 홍보하며, 선물을 보낸 사용자에게 Avatar Decoration을 제공한다고 안내한다. - 연말 개선 사항은 새로운 대규모 기능보다는 충돌, 지연, 메모리, 저장 공간처럼 일상적인 사용성을 좌우하는 문제를 줄이는 데 초점이 맞춰져 있다. Discord의 2024년 업데이트는 눈에 띄는 기능 추가보다 성능과 안정성 개선에 집중한 사례다. 특히 모바일 사용자는 앱 업데이트를 유지하고, 저장 공간이 부족하거나 채팅·GIF 로딩이 느렸던 경우 개선 효과를 확인해볼 만하다.

원문 읽기(새 탭에서 열림)
discord원문

디스코드 업데이트: (새 탭에서 열림)

디스코드(Discord)는 2024년 9월 업데이트를 통해 플랫폼 내 앱 생태계를 대폭 확장하고 사용자 보안을 한층 강화했습니다. 앱 런처(App Launcher)의 도입으로 대화 중 게임이나 영상 공유가 더욱 간편해졌으며, 종단간 암호화(E2EE)와 패스키(Passkeys) 지원을 통해 통화 보안과 로그인 편의성을 동시에 잡았습니다. 이번 업데이트는 디스코드를 단순한 채팅 도구를 넘어, 개발자와 사용자가 함께 만들어가는 강력한 커뮤니케이션 플랫폼으로 진화시키는 데 중점을 두고 있습니다. ### 앱 런처를 통한 소셜 활동의 확장 * **어디서나 간편한 앱 사용:** 이제 데스크톱과 모바일 모두에서 앱 런처를 통해 수천 개의 앱을 검색하고 채팅이나 음성 채널에 즉시 불러올 수 있습니다. 마음에 드는 앱은 계정에 추가해 언제든 쉽게 다시 사용할 수 있습니다. * **신규 액티비티(Activities) 추가:** 서버 간 전투를 벌이는 'Arena Kingdoms', 체스 퍼즐을 푸는 'Echo Chess', 바이킹 테마의 PVP 게임 'Battletabs' 등 4종의 새로운 게임이 추가되어 친구들과 함께 즐길 수 있습니다. * **이미지 편집 및 애니메이션:** 채팅창의 이미지에 마우스를 올리면 앱 런처를 통해 즉석에서 편집할 수 있습니다. 예를 들어 'Viggle' 앱의 명령어를 사용하여 정지된 사진 속 인물이 춤을 추게 만드는 등의 재미있는 상호작용이 가능합니다. * **개발자 생태계 활성화:** 개발자들은 이제 자신만의 액티비티를 직접 구축하고 출시하여 수익을 창출할 수 있으며, 앱 런처의 검색 기능을 통해 전 세계 사용자에게 노출될 기회를 얻습니다. ### 보안 강화 및 프라이버시 보호 * **A/V 통화 종단간 암호화(E2EE):** 1:1 DM, 그룹 DM, 서버 음성 채널 및 Go Live 스트리밍의 음성과 영상 통화에 종단간 암호화가 도입됩니다. 이를 통해 통화 참여자 외에는 그 누구도 데이터에 접근할 수 없으며, 사용자는 통화 중에 암호화 상태를 직접 확인할 수 있습니다. * **패스키(Passkeys) 도입:** 생체 인식 기술을 활용한 패스키 로그인을 지원합니다. 이제 복잡한 비밀번호를 입력할 필요 없이 Face ID나 Touch ID 등을 통해 즉시 로그인할 수 있으며, 생체 데이터는 기기에만 저장되어 디스코드 서버에도 전송되지 않으므로 보안성이 뛰어납니다. ### 사용자 교육 및 콘텐츠 업데이트 * **디스코드 도장(Discord Dojo):** 초보자부터 숙련자까지 플랫폼을 100% 활용할 수 있도록 단축키, 메시지 서식 지정 방법 등을 담은 교육 비디오와 블로그 리소스를 제공합니다. * **스트리트 파이터 6 콜라보레이션:** 상점에서 류, 춘리, 아쿠마 등 인기 캐릭터를 테마로 한 장식과 효과를 만나볼 수 있으며, 특정 퀘스트를 완료하면 'Battle Field' 장식을 무료로 획득할 수 있습니다. * **시스템 안정성 향상:** 엔지니어링 최적화를 통해 iOS 환경에서의 앱 충돌(Crash) 발생률을 84%나 감소시키는 성과를 거두어 더욱 쾌적한 모바일 환경을 제공합니다. 이번 업데이트를 통해 디스코드는 더욱 안전하고 다채로운 즐길 거리가 가득한 공간으로 변모했습니다. 특히 보안이 중요한 사용자라면 지금 바로 패스키를 설정하고, 친구들과 함께 새로워진 앱 런처를 통해 'Arena Kingdoms'나 'Viggle' 같은 새로운 기능을 직접 체험해 보시길 권장합니다.

datadog원문

테스트 시간을 50 (새 탭에서 열림)

개발 효율성을 저해하는 길고 불안정한 CI 파이프라인 문제를 해결하기 위해, 테스트와 소스 코드 간의 의존성을 분석하여 변경된 코드와 관련된 테스트만 선택적으로 실행하는 '테스트 영향 분석(Test Impact Analysis)' 기술이 주목받고 있습니다. Datadog은 Ruby 환경에서 이를 실현하기 위해 성능 저하를 최소화하면서도 기존 도구와 호환되는 전용 라이브러리를 개발하였으며, 이는 전체 테스트 시간을 절반 수준으로 단축하는 성과를 거두었습니다. 이 과정에서 개발 팀은 Ruby 내장 모듈의 한계를 극복하기 위해 C 확장을 통한 저수준 인터프리터 이벤트 활용 방식을 채택했습니다. ## 테스트 영향 분석(TIA)의 개념과 필요성 - 소프트웨어 규모가 커짐에 따라 전체 테스트 수트 실행 시간은 비대해지며, 코드 변경과 무관한 '불안정한 테스트(Flaky tests)'로 인해 CI가 실패하는 빈도가 높아집니다. - 테스트 영향 분석은 각 테스트가 실행될 때 접근하는 소스 파일 목록을 동적으로 맵핑하여 저장하는 기술입니다. - Git 커밋 시 변경된 파일과 맵핑된 파일 목록에 교집합이 있는 테스트만 실행함으로써, 불필요한 리소스 낭비를 줄이고 파이프라인의 안정성을 높일 수 있습니다. - Datadog의 'Intelligent Test Runner'는 이러한 원리를 바탕으로 정확성, 성능, 사용자 투명성을 핵심 가치로 설계되었습니다. ## 기존 Ruby 솔루션의 성능 한계 - **내장 Coverage 모듈:** Ruby 3.1에서 추가된 resume/suspend 메서드를 통해 테스트별 커버리지를 측정할 수 있으나, `simplecov`와 같은 기존 도구와 충돌하며 약 300% 수준의 매우 높은 성능 오버헤드가 발생합니다. - **TracePoint API:** 코드 실행 시 이벤트를 구독하는 표준 API로 구현이 용이하고 호환성도 뛰어나지만, 순수 코드 실행 위주의 벤치마크(RuboCop 등)에서 200~400%의 오버헤드를 기록하여 실무 적용이 어렵습니다. - 이러한 기존 방식들은 대규모 테스트 수트를 빠르게 실행하려는 원래의 목적에 부합하지 않는 성능 결과(기존보다 3~4배 느려짐)를 보였습니다. ## C 확장을 이용한 저수준 인터프리터 이벤트 활용 - 성능 문제를 해결하기 위해 Ruby VM의 내부 동작을 분석하고, C 언어로 직접 커버리지 수집 도구를 개발했습니다. - Ruby 인터프리터 내부에서 사용하는 `rb_thread_add_event_hook` 함수를 활용해 `RUBY_EVENT_LINE` 이벤트를 직접 훅(hook)하는 방식을 취했습니다. - 테스트 시작(start)과 종료(stop) 시점에만 이벤트 훅을 등록 및 해제하며, 실행되는 파일의 경로가 프로젝트 루트 내에 있는지 C 수준에서 빠르게 필터링하여 해시 구조에 저장합니다. - 이 방식은 Ruby 레벨의 추상화 단계를 건너뛰고 VM 이벤트에 직접 접근함으로써, 데이터 수집의 정확성을 유지하면서도 실행 오버헤드를 획기적으로 낮추는 기반이 되었습니다. Ruby 기반의 대규모 프로젝트를 운영 중이라면 매번 전체 테스트를 실행하기보다, 변경 사항에 기반한 지능형 테스트 실행 방식을 도입하여 CI 비용과 시간을 최적화할 것을 권장합니다. 특히 성능에 민감한 환경에서는 표준 API에 의존하기보다 저수준 최적화가 포함된 전문적인 모니터링 도구를 활용하는 것이 효과적입니다.

datadog원문

테스트 시간을 50% 단축하는 Ruby 라이브러리를 만든 방법 (새 탭에서 열림)

소프트웨어 프로젝트의 규모가 커짐에 따라 발생하는 길고 불안정한 CI 파이프라인은 개발 생산성을 저해하는 주요 원인입니다. 데이터독(Datadog)은 코드 변경 사항과 관련된 테스트만 선택적으로 실행하는 '테스트 영향 분석(Test Impact Analysis)' 기술을 통해 이 문제를 해결하고자 했으며, 성능 오버헤드를 최소화한 Ruby용 Intelligent Test Runner를 구축했습니다. 이를 위해 기존 도구들의 한계를 넘어 Ruby VM 인터프리터 이벤트를 직접 활용하는 C 익스텐션을 개발함으로써 테스트 시간을 절반으로 단축하는 성과를 거두었습니다. **테스트 영향 분석의 개념과 필요성** * CI 파이프라인의 병렬 실행은 속도를 높일 수 있지만, 클라우드 컴퓨팅 비용이 증가하고 관련 없는 코드의 결함으로 인한 테스트 실패(Flaky tests) 문제를 해결하지 못합니다. * 테스트 영향 분석은 각 테스트와 해당 테스트가 실행하는 소스 파일 간의 매핑 정보를 동적으로 생성하여 관리합니다. * Git 커밋에서 변경된 파일과 특정 테스트가 의존하는 파일 목록이 겹칠 때만 해당 테스트를 실행하고, 관련이 없는 경우 건너뜁니다. * 이 시스템은 정확성(필요한 테스트를 거르지 않음), 성능(매 커밋마다 실행 가능할 정도로 낮은 오버헤드), 투명성(사용자 코드 수정 없음)이라는 세 가지 핵심 요구사항을 충족해야 합니다. **기존 Ruby 솔루션의 한계** * **내장 Coverage 모듈:** Ruby 3.1에서 추가된 테스트별 커버리지 수집 기능은 `SimpleCov`와 같은 기존 커버리지 도구와 호환되지 않으며, 성능 오버헤드가 약 300%에 달해 테스트 속도가 4배나 느려지는 단점이 있습니다. * **TracePoint API:** VM 이벤트를 구독하는 `TracePoint` 방식은 사용이 간편하고 기존 도구와 충돌하지 않지만, 여전히 200~400% 수준의 높은 성능 저하를 유발하여 실제 개발 환경에 적용하기 어렵습니다. **Ruby VM 이벤트를 활용한 맞춤형 C 익스텐션** * 성능 최적화를 위해 Ruby 소스 코드의 `coverage.c`와 `thread.c`를 분석하여, C 언어 수준에서 직접 인터프리터 이벤트를 가로채는 방식을 채택했습니다. * Ruby의 C API인 `rb_add_event_hook2`를 사용하여 `RUBY_EVENT_LINE` 이벤트를 등록함으로써, 코드가 실행되는 시점에 즉각적으로 파일 정보를 수집하도록 설계했습니다. * `dd_cov_update_line_coverage`와 같은 콜백 함수 내에서 실행 중인 파일이 프로젝트 루트 내에 있는지 확인하는 필터링 로직을 구현하여 데이터 수집의 효율성을 높였습니다. * 이 접근 방식은 Ruby 인터프리터 내부 메커니즘을 직접 활용함으로써 성능 오버헤드를 획기적으로 낮추고, 대규모 테스트 수트에서도 무리 없이 작동합니다. 규모가 큰 Ruby 프로젝트에서 테스트 속도 정체와 CI 비용 증가 문제를 겪고 있다면, 전체 테스트를 매번 실행하는 대신 테스트 영향 분석 도구를 도입하여 파이프라인의 효율성을 극대화할 것을 권장합니다. 특히 성능이 중요한 환경이라면 Ruby 내장 도구에만 의존하기보다 VM 이벤트를 직접 제어하는 방식이 유효한 해결책이 될 수 있습니다.

figma3분 읽기큐레이션 요약

파일 로드 속도 개선:

Figma는 파일 전체를 한꺼번에 불러오는 대신 사용자가 현재 보고 있는 페이지만 동적으로 로드해 파일 로딩 속도를 개선했다. 파일이 커져도 실제 사용자가 접근하는 콘텐츠의 복잡도에 비례해 로드하도록 설계한 결과, 가장 느린 5%의 페이지 로드 시간이 33% 감소했다. 핵심 과제는 페이지 간 컴포넌트·스타일·변수 참조 같은 의존성을 정확히 추적하면서 필요한 데이터만 전송하는 것이었다. ## 사용자 체감 복잡도에 맞춘 로딩 - Figma 파일은 여러 페이지, 컴포넌트, 라이브러리, 프로토타입 화면을 포함해 매우 커질 수 있다. - 하지만 사용자는 한 세션에서 파일의 모든 페이지를 탐색하지 않는 경우가 많다. - 따라서 파일 크기 전체가 아니라 현재 열어 본 페이지의 복잡도에 따라 로딩 시간이 결정되어야 한다. - 선택한 페이지만 먼저 표시하고, 다른 페이지는 사용자가 접근할 때 불러오면 초기 로딩 시간과 메모리 사용량을 줄일 수 있다. - Figma는 파일이 계속 커지더라도 로딩 성능은 지속적으로 개선되는 것을 목표로 삼았다. ## 페이지 간 읽기 의존성 - Figma 파일은 각 레이어와 속성을 가진 노드들의 트리 구조로 구성된다. - 노드는 다른 페이지에 있는 노드를 참조할 수 있으며, 이를 **읽기 의존성(read dependency)**이라고 부른다. - 예를 들어 인스턴스는 다른 페이지에 있는 원본 컴포넌트를 가리키므로, 올바르게 렌더링하려면 해당 컴포넌트 노드도 먼저 받아야 한다. - 스타일 역시 내부적으로 노드로 구현된다. - 특정 프레임이 `BrandPrimary` 색상 스타일을 사용하면 해당 스타일 노드를 로드해야 실제 색상값을 해석할 수 있다. - 변수도 같은 방식으로 동작한다. - 텍스트 크기에 `text-subheader` 변수를 적용했다면, 클라이언트는 변수 노드를 조회해 실제 값인 `16` 같은 원시 값을 확인해야 한다. - 따라서 단순히 현재 페이지만 로드해서는 부족하며, 렌더링에 필요한 다른 페이지의 참조 데이터까지 함께 찾아야 한다. ## QueryGraph 기반 동적 로딩 - Figma는 읽기 의존성을 메모리 내 그래프로 관리하는 **QueryGraph**를 구축했다. - QueryGraph는 의존 노드 간 연결을 추적하고, Figma의 멀티플레이어 시스템이 클라이언트에 어떤 데이터를 전송할지 결정하는 기반이 됐다. - 이 구조는 기존에 보기 전용 파일과 프로토타입의 동적 로딩을 구현하는 데 활용됐다. - 동적으로 불러오는 단위는 콘텐츠 유형에 따라 달라진다. - **Figma 캔버스:** 선택한 페이지를 먼저 로드하고, 추가 페이지는 필요할 때 요청한다. - **프로토타입 뷰어:** 한 번에 하나의 프레임을 표시하고, 사용자가 이동할 가능성이 있는 인접 프레임을 미리 로드한다. - 페이지를 로드할 때는 해당 페이지 자체뿐 아니라 다른 페이지에 존재하는 필수 컴포넌트·스타일·변수 노드도 QueryGraph를 통해 함께 전송한다. ## 동적 로딩의 효과 - 모든 페이지와 노드를 초기화하는 방식보다 불필요한 데이터 전송을 줄일 수 있다. - 사용자가 실제로 접근하지 않는 페이지를 메모리에 올리지 않아 메모리 사용량도 감소한다. - 큰 파일이라도 현재 작업 중인 페이지가 단순하다면 빠르게 캔버스를 표시할 수 있다. - 가장 느린 5%의 페이지 로드 시간이 33% 줄어드는 성과를 거뒀다. ## 실용적인 시사점 대규모 웹 애플리케이션에서는 전체 데이터를 일괄 로드하기보다 사용자의 현재 화면과 실제 접근 경로를 기준으로 로딩 단위를 정하는 것이 효과적이다. 다만 페이지 단위 지연 로딩을 적용할 때는 컴포넌트, 스타일, 변수처럼 화면 밖에 존재하는 참조 데이터까지 의존성 그래프로 추적해야 하며, 필요한 의존성만 정확히 함께 로드하는 설계가 중요하다.

원문 읽기(새 탭에서 열림)
datadog원문

.NET 연속 프로파일러: 메모리 사용량 (새 탭에서 열림)

Datadog의 .NET 프로파일러는 가비지 컬렉션(GC)의 효율성과 메모리 할당 패턴을 분석하여 애플리케이션의 성능 병목 현상을 진단합니다. 이 시스템은 모든 할당을 추적하는 대신 `AllocationTick` 이벤트를 활용한 샘플링 방식을 채택하여 운영 환경에서의 오버헤드를 최소화하면서도 정밀한 데이터를 제공합니다. 특히 .NET 7의 최신 API를 통해 객체의 생존 주기를 추적함으로써, CPU 부하의 원인이 되는 과도한 GC 작업과 잠재적인 메모리 누수 지점을 정확히 찾아내는 데 결론적인 도움을 줍니다. ### 가비지 컬렉터가 CPU에 미치는 영향 측정 * **전용 스레드 모니터링**: 서버 GC 설정 시 CLR이 생성하는 코어당 전용 스레드(.NET Server GC 및 .NET BGC)의 CPU 소비량을 운영체제로부터 직접 수집합니다. * **Pull 모델 채택**: GC 발생 시마다 이벤트를 받는 Push 방식과 달리, 프로파일러가 1분마다 주기적으로 GC 스레드의 CPU 사용 통계를 가져와 'Garbage Collector'라는 단일 프레임을 가진 네이티브 콜 스택 샘플로 기록합니다. * **버전별 차이**: .NET 5 이상에서는 GC 스레드 식별이 가능하여 정확한 측정이 가능하지만, 이전 버전에서는 스레드 ID 정보 부족으로 인해 이 기능을 완벽히 지원하기 어렵습니다. ### AllocationTick을 활용한 효율적인 할당 추적 * **샘플링 기반 추적**: 모든 객체 할당을 기록하는 `ObjectAllocated` 방식은 성능 저하가 극심하므로, 약 100KB의 할당이 누적될 때마다 발생하는 `AllocationTick` 이벤트를 사용하여 데이터를 수집합니다. * **상세 정보 수집**: 이벤트 페이로드에서 클래스 ID(ClassID), 타입 이름, 메모리 주소, 객체 크기뿐만 아니라 해당 객체가 할당된 힙의 종류(SOH, LOH, POH)까지 식별합니다. * **동기적 콜 스택 캡처**: 해당 이벤트는 할당을 수행한 스레드에서 동기적으로 발생하므로, 즉시 콜 스택을 워킹(Stack Walking)하여 어떤 비즈니스 로직이 메모리 압박을 유발하는지 특정할 수 있습니다. ### Weak Handle을 이용한 생존 객체 및 누수 탐지 * **객체 이동 대응**: GC의 컴팩션(Compaction) 단계에서 객체 주소가 변경되는 문제를 해결하기 위해, 샘플링된 객체에 대해 Weak 핸들을 생성하여 관리합니다. * **ICorProfilerInfo13 활용**: .NET 7에서 추가된 이 프로파일링 API를 통해, GC 이후에도 핸들이 가리키는 객체가 여전히 메모리에 살아있는지(`IsAllocated`)를 확인합니다. * **생명 주기 분석**: GC가 끝날 때마다 참조되지 않는 객체의 핸들은 제거하고, 생존한 객체들은 다음 프로필에 포함시켜 어떤 데이터가 메모리에 오래 머무르며 누수를 유발하는지 추적합니다. 운영 환경에서 메모리 문제를 분석할 때는 단순한 할당량 확인을 넘어, GC로 인한 CPU 점유율과 객체의 생존 기간을 함께 살펴야 합니다. 특히 .NET 7 이상의 최신 런타임을 활용하면 프로파일러의 Weak 핸들 추적 기능을 통해 메모리 누수 탐지의 정확도를 대폭 높일 수 있습니다.

microsoft원문

Copy-on-Write 성능 및 디 (새 탭에서 열림)

Windows 11의 Dev Drive와 Copy-on-Write(CoW) 링크 기능은 대규모 코드베이스의 빌드 성능을 최대 43%까지 향상시키며, 특히 프로젝트 간 종속성이 깊은 C# 환경에서 탁월한 효율을 발휘합니다. 이 기술은 파일 데이터를 물리적으로 복제하는 대신 동일한 디스크 블록을 참조하는 방식을 통해 I/O 부하를 획기적으로 줄이며, Windows Server 2025 및 Windows 11 24H2에 기본 기능으로 탑재될 예정입니다. 개발자는 전용 도구를 통해 CoW 링크 상태를 모니터링하고 참조 누수를 관리함으로써 최적의 개발 성능을 유지할 수 있습니다. **레포지토리 빌드 성능 테스트 결과** - **C# 및 마이크로서비스 이점:** 프로젝트 간 종속성이 깊어 어셈블리 복사가 빈번한 C# 프로젝트나, 빌드 출력 시 대규모 마이크로서비스 레이아웃을 구성하는 환경에서 최소 10%에서 최대 43%의 빌드 시간 단축 효과가 확인되었습니다. - **언어별 차이:** C++ 프로젝트는 상대적으로 적은 수의 대용량 파일을 생성하고 복사 빈도가 낮아 C#에 비해 성능 향상 폭이 적었으나, 파일 복사 과정이 포함된 경우에는 여전히 이득을 보였습니다. - **병렬성 영향:** 빌드 초기 단계의 병렬 처리는 빨라지지만, 마지막 단계에서 거대 프로젝트들이 선형적으로 빌드되는 구조의 레포지토리는 전체 빌드 시간 단축 효과가 희석될 수 있습니다. **CoW 링크 및 블록 클론 식별 방법** - **참조 상태 확인:** `fsutil file queryExtentsAndRefCounts` 명령어를 사용하여 특정 파일이 CoW 링크인지, 즉 블록 클론(Block Clone) 상태인지 확인할 수 있습니다. - **Ref 카운트의 의미:** 출력 결과 중 `Ref: 0x4`와 같은 값은 해당 디스크 볼륨 내에서 4개의 파일 엔트리가 동일한 물리적 데이터 블록을 공유하고 있음을 나타냅니다. - **메타데이터 관리:** 각 클론된 파일은 참조 추적을 위해 최소 하나 이상의 클러스터를 별도로 사용하여 메타데이터를 관리합니다. **분석 도구(ProcMon, Xperf) 사용을 위한 필터 설정** - **필터 드라이버 허용:** Dev Drive는 보안과 성능을 위해 필터 드라이버 연결을 제한하므로, `fsutil devdrv setfiltersallowed` 명령을 통해 분석 도구 전용 필터를 허용 목록에 추가해야 합니다. - **Xperf 사용 시 주의사항:** 성능 측정을 위해 `FileInfo` 필터를 허용한 경우, 측정이 끝난 후에는 반드시 목록에서 제거하고 드라이브를 재마운트해야 합니다. 이를 방치하면 드라이브 성능이 지속적으로 저하될 수 있습니다. - **상시 허용:** ProcMon 필터와 같은 도구는 실제 분석 도구가 실행 중일 때만 부하를 주므로, 필요에 따라 허용 목록에 상시 유지해도 무방합니다. **참조 누수(Leaked References) 탐지 및 복구** - **클론 한계치:** Dev Drive의 기반인 ReFS는 데이터 블록당 최대 8,176개의 클론을 허용하며, 이를 초과할 경우 복사 오류(`STATUS_BLOCK_TOO_MANY_REFERENCES`)가 발생할 수 있습니다. - **관리 도구 활용:** 장기간 빌드를 반복하여 고립된 참조나 누수가 의심될 경우, 관리자 권한으로 `refsutil leak <드라이브명> /s` 명령을 실행하여 누수된 클러스터를 스캔하고 복구할 수 있습니다. - **사전 감지:** `/d` 파라미터를 사용하면 실제 수정 없이 누수 여부만 미리 파악할 수 있어 시스템 안정성을 점검하는 데 용이합니다. **실용적인 결론 및 제언** 대규모 프로젝트를 운영하는 팀은 Dev Drive 도입 시 NuGet 패키지 캐시를 소스 코드와 동일한 파티션에 배치하여 CoW 이득을 극대화해야 합니다. 또한, 빌드 성능 분석을 위해 필터 드라이버 설정을 변경했다면 성능 유지를 위해 분석 완료 후 불필요한 필터를 반드시 정리하는 습관이 필요합니다.

datadog원문

Datadog의 데이터 시각화를 iOS에 구현한 방법: 성능 최적화에 집중하며 (새 탭에서 열림)

Datadog은 복잡한 데이터 시각화를 iOS 모바일 앱에 네이티브로 구현하기 위해 자체 SwiftUI 기반 그래프 라이브러리인 'DogGraphs'를 개발했습니다. iOS 14 호환성을 유지해야 하는 제약 속에서 성능 병목을 해결하기 위해 SwiftUI의 렌더링 파이프라인과 디핑(Diffing) 메커니즘을 심도 있게 분석하고 최적화했습니다. 그 결과, 다양한 제품군에서 빠르고 유연하게 동작하며 컴파일 타임에 타입 안정성까지 보장하는 선언형 그래프 프레임워크를 구축할 수 있었습니다. ### DogGraphs 개발 배경과 도전 과제 * **자체 라이브러리 필요성**: 개발 당시 Swift Charts 같은 공식 라이브러리가 없었으며, Datadog 특유의 복잡한 데이터 시각화 요구사항을 충족하기 위해 직접 개발을 결정했습니다. * **하위 호환성 제약**: iOS 14를 지원해야 했기에 성능 최적화에 유리한 최신 `Canvas` API를 사용할 수 없었고, 표준 SwiftUI 뷰 계층 구조만으로 고성능을 구현해야 했습니다. * **선언형 API 설계**: Swift의 Result Builder를 활용해 SwiftUI와 유사한 구문으로 복잡한 그래프를 정의할 수 있게 했으며, 서로 다른 유형의 그래프를 잘못 쌓는 등의 실수를 컴파일 타임에 방지하도록 설계했습니다. ### 성능 분석 및 프로파일링 도구 활용 * **_printChanges() 활용**: 뷰의 `body` 내에서 이 비공개 API를 호출하여 어떤 상태 변화가 불필요한 재렌더링을 유발하는지 로그로 확인하고 디버깅했습니다. * **Xcode Instruments**: 'SwiftUI View body evaluations'를 통해 뷰의 바디가 평가되는 횟수와 평균 소요 시간을 측정했으며, 'Time profiler'로 실행 시간이 긴 함수를 찾아 최적화했습니다. * **주요 측정 시나리오**: 초기 그래프 렌더링 시점, 툴팁 선택이나 레이어 토글 같은 상호작용 발생 시, 기기 회전 및 다크/라이트 모드 전환 시의 성능을 집중적으로 점검했습니다. ### SwiftUI 핵심 개념과 디핑(Diffing) 메커니즘 * **렌더링 원리 이해**: SwiftUI의 성능 최적화를 위해 Identity(정체성), Lifetime(생명주기), Dependencies(의존성)라는 세 가지 핵심 개념을 기반으로 뷰 업데이트 방식을 분석했습니다. * **비트 단위 비교**: SwiftUI는 뷰의 필드를 비트 단위로 비교(memcmp)하여 이전 값과 차이가 없으면 `body`를 다시 계산하지 않고 건너跳는 최적화 방식을 사용합니다. * **의존성 관리**: 불필요한 의존성 전파를 막고 뷰 구조를 효율적으로 설계함으로써, 데이터 변경 시 영향을 받는 뷰만 정확히 다시 그려지도록 유도했습니다. ### 실용적인 권장 사항 복잡한 SwiftUI 애플리케이션의 성능을 높이려면 단순히 최신 기능을 사용하는 것에 그치지 말고, **뷰의 정체성(Identity)과 의존성 관계를 명확히 정의**해야 합니다. 특히 대규모 데이터를 다루는 시각화 도구에서는 SwiftUI의 내부 디핑 엔진이 효율적으로 작동할 수 있도록 뷰 모델과 프로퍼티 구조를 최적화하고, Instruments를 통해 렌더링 비용을 주기적으로 측정하는 과정이 필수적입니다.

datadog원문

fetch를 현실로 만들기: 범용 쿼리 및 렌더링 스케줄러 구축 (새 탭에서 열림)

데이터독(Datadog)은 복잡한 대시보드의 성능 최적화를 위해 쿼리와 렌더링 작업을 효율적으로 관리하는 범용 스케줄러를 개발했습니다. 기존의 복잡한 규칙 기반 시스템을 단순화하고 브라우저 네이티브 API를 활용함으로써, UI 응답성을 높이고 백엔드 부하를 안정화하는 성과를 거두었습니다. 이 글은 기존 스케줄러의 한계를 극복하고 모든 애플리케이션에 적용 가능한 유연한 스케줄링 모델로 전환한 과정을 다룹니다. ### 기존 스케줄러(v1)의 문제점 * **지나친 복잡성:** 약 20여 개의 매개변수가 얽힌 복잡한 휴리스틱(heuristics)으로 운영되어, 개발자가 시스템의 동작 방식을 예측하거나 추론하기 어려웠습니다. * **로직의 결합:** 쿼리(데이터 호출)와 렌더링(화면 표시) 스케줄링이 명확히 분리되지 않았습니다. 예를 들어, 렌더링 대기 작업이 많다는 이유로 연관 없는 쿼리 요청이 지연되는 등의 비효율이 발생했습니다. * **낮은 범용성:** 대시보드 환경에만 특화되어 설계되었기 때문에, 데이터독의 다른 제품군이나 일반적인 위젯 컴포넌트에서 재사용하기 어려운 구조적 한계가 있었습니다. ### 데이터 쿼리 스케줄링의 단순화 * **가시성 기반 우선순위:** 화면에 보이는(visible) 위젯의 쿼리는 요청 즉시 실행하고, 화면 밖(offscreen) 위젯은 별도의 대기열에 추가하여 지연 처리합니다. * **고정 시간 윈도우 알고리즘:** 복잡한 계산 대신 2,000ms라는 고정된 시간 창(window) 동안 최대 10개의 태스크만 실행하도록 제한하여 작업 분포를 평탄화했습니다. * **대기열 관리 최적화:** 백엔드에 펜딩된 요청이 너무 많으면 실행을 일시 중단하며, 화면 밖 작업들은 대기열에 들어온 순서대로 처리하여 공정성을 유지합니다. * **도입 결과:** 로직이 단순해졌음에도 불구하고 서버의 '429(Too many requests)' 에러가 크게 감소했으며, 쿼리 재시도 횟수가 줄어들어 전체적인 데이터 로딩 속도가 향상되었습니다. ### Browser Scheduling API를 활용한 렌더링 최적화 * **자원 상태 인지:** 기존 스케줄러는 브라우저의 CPU나 메모리 가용 상태를 알지 못한 채 작업을 할당했으나, 새로운 시스템은 브라우저 네이티브 기능을 활용합니다. * **우선순위 세분화:** 최신 `Browser Scheduling API`의 `postTask` 메서드를 도입하여 작업의 성격에 따라 우선순위(user-blocking, user-visible, background)를 부여합니다. * **효율적인 메인 스레드 사용:** 브라우저가 직접 작업의 우선순위를 제어하게 함으로써, 중요한 UI 업데이트는 즉시 처리하고 덜 중요한 렌더링은 브라우저가 유휴 상태일 때 실행하도록 최적화했습니다. 복잡한 웹 애플리케이션에서 성능을 확보하려면 스케줄링 로직을 최대한 단순화하고 브라우저가 제공하는 표준 API를 적극적으로 활용해야 합니다. 이는 개발자에게는 시스템에 대한 통제력을 제공하며, 사용자에게는 더 매끄러운 인터랙션 경험을 선사합니다.

datadog원문

Datadog Agent 메트릭 파이프라인의 성능 개선 (새 탭에서 열림)

Datadog Agent는 동일한 CPU 리소스로 더 많은 메트릭을 빠르게 처리하기 위해 메트릭 고유 키(Context) 생성 로직을 최적화했습니다. Go 언어의 프로파일링 도구를 통해 태그 정렬 및 해싱 과정이 시스템의 주요 병목 지점임을 확인했으며, 이를 해결하기 위해 상황별 특수화 알고리즘과 64비트 해시 최적화 기법을 도입했습니다. 이러한 개선을 통해 에이전트의 데이터 처리 성능을 한 단계 높이고 리소스 효율성을 극대화하는 결과를 얻었습니다. ### 병목 지점 식별 및 분석 * Go 언어(Golang)의 CPU 프로파일링과 플레임그래프(Flamegraph) 도구를 활용하여 메트릭 파이프라인 내 리소스 소모가 큰 지점을 추적했습니다. * 분석 결과, 메트릭을 수신하고 고유 키를 생성하는 `addSample` 및 `trackContext` 함수가 가장 많은 CPU를 점유하고 있음을 확인했습니다. * 특히 태그 중복을 제거하고 동일한 해시 값을 보장하기 위해 수행하는 태그 정렬 로직(`util.SortUniqInPlace`)이 전체 성능의 주요 장애물로 작용하고 있었습니다. ### 메트릭 컨텍스트 생성의 기술적 문제 * 고유 식별을 위해 메트릭 이름, DogStatsD 태그, 컨테이너 태그를 모두 조합하여 해시 키를 생성해야 합니다. * 해시 충돌을 방지하면서도 빠른 생성 속도를 유지해야 하며, 동일한 메트릭에 대해 항상 일관된 키를 생성하기 위해 태그 리스트를 정렬하는 과정이 필수적이었습니다. * 태그 리스트 정렬은 데이터 양이 많아질수록 비용이 급격히 증가하는 특성이 있어, 매번 메트릭이 들어올 때마다 이를 수행하는 것은 비효율적이었습니다. ### 성능 최적화를 위한 다각도 접근 * **코드 특수화(Specialization):** 모든 경우에 일반적인 정렬 알고리즘을 사용하는 대신, 태그의 개수에 따라 가장 빠른 성능을 낼 수 있는 정렬 방식을 선택적으로 적용하도록 로직을 개선했습니다. * **해시 알고리즘 및 구조 개선:** 벤치마크를 통해 속도와 고유성이 검증된 Murmur3 알고리즘을 도입했습니다. * **Go 런타임 최적화 활용:** 기존 128비트 해시를 충돌 방지에 충분한 64비트로 전환하여, Go 런타임의 최적화된 맵 접근 함수(`mapassign_fast64`, `mapaccess2_fast64`)가 동작하도록 유도함으로써 처리 속도를 가속화했습니다. 데이터 집약적인 시스템에서는 런타임 프로파일링을 통해 '핫 패스(Hot path)'를 정확히 찾아내는 것이 중요합니다. 특히 태그 정렬이나 해싱과 같은 빈번한 기본 연산에서 발생하는 미세한 오버헤드를 줄이는 것만으로도 대규모 환경에서의 전체 처리량(Throughput)을 크게 향상시킬 수 있습니다.

figma3분 읽기큐레이션 요약

Figma의 인프라: 웹

Figma는 웹 기반 디자인 도구도 데스크톱 애플리케이션 수준의 속도와 안정성을 제공해야 한다고 주장한다. 이를 위해 클라우드 기반의 단일 진실 공급원, 실시간 협업, 프로토타이핑과 개발자 핸드오프를 통합했으며, 사용자와 데이터가 증가함에 따라 인프라를 확장 가능한 구조로 전환하고 있다. 핵심 과제는 불필요한 데이터 로딩을 줄이고, 데이터베이스를 수평 확장하며, 전 세계 사용자의 지연 시간을 낮추는 것이다. ## Figma가 해결하려는 문제 - 기존 디자인 작업은 특정 데스크톱 애플리케이션과 플랫폼에 종속됐다. - 파일을 내보내거나 여러 도구 사이에서 옮기는 과정에서 최신 버전 관리와 협업이 어려웠다. - Figma는 디자인 파일을 클라우드에 저장하고 고유 URL을 부여해 팀 전체의 단일 진실 공급원으로 만든다. - 프로토타이핑과 개발자 핸드오프 기능을 제품 안에 포함해 별도 도구와 파일 변환의 필요성을 줄였다. ## 실시간 협업과 인프라 요구사항 - 여러 사용자가 하나의 파일을 동시에 보고 편집할 수 있는 멀티플레이어 기능을 제공한다. - 디자인 파일에는 복잡한 도형과 대용량 이미지가 포함될 수 있어 백엔드와 네트워크로 전송되는 데이터가 많다. - 사용자는 데스크톱 도구와 같거나 더 나은 상호작용 성능을 기대한다. - 따라서 인프라는 다음 요구사항을 동시에 충족해야 한다. - 낮은 상호작용 지연 시간 - 높은 가용성 - 대규모 파일과 동시 접속 처리 - 실시간 변경사항 동기화 ## 초기 인프라의 한계 - 초기 Figma는 단순한 백엔드 구조를 사용해 빠르게 제품을 개발하고 운영했다. - 예를 들어 파일을 로드할 때 사용자가 접근 가능한 공유 컴포넌트를 모두 미리 불러왔다. - 공유 디자인 요소가 수천 개일 때는 효과적이었지만, 조직의 라이브러리가 약 1만 개에 가까워지면 백엔드에 큰 부담이 발생했다. - Microsoft, Uber 같은 대규모 조직의 도입과 글로벌 사용자 증가로 이러한 문제가 일반적인 확장성 문제로 나타났다. ## 필요한 데이터만 불러오는 구조 - 기존 시스템은 사용자가 실제로 즉시 필요로 하지 않는 데이터까지 파일 로드 시점에 미리 가져오는 경우가 있었다. - 이 방식은 초기 진입 속도와 백엔드 부하 모두에 악영향을 준다. - 단순히 서버 성능만 개선하는 것으로는 해결되지 않으며, 클라이언트와 서버 간 상호작용 방식을 다시 설계해야 한다. - 클라이언트가 필요한 정보만 요청하도록 제품의 데이터 로딩 방식과 사용자 경험을 함께 바꿔야 한다. - 인프라 팀뿐 아니라 제품과 클라이언트 개발팀의 협업이 필요한 문제다. ## 단일 데이터베이스에서 수평 확장으로 - 당시 Figma의 전체 인프라는 AWS의 매우 강력한 단일 데이터베이스 인스턴스에 의존했다. - 단순한 구조를 선호하는 KISS 원칙 덕분에 초기에는 운영이 쉬웠고 빠르게 성장할 수 있었다. - 그러나 단일 인스턴스는 성능과 용량 확장에 한계가 있다. - 다음 단계에서는 여러 노드로 확장할 수 있는 수평 확장형 데이터베이스 계층을 구축하려 했다. - 데이터베이스를 거의 모든 시스템과 서비스가 사용하므로, 일관성·장애 처리·서비스 의존성까지 함께 재설계해야 하는 대규모 작업이다. ## 글로벌 사용자의 지연 시간 개선 - 주간 활성 사용자의 80% 이상이 미국 외 지역에 있었다. - 당시 요청은 미국 오리건의 데이터센터까지 왕복해야 했기 때문에, 사용자 경험이 물리적 네트워크 거리에 영향을 받았다. - 이를 개선하기 위해 사용자와 가까운 곳에 인프라 구성 요소를 배치하려 했다. - 첫 단계로 전 세계 주요 지역에 원격 프록시를 전략적으로 배치해 데이터센터까지의 네트워크 지연을 줄이는 방안을 추진했다. - 장기적으로는 글로벌 사용자에게 더 가까운 위치에서 요청을 처리하는 방향으로 인프라를 발전시키려 했다. ## 실용적인 결론 웹 기반 협업 도구의 확장은 서버를 더 큰 장비로 교체하는 것만으로 해결되지 않는다. 필요한 데이터만 지연 로딩하고, 데이터베이스를 수평 확장하며, 사용자가 가까운 위치에서 서비스를 이용하도록 네트워크 구조를 개선하는 등 제품 경험과 시스템 아키텍처를 함께 재설계해야 한다.

원문 읽기(새 탭에서 열림)
figma3분 읽기큐레이션 요약

파일 로딩, 드래

Figma는 디자인 도구가 사용자의 사고와 손동작을 즉시 따라가려면 성능이 핵심이라고 강조한다. 문서 렌더러 재구성, WebAssembly 최적화 등을 통해 대용량 파일 로딩과 줌·드래그 성능을 최대 3배 개선했으며, 실제 사용자 문서와 프레임 시간 지표를 기반으로 효과를 측정했다. 특히 단순한 평균 속도뿐 아니라 화면 피드백의 끊김까지 함께 줄이는 것을 목표로 삼았다. ## 성능이 창작 경험을 좌우하는 이유 - 디자인 도구의 지연은 사용자의 사고와 화면 조작 사이에 간극을 만든다. - Figma는 제품이 사용자의 창의적 사고와 신체 움직임을 자연스럽게 확장해야 한다고 본다. - 따라서 기능을 추가하는 것뿐 아니라, 실제 사용 문서에서 성능 병목을 지속적으로 찾아 개선하는 과정이 필요하다. - 이번 작업에서는 문서 렌더러 구조를 재설계하고 WebAssembly 관련 문제를 해결해 큰 폭의 성능 향상을 얻었다. ## WebAssembly와 렌더러 최적화로 파일 로딩 개선 - 대규모 조직에서는 여러 겹으로 중첩된 컴포넌트와 다양한 상태를 하나의 복잡한 문서에 담는다. - Microsoft Fluent Design 팀은 Windows 기본 컨트롤의 모든 상태와 조합을 하나의 Figma 파일에 구성해 로딩 성능의 한계를 시험했다. - 실제 대형 문서의 로딩 시간이 **29초에서 8초 이하**로 감소했다. - WebAssembly 최적화와 여러 렌더링 관련 변경 사항이 약 두 달 동안 적용됐다. - WebAssembly는 macOS·Windows의 데스크톱 앱과 Chrome, Firefox, Safari 등 주요 환경에 활성화됐다. - 결과적으로 복잡한 파일의 로딩뿐 아니라 전반적인 문서 처리 성능도 향상됐다. ## 줌과 드래그의 연속적인 상호작용 - 파일을 연 뒤에도 줌인·줌아웃과 레이어 드래그처럼 반복적으로 수행하는 작업의 반응성이 중요하다. - Figma는 화면이 순간적으로 멈추는 ‘hitch’를 줄이는 데 집중했다. - 줌 성능과 드래그 성능이 모두 최대 **3배** 개선됐다. - 이미지가 많이 포함된 복잡한 파일을 사용하는 N3TWORK는 새 렌더러 적용 후 컴포넌트 게시와 파일 로딩 속도의 변화를 즉시 체감했다. - 이 사례는 일반적인 벤치마크뿐 아니라 특정 사용자의 실제 문서와 작업 방식에 맞춘 최적화도 큰 효과를 낼 수 있음을 보여준다. ## 평균 프레임 시간과 최대 프레임 시간을 함께 측정하는 이유 - 연속적인 조작에서는 작업이 끝나는 총 시간보다 조작 중 화면이 얼마나 부드럽게 갱신되는지가 중요하다. - 같은 500ms가 걸리는 작업이라도 매 순간 화면을 보여주는 경우와 끝날 때까지 아무 피드백이 없는 경우의 체감 품질은 크게 다르다. - Figma는 직접 조작감을 중시하기 때문에 다음 두 지표를 함께 추적한다. - **평균 프레임 시간**: 전반적인 화면 갱신 속도와 부드러움을 나타낸다. - **최대 프레임 시간**: 특정 순간에 발생하는 긴 지연과 끊김을 나타낸다. - 최대 프레임 시간이 커지면 드래그 중 갑자기 멈추는 듯한 ‘걸림’이 발생한다. - 평균 프레임 시간이 커지면 화면 전체가 낮은 프레임 레이트로 동작해 지속적으로 버벅거린다. - 예를 들어 평균 프레임 레이트가 같아도 일부 프레임만 200ms 또는 367ms 지연되면 움직임이 불규칙하게 끊긴다. - 반대로 최대 지연 시간이 같더라도 긴 프레임 지연이 자주 발생하면 전체 화면이 더 심하게 끊겨 보인다. - 이상적으로는 항상 60fps 이상을 유지해야 하지만, 현실적인 개선 과정에서는 두 지표를 시간에 따라 추적하는 것이 유용하다. ## 실제 사용자 문서를 기준으로 한 성능 개선 - Figma는 인위적인 테스트 파일만이 아니라 사용자가 공유한 실제 문서를 분석해 최적화 대상을 찾았다. - 문서의 컴포넌트 중첩 수준, 비트맵 이미지 수, 디자인 시스템의 복잡도 등 현실적인 조건을 반영했다. - 사용자와 직접 문제를 진단하고 새 렌더러를 적용해 즉각적인 성능 변화를 확인하는 방식도 활용했다. - 이는 성능 최적화가 단일 벤치마크 수치를 높이는 작업이 아니라, 실제 작업 흐름에서 지연과 불연속적인 피드백을 제거하는 과정임을 보여준다. 복잡한 디자인 문서를 주로 다룬다면 파일 크기 자체보다 컴포넌트 중첩, 이미지 밀도, 렌더링 구조가 성능에 미치는 영향을 살펴보는 것이 중요하다. 성능을 평가할 때도 평균 속도만 보지 말고, 순간적인 프레임 지연과 사용자 조작 중 발생하는 끊김을 함께 측정해야 한다.

원문 읽기(새 탭에서 열림)
datadog원문

Datadog APM을 사용하여 Homebrew 성능 개선 (새 탭에서 열림)

이 글은 Datadog의 소프트웨어 엔지니어링 인턴인 Andrew Robert McBurney가 오픈 소스 프로젝트인 Homebrew의 `brew linkage` 명령어 성능을 개선한 과정을 다룹니다. Datadog의 APM 도구와 플레임 그래프를 활용해 병목 지점을 정확히 파악했으며, 캐싱 메커니즘을 도입하여 패키지 검사 속도를 획기적으로 향상시켰습니다. 결과적으로 106개 패키지 처리 시간을 11.5초에서 182밀리초로 단축하며 프로젝트의 요구 성능을 성공적으로 충족했습니다. ### APM을 활용한 성능 병목 지점 탐색 * Datadog의 `ddtrace` 젬(gem)을 사용해 Homebrew의 루비 코드를 인스트루먼테이션(instrumentation)하여 실행 데이터를 수집했습니다. * 수집된 데이터를 플레임 그래프로 시각화하여 분석한 결과, `LinkageChecker::check_dylibs` 함수가 전체 실행 시간의 대부분을 차지하는 병목 지점임을 확인했습니다. * 이 함수는 패키지의 동적 라이브러리 링크를 확인하고 이를 시스템 라이브러리, 깨진 링크, 선언되지 않은 의존성 등으로 분류하는 복잡한 작업을 수행합니다. ### 멀티스레딩의 한계와 캐싱 전략 도입 * 초기에는 루비의 `Thread` 프리미티티브를 이용한 멀티스레딩으로 성능 개선을 시도했으나, 루비의 **GIL(Global Interpreter Lock)** 제한으로 인해 기대했던 성능 향상을 얻지 못했습니다. * 대안으로 SQLite3를 이용한 온디스크(on-disk) 캐싱 메커니즘을 설계하여, 한 번 계산된 연결성 정보를 영구 저장하고 재사용하도록 했습니다. * SQLite3 기반 캐싱 도입 후, `boost` 라이브러리 검사 시간이 1.01초에서 1.38밀리초로 줄어드는 등 전체적인 명령 처리 속도가 비약적으로 개선되었습니다. ### 의존성을 고려한 PStore 기반 최종 최적화 * Homebrew 유지관리자의 피드백을 반영하여, 외부 의존성인 SQLite3 젬 대신 루비 표준 라이브러리인 **PStore**로 캐싱 구현을 교체했습니다. * PStore는 루비 객체를 파일에 영구적으로 저장하는 해시 기반의 메커니즘으로, 추가적인 외부 라이브러리 설치 없이도 SQLite3와 유사한 성능 이점을 제공합니다. * 이 과정을 통해 대규모 오픈 소스 프로젝트에서는 성능 최적화만큼이나 의존성 관리와 표준 라이브러리 활용이 중요하다는 점을 입증했습니다. ### 실용적인 결론 성능 최적화 시 직관에 의존하기보다 APM과 같은 도구를 사용하여 데이터 기반으로 병목을 찾는 것이 중요합니다. 특히 루비 환경에서는 GIL로 인해 병렬 처리가 제한적일 수 있으므로, 연산량이 많은 작업은 캐싱을 통해 중복 계산을 피하는 것이 가장 효과적인 전략이 될 수 있습니다. 또한, 오픈 소스 기여 시에는 프로젝트의 경량성을 유지하기 위해 가급적 표준 라이브러리(예: PStore)를 활용하는 것을 권장합니다.