[loki] Grafana Loki: Range Aggregation 성능 최적화와 메모리 할당 감소
PR 링크: grafana/loki#21924 상태: Merged | 변경: +227 / -27
들어가며
Grafana Loki의 엔진은 시계열 데이터를 처리할 때 다양한 윈도우 집계(Range Aggregation) 전략을 사용합니다. 특히 step < range인 'overlapping' 윈도우 시나리오에서, 기존 구현은 매번 새로운 슬라이스를 생성하고 반복문을 통해 데이터를 탐색하는 과정에서 과도한 메모리 할당(Allocation)이 발생하고 있었습니다. 이번 PR은 이러한 비효율을 개선하여 메모리 사용량을 획기적으로 줄이고 처리 속도를 개선했습니다.
코드 분석
1. pkg/engine/internal/executor/range_aggregation.go
핵심 변경 사항은 createOverlappingMatcher 함수 내의 윈도우 매칭 로직입니다. 기존에는 sort.Search를 사용하고, 매칭되는 윈도우를 찾기 위해 매번 append를 호출하여 새로운 슬라이스를 할당했습니다.
Before:
firstOOBIndex := sort.Search(len(windows), func(i int) bool {
return t.Compare(windows[i].start) <= 0
})
// ...
var result []window
for _, window := range slices.Backward(windows[:windowIndex+1]) {
if t.Compare(window.start) > 0 && t.Compare(window.end) <= 0 {
result = append(result, window)
}
}
After:
firstOOBIndex, _ := slices.BinarySearchFunc(windows, t, cmpWindowStartTime)
// ...
prefix := windows[:windowIndex+1]
low, _ := slices.BinarySearchFunc(prefix, t, cmpWindowEndTime)
return windows[low : windowIndex+1]
새로운 구현은 slices.BinarySearchFunc를 사용하여 이진 탐색을 수행하고, 새로운 슬라이스를 할당하는 대신 기존 windows 배열의 일부분을 가리키는 슬라이스(View)를 반환합니다. 이는 메모리 할당을 제로(Zero)에 가깝게 줄여줍니다.
2. pkg/engine/internal/executor/pipeline_utils.go
테스트와 벤치마크를 위해 BufferedPipeline에 Reset() 메서드가 추가되었습니다. 이는 파이프라인의 상태를 초기화하여 동일한 데이터를 반복적으로 처리할 수 있게 합니다.
func (p *BufferedPipeline) Reset() {
p.current = -1
}
왜 이게 좋은가
이번 최적화의 핵심은 '데이터 복사 대신 슬라이스 뷰(View) 활용'과 '불필요한 클로저 할당 제거'입니다.
- 성능 수치: 벤치마크 결과, overlapping 시나리오에서
sec/op가 약 39% 향상되었으며,B/op(바이트 할당)는 무려 99% 감소했습니다.allocs/op역시 49,468에서 304로 극적으로 줄어들었습니다. - 교훈:
sort.Search와 같은 함수는 매번 클로저를 생성할 수 있으므로, 성능이 중요한 핫패스(Hot path)에서는slices.BinarySearchFunc와 같은 최신 표준 라이브러리 함수를 활용하는 것이 좋습니다.- 슬라이스를 새로 생성하여 반환하기보다는, 원본 배열의 범위를 슬라이싱하여 반환하는 것이 메모리 효율 측면에서 훨씬 유리합니다.
리뷰 피드백
PR 리뷰 과정에서 벤치마크 코드 내의 매직 넘버에 대한 지적이 있었으며, 이는 불필요한 코드를 제거하는 방향으로 깔끔하게 정리되었습니다. 기술적인 의사결정 과정에서 벤치마크를 통한 정량적 검증이 얼마나 중요한지 잘 보여주는 사례입니다.
참고 자료
⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.
관련 포스트
PR Analysis 의 다른글
- 이전글 [vllm] vLLM Qwen3.5 GDN 최적화: `einops.rearrange`를 `torch.flatten`으로 교체하여 20배 성능 향상!
- 현재글 : [loki] Grafana Loki: Range Aggregation 성능 최적화와 메모리 할당 감소
- 다음글 [cpython] CPython 성능 최적화: 임시 리스트를 튜플로 변환할 때의 '아이템 스틸' 기법
댓글