[Loki] Plain 디코더 벤치마크 추가 및 코드 개선
PR 링크: grafana/loki#20423 상태: Merged | 변경: +101 / -26
들어가며
성능 최적화의 첫 번째 단계는 측정입니다. Loki의 dataobj 모듈에서 bitmap, delta, RLE 디코더에는 벤치마크가 있었지만, plain bytes 디코더에는 없었습니다. 이 PR은 다양한 시나리오와 배치 크기에 대한 체계적인 벤치마크를 추가합니다.
핵심 코드 분석
불필요한 빈 슬라이스 체크 제거 및 에러 처리 개선
Before (value_encoding_plain.go):
func (dec *plainBytesDecoder) Decode(s []Value) (int, error) {
if len(s) == 0 {
return 0, nil
}
var err error
for i := range s {
err = dec.decode(&s[i])
if errors.Is(err, io.EOF) {
// ...
After:
func (dec *plainBytesDecoder) Decode(s []Value) (int, error) {
for i := range s {
err := dec.decode(&s[i])
if err != nil && errors.Is(err, io.EOF) {
// ...
두 가지 개선이 있습니다:
len(s) == 0체크 제거: 빈 슬라이스에서는for range가 자연스럽게 0회 실행됩니다err != nil선행 체크 추가:errors.Is는 리플렉션을 사용하므로, nil인 경우 불필요한 비용을 방지합니다
체계적인 벤치마크 설계
scenarios := []scenario{
{
name: "constant-size", // 모든 값이 100바이트
makeValues: func() []Value { /* ... */ },
},
{
name: "variable-size", // 16~1024바이트 랜덤
makeValues: func() []Value { /* ... */ },
},
}
batchSizes := []int{1024, 2048, 4096, 8192}
벤치마크 결과 (Apple M1 Max):
| 시나리오 | Batch 1024 | Batch 8192 |
|---|---|---|
| constant-size | 306μs (6.0 GiB/s) | 308μs (6.0 GiB/s) |
| variable-size | 116μs (15.9 GiB/s) | 120μs (15.5 GiB/s) |
왜 이게 좋은가
- 배치 크기에 따른 성능 변화를 측정하여 최적 배치 크기를 결정할 수 있는 데이터를 제공합니다
b.SetBytes()와rows/s커스텀 메트릭으로 처리량을 직관적으로 파악할 수 있습니다b.Loop()패턴으로 Go 최신 벤치마크 모범 사례를 따릅니다- constant-size vs variable-size 시나리오 구분으로 데이터 특성에 따른 성능 차이를 확인할 수 있습니다
- 배치 크기가 커져도 성능이 거의 일정한 것은 디코더가 메모리 효율적으로 구현되었음을 보여줍니다
참고 자료
관련 포스트
PR Analysis 의 다른글
- 이전글 [Grafana Loki] pkg/dataobj를 위한 실험적 arena 스타일 메모리 패키지 도입
- 현재글 : [Loki] Plain 디코더 벤치마크 추가 및 코드 개선
- 다음글 [Triton] Proton에서 선택적 커널 메타데이터 기록 및 커스텀 메트릭 지원
댓글