[Loki] 페이지 빌더 메모리 사전 할당 제거로 희소 컬럼 메모리 효율 개선
PR 링크: grafana/loki#20043 상태: Merged | 변경: +8 / -1
들어가며
Grafana Loki의 데이터 오브젝트에서 각 컬럼마다 하나의 pageBuilder가 생성됩니다. 기존에는 각 빌더가 생성 시점에 PageSizeHint 크기(예: 256KB)만큼의 버퍼를 미리 할당했습니다. 구조화된 메타데이터처럼 대부분의 컬럼이 희소하게(sparsely) 채워지는 데이터셋에서는, 수십 개의 컬럼 빌더가 각각 256KB를 잡아먹어 상당한 메모리 오버헤드가 발생했습니다.
핵심 코드 분석
사전 할당 제거
Before:
func newPageBuilder(opts BuilderOptions) (*pageBuilder, error) {
var (
presenceBuffer = bytes.NewBuffer(nil)
valuesBuffer = bytes.NewBuffer(make([]byte, 0, opts.PageSizeHint))
// ...
)
After:
func newPageBuilder(opts BuilderOptions) (*pageBuilder, error) {
var (
// We avoid giving an initial capacity to the buffers below to reduce
// the memory footprint for page builders (one per column), since it's
// atypical for every column to completely fill its pages.
//
// However, this will slightly increase the memory footprint for any
// column with at least one full page, due to how Go grows slices.
presenceBuffer = bytes.NewBuffer(nil)
valuesBuffer = bytes.NewBuffer(nil)
// ...
)
왜 이게 좋은가
- 희소 컬럼 메모리 절약: 100개의 컬럼 중 10개만 실제로 사용되는 경우, 사전 할당이 없으면 90개의 빈 컬럼이 거의 메모리를 차지하지 않습니다.
- 트레이드오프 명시: 풀 페이지를 가진 컬럼은 Go의 슬라이스 성장 전략(2의 거듭제곱) 때문에 약간 더 많은 메모리를 사용하지만, 전체적으로는 이득입니다.
- 구조화된 메타데이터에 최적화: Loki의 구조화된 메타데이터는 대부분의 컬럼이 부분적으로만 채워지므로, 이 변경의 효과가 극대화됩니다.
- 간결한 변경: 한 줄의 코드 변경(
make([]byte, 0, opts.PageSizeHint)->nil)으로 의미 있는 메모리 절약을 달성했습니다.
참고 자료
관련 포스트
PR Analysis 의 다른글
- 이전글 [pydantic-ai] anthropic_cache_messages 설정 추가 및 캐시 포인트 자동 제한
- 현재글 : [Loki] 페이지 빌더 메모리 사전 할당 제거로 희소 컬럼 메모리 효율 개선
- 다음글 [Feast] 시간 윈도우 집계를 위한 타일링(Tiling) 지원 구현
댓글