[Loki] Thor 쿼리 엔진 메모리 최적화 Part 3: 불필요한 스키마 재생성 제거
PR 링크: grafana/loki#20530 상태: Merged | 변경: +8 / -8
들어가며
Loki의 Thor 쿼리 엔진 메모리 최적화 시리즈의 세 번째 PR입니다. 이전 Part 2에서 식별자 캐싱과 빌더 사전 예약(Reserve)을 도입한 후, 이 PR은 Arrow 스키마와 필드 배열의 불필요한 재생성을 제거합니다.
핵심 코드 분석
최적화 1: 스키마 필드 복사 대신 직접 추가
// Before: AddField로 매번 새 스키마 생성
for i := range duplicates {
sourceField := newSchema.Field(sourceFieldIdx)
// AddField는 매 호출마다 전체 스키마를 복사
newSchema, err = newSchema.AddField(len(newSchema.Fields()), ...)
}
// After: 슬라이스에 직접 추가 후 한 번에 스키마 생성
newFields := make([]arrow.Field, 0, oldSchema.NumFields()+len(duplicates))
newFields = append(newFields, oldSchema.Fields()...)
for i := range duplicates {
newFields = append(newFields, semconv.FieldFromIdent(destinationIdent, true))
}
md := oldSchema.Metadata()
newSchema := arrow.NewSchema(newFields, &md)
최적화 2: 필터에서 기존 스키마 재사용
// Before: 필터링 후 새 스키마 생성
schema := arrow.NewSchema(fields, nil)
return array.NewRecordBatch(schema, arrays, ct)
// After: 원본 배치의 스키마 재사용
return array.NewRecordBatch(batch.Schema(), arrays, ct)
필터링은 행만 제거하고 열 구조는 변경하지 않으므로, 동일한 스키마를 재사용할 수 있습니다.
왜 이게 좋은가
1. O(n²) 스키마 복사 제거
AddField를 k번 호출하면 매번 기존 필드 배열 전체를 복사하므로 O(n*k) 비용이 발생합니다. 사전 할당된 슬라이스에 append한 후 한 번에 스키마를 생성하면 O(n+k)로 줄어듭니다.
2. 불필요한 할당 제거
필터링에서 스키마가 변하지 않는 경우 새 스키마를 생성할 이유가 없습니다. 기존 스키마 참조를 재사용하면 메모리 할당이 0입니다.
3. 누적 효과
테스트 스위트 전체에서 "수 GB"의 할당을 절감한다고 기술되어 있습니다. 개별 변경은 작지만, 쿼리 실행 중 수천 번 반복되는 경로에서 효과가 누적됩니다.
참고 자료
- Apache Arrow Go: Schema — Arrow 스키마 API
- Grafana Loki PR #20473 — 메모리 최적화 Part 2
관련 포스트
PR Analysis 의 다른글
- 이전글 [Loki] Partition Ring 셔플 샤딩 캐시 크기를 설정 플래그로 추출
- 현재글 : [Loki] Thor 쿼리 엔진 메모리 최적화 Part 3: 불필요한 스키마 재생성 제거
- 다음글 [triton] CUDA 가변 인자 Pre-compiled Launcher로 커널 런치 오버헤드 제거
댓글