[Loki] Bitmap 디코더 최적화: 처리량 93.5% 개선
PR 링크: grafana/loki#20467 상태: Merged | 변경: +269 / -379
들어가며
Loki의 dataobj 모듈에서 페이지 리더는 값의 존재 여부(presence)를 비트맵으로 관리합니다. 기존 구현은 범용 []Value 슬라이스에 uint64 값으로 0/1을 저장했는데, 실제로 이 인코딩은 presence bitmap에만 사용되므로 boolean 전용으로 특수화할 수 있었습니다.
핵심 코드 분석
페이지 리더의 presence 버퍼를 Bitmap으로 교체
Before (page_reader.go):
type pageReader struct {
presenceBuf []Value // uint64 값 0 또는 1을 Value 래퍼로 저장
// ...
}
// presence 값을 하나씩 순회하며 타입 체크
for _, p := range pr.presenceBuf[:count] {
if p.Type() != datasetmd.PHYSICAL_TYPE_UINT64 {
return n, fmt.Errorf("unexpected presence type: %s", p.Type())
}
if p.Uint64() == 1 {
presentCount++
}
}
After:
type pageReader struct {
presenceBuf memory.Bitmap // 비트 단위로 packed
// ...
}
// 비트 단위로 직접 접근
for i := range count {
if pr.presenceBuf.Get(i) {
presentCount++
}
}
디코더를 boolean 전용으로 특수화
Before:
type bitmapDecoder struct {
r streamio.Reader
runValue uint64
setWidth int // 비트 너비 (범용)
set []byte // 가변 크기 set
}
After:
type bitmapDecoder struct {
data []byte // 직접 바이트 슬라이스 참조
off int // 바이트 오프셋
runValue bool // bool로 단순화
set byte // 1바이트에 8개 값 (LSB-first)
}
왜 이게 좋은가
벤치마크 결과가 극적입니다:
| 시나리오 | 개선율 |
|---|---|
| RLE, batch 256 | -95.63% (265μs → 11.6μs) |
| RLE, batch 1024 | -98.80% (244μs → 2.9μs) |
| RLE, batch 4096 | -99.67% (249μs → 0.8μs) |
| Mixed, batch 256 | -64.39% |
| Mixed, batch 4096 | -65.48% |
| 기하평균 | -93.50% |
[]Value대신memory.Bitmap을 사용하여 메모리 사용량이 8배 이상 줄어들었습니다 (값당 24+ bytes → 1 bit)streamio.Reader인터페이스 대신 직접 바이트 슬라이스를 참조하여 함수 호출 오버헤드가 제거되었습니다- boolean 전용이므로 비트 너비 계산, 타입 체크 등 범용 로직이 모두 제거되었습니다
참고 자료
관련 포스트
PR Analysis 의 다른글
- 이전글 [vllm] Draft Model 기반 Speculative Decoding 지원
- 현재글 : [Loki] Bitmap 디코더 최적화: 처리량 93.5% 개선
- 다음글 [Grafana Loki] dataobj pageReader의 메모리 할당을 Reclaim과 Bitmap 직접 전달로 최적화
댓글