[Grafana Loki] 쿼리 옵티마이저를 bottom-up에서 top-down 방식으로 리팩터링하여 중복 작업 제거
PR 링크: grafana/loki#19581 상태: Merged | 변경: +691 / -722
들어가며
Grafana Loki의 물리 플랜 옵티마이저는 DAG(방향 비순환 그래프)를 순회하며 최적화 규칙을 적용합니다. 기존 구현은 bottom-up 방식으로 각 노드를 방문할 때마다 규칙의 apply 메서드를 호출했습니다. 그러나 규칙들은 내부적으로 top-down 전파를 수행하므로, 동일한 변환이 여러 번 중복 적용되거나 결과를 예측하기 어려웠습니다. 이 PR은 apply를 루트 노드에서 한 번만 호출하고, 각 규칙이 스스로 대상 노드를 수집하도록 리팩터링합니다.
핵심 코드 분석
Before: 각 노드에서 개별 규칙 적용
// apply는 DAG의 각 노드에서 호출됨
func (r *predicatePushdown) apply(node Node) bool {
switch node := node.(type) {
case *Filter:
for i := 0; i < len(node.Predicates); i++ {
if ok := r.applyPredicatePushdown(node, node.Predicates[i]); ok {
// ...
}
}
}
return false
}
After: 루트에서 시작하여 대상 노드를 수집 후 적용
// apply는 루트 노드에서만 한 번 호출됨
func (r *predicatePushdown) apply(root Node) bool {
// 대상 노드를 먼저 수집
nodes := findMatchingNodes(r.plan, root, func(node Node) bool {
_, ok := node.(*Filter)
return ok
})
changed := false
for _, n := range nodes {
filter := n.(*Filter)
for i := 0; i < len(filter.Predicates); i++ {
if !canApplyPredicate(filter.Predicates[i]) {
continue // 적용 가능 여부를 먼저 체크
}
if ok := r.applyToTargets(filter, filter.Predicates[i]); ok {
changed = true
filter.Predicates = slices.Delete(filter.Predicates, i, i+1)
i--
}
}
}
return changed
}
왜 이게 좋은가
- 중복 규칙 적용 제거: bottom-up 순회에서는 하위 노드에서 이미 적용된 규칙이 상위 노드에서 다시 적용될 수 있지만, top-down은 이를 방지한다.
- 추론 용이성: 규칙의 진입점이 루트 하나이므로, 규칙 적용 순서와 결과를 예측하기 쉬워진다.
- 관심사 분리:
canApplyPredicate체크를applyToTargets진입 전에 수행하여, 대상 탐색 로직과 적용 가능 여부 판단을 분리했다. - 새 규칙 추가 용이:
groupByPushdown,projectionPushdown등 새 규칙도 동일한findMatchingNodes+applyToTargets패턴을 따르면 된다.
참고 자료
관련 포스트
PR Analysis 의 다른글
- 이전글 [Triton] gfx1250 Shared Memory 크기 정확하게 반환하기
- 현재글 : [Grafana Loki] 쿼리 옵티마이저를 bottom-up에서 top-down 방식으로 리팩터링하여 중복 작업 제거
- 다음글 [triton] AMD: gfx1250에서 ttg.async_wait lowering 및 asynccnt 기반 동기화 구현
댓글