본문으로 건너뛰기

[Loki] memory 서브패키지 통합으로 코드 구조 개선

PR 링크: grafana/loki#20469 상태: Merged | 변경: +295 / -441

들어가며

Loki의 메모리 관련 패키지가 memory, memory/bitmap, memory/buffer로 분산되어 있어 stuttering 패턴(예: memory.Memory, bitmap.Bitmap)이 발생하고, allocator에서 순환 의존성을 피하기 위해 bitmap의 경량 복제본을 별도로 유지해야 했다. 이 PR은 서브패키지들을 memory 패키지로 통합하여 이 문제를 해결한다.

핵심 코드 분석

이름 변경: stuttering 제거

// Before
memory.Memory  -> memory.Region
memory/bitmap.Bitmap -> memory.Bitmap
memory/buffer.Buffer -> memory.Buffer (MakeBuffer 함수로 생성)

Allocator에서 통합된 Bitmap 사용

type Allocator struct {
    regions []*Region
    free    Bitmap  // 이전: bitmap (경량 복제본)
    empty   Bitmap
}

func (alloc *Allocator) Allocate(size int) *Region {
    for i := range alloc.free.IterValues(true) {
        region := alloc.regions[i]
        if region != nil && cap(region.data) >= size {
            alloc.free.Set(i, false)
            return region
        }
    }
    region := &Region{data: allocBytes(size)}
    alloc.addRegion(region, false)
    return region
}

Buffer 생성 함수 변경

// Before
valuesBuf := buffer.WithCapacity[int64](alloc, count)

// After
valuesBuf := memory.MakeBuffer[int64](alloc, count)

새로운 Bitmap 구현

통합된 Bitmap은 Apache Arrow의 LSB 비트 순서와 호환되며, 더 풍부한 API를 제공한다:

type Bitmap struct {
    alloc *Allocator
    data  []uint8
    len   int
}

func (bmap *Bitmap) Append(value bool) {
    if bmap.needGrow(1) {
        bmap.Grow(1)
    }
    bmap.AppendUnsafe(value)
}

func (bmap *Bitmap) AppendUnsafe(value bool) {
    bitutil.SetBitTo(bmap.data, bmap.len, value)
    bmap.len++
}

왜 이게 좋은가

  1. 중복 코드 제거: allocator의 경량 bitmap 복제본을 제거하고 실제 Bitmap 구현을 직접 사용한다.
  2. Go 네이밍 관례: memory.Memory 같은 stuttering을 memory.Region으로 개선하여 Go 코드 컨벤션을 따른다.
  3. 순 삭제 146줄: 295줄 추가에 441줄 삭제로, 전체적으로 코드가 줄었다.
  4. Arrow 호환성: 새 Bitmap은 Apache Arrow의 bitutil을 활용하여 LSB 비트 순서 호환성을 보장한다.

참고 자료

댓글

관련 포스트

PR Analysis 의 다른글