core/filtermaps: simplified matcher

This commit is contained in:
Zsolt Felfoldi 2025-03-14 10:13:38 +01:00
parent 8b3aa452cf
commit 8f2f37da67

View file

@ -550,24 +550,18 @@ type matchSequence struct {
// newInstance creates a new instance of matchSequence.
func (m *matchSequence) newInstance(mapIndices []uint32) matcherInstance {
// determine set of indices to request from next matcher
nextIndices := make([]uint32, 0, len(mapIndices)*3/2)
needMatched := make(map[uint32]struct{})
baseRequested := make(map[uint32]struct{})
nextRequested := make(map[uint32]struct{})
for _, mapIndex := range mapIndices {
needMatched[mapIndex] = struct{}{}
baseRequested[mapIndex] = struct{}{}
if _, ok := nextRequested[mapIndex]; !ok {
nextIndices = append(nextIndices, mapIndex)
nextRequested[mapIndex] = struct{}{}
}
nextIndices = append(nextIndices, mapIndex+1)
nextRequested[mapIndex+1] = struct{}{}
nextRequested[mapIndex] = struct{}{}
}
return &matchSequenceInstance{
matchSequence: m,
baseInstance: m.base.newInstance(mapIndices),
nextInstance: m.next.newInstance(nextIndices),
nextInstance: m.next.newInstance(mapIndices),
needMatched: needMatched,
baseRequested: baseRequested,
nextRequested: nextRequested,
@ -687,12 +681,9 @@ func (m *matchSequenceInstance) getMatchesForLayer(ctx context.Context, layerInd
if _, ok := m.nextRequested[mapIndex]; ok {
continue
}
if _, ok := m.nextRequested[mapIndex+1]; ok {
continue
}
matchedResults = append(matchedResults, matcherResult{
mapIndex: mapIndex,
matches: m.params.matchResults(mapIndex, m.offset, m.baseResults[mapIndex], m.nextResults[mapIndex], m.nextResults[mapIndex+1]),
matches: m.params.matchResults(mapIndex, m.offset, m.baseResults[mapIndex], m.nextResults[mapIndex]),
})
delete(m.needMatched, mapIndex)
}
@ -715,9 +706,6 @@ func (m *matchSequenceInstance) dropIndices(dropIndices []uint32) {
if m.dropNext(mapIndex) {
dropNext = append(dropNext, mapIndex)
}
if m.dropNext(mapIndex + 1) {
dropNext = append(dropNext, mapIndex+1)
}
}
m.nextInstance.dropIndices(dropNext)
}
@ -743,9 +731,6 @@ func (m *matchSequenceInstance) evalBase(ctx context.Context, layerIndex uint32)
if m.dropNext(r.mapIndex) {
dropIndices = append(dropIndices, r.mapIndex)
}
if m.dropNext(r.mapIndex + 1) {
dropIndices = append(dropIndices, r.mapIndex+1)
}
}
if len(dropIndices) > 0 {
m.nextInstance.dropIndices(dropIndices)
@ -771,9 +756,6 @@ func (m *matchSequenceInstance) evalNext(ctx context.Context, layerIndex uint32)
}
m.mergeNextStats(stats)
for _, r := range results {
if r.mapIndex > 0 && m.dropBase(r.mapIndex-1) {
dropIndices = append(dropIndices, r.mapIndex-1)
}
if m.dropBase(r.mapIndex) {
dropIndices = append(dropIndices, r.mapIndex)
}
@ -792,12 +774,7 @@ func (m *matchSequenceInstance) dropBase(mapIndex uint32) bool {
return false
}
if _, ok := m.needMatched[mapIndex]; ok {
if next := m.nextResults[mapIndex]; next == nil ||
(len(next) > 0 && next[len(next)-1] >= (uint64(mapIndex)<<m.params.logValuesPerMap)+m.offset) {
return false
}
if nextNext := m.nextResults[mapIndex+1]; nextNext == nil ||
(len(nextNext) > 0 && nextNext[0] < (uint64(mapIndex+1)<<m.params.logValuesPerMap)+m.offset) {
if next := m.nextResults[mapIndex]; next == nil || len(next) > 0 {
return false
}
}
@ -812,15 +789,8 @@ func (m *matchSequenceInstance) dropNext(mapIndex uint32) bool {
if _, ok := m.nextRequested[mapIndex]; !ok {
return false
}
if _, ok := m.needMatched[mapIndex-1]; ok {
if prevBase := m.baseResults[mapIndex-1]; prevBase == nil ||
(len(prevBase) > 0 && prevBase[len(prevBase)-1]+m.offset >= (uint64(mapIndex)<<m.params.logValuesPerMap)) {
return false
}
}
if _, ok := m.needMatched[mapIndex]; ok {
if base := m.baseResults[mapIndex]; base == nil ||
(len(base) > 0 && base[0]+m.offset < (uint64(mapIndex+1)<<m.params.logValuesPerMap)) {
if base := m.baseResults[mapIndex]; base == nil || len(base) > 0 {
return false
}
}
@ -833,59 +803,39 @@ func (m *matchSequenceInstance) dropNext(mapIndex uint32) bool {
// results at mapIndex and mapIndex+1. Note that acquiring nextNextRes may be
// skipped and it can be substituted with an empty list if baseRes has no potential
// matches that could be sequence matched with anything that could be in nextNextRes.
func (params *Params) matchResults(mapIndex uint32, offset uint64, baseRes, nextRes, nextNextRes potentialMatches) potentialMatches {
func (params *Params) matchResults(mapIndex uint32, offset uint64, baseRes, nextRes potentialMatches) potentialMatches {
if nextRes == nil || (baseRes != nil && len(baseRes) == 0) {
// if nextRes is a wild card or baseRes is empty then the sequence matcher
// result equals baseRes.
return baseRes
}
if len(nextRes) > 0 {
// discard items from nextRes whose corresponding base matcher results
// with the negative offset applied would be located at mapIndex-1.
start := 0
for start < len(nextRes) && nextRes[start] < uint64(mapIndex)<<params.logValuesPerMap+offset {
start++
if baseRes == nil || (nextRes != nil && len(nextRes) == 0) {
// if baseRes is a wild card or nextRes is empty then the sequence matcher
// result is the items of nextRes with a negative offset applied.
result := make(potentialMatches, 0, len(nextRes))
min := (uint64(mapIndex) << params.logValuesPerMap) + offset
for _, v := range nextRes {
if v >= min {
result = append(result, v-offset)
}
}
nextRes = nextRes[start:]
return result
}
if len(nextNextRes) > 0 {
// discard items from nextNextRes whose corresponding base matcher results
// with the negative offset applied would still be located at mapIndex+1.
stop := 0
for stop < len(nextNextRes) && nextNextRes[stop] < uint64(mapIndex+1)<<params.logValuesPerMap+offset {
stop++
}
nextNextRes = nextNextRes[:stop]
// iterate through baseRes and nextRes in parallel and collect matching results.
maxLen := len(baseRes)
if l := len(nextRes); l < maxLen {
maxLen = l
}
maxLen := len(nextRes) + len(nextNextRes)
if maxLen == 0 {
return nextRes
}
if len(baseRes) < maxLen {
maxLen = len(baseRes)
}
// iterate through baseRes, nextRes and nextNextRes and collect matching results.
matchedRes := make(potentialMatches, 0, maxLen)
for _, nextRes := range []potentialMatches{nextRes, nextNextRes} {
if baseRes != nil {
for len(nextRes) > 0 && len(baseRes) > 0 {
if nextRes[0] > baseRes[0]+offset {
baseRes = baseRes[1:]
} else if nextRes[0] < baseRes[0]+offset {
nextRes = nextRes[1:]
} else {
matchedRes = append(matchedRes, baseRes[0])
baseRes = baseRes[1:]
nextRes = nextRes[1:]
}
}
for len(nextRes) > 0 && len(baseRes) > 0 {
if nextRes[0] > baseRes[0]+offset {
baseRes = baseRes[1:]
} else if nextRes[0] < baseRes[0]+offset {
nextRes = nextRes[1:]
} else {
// baseRes is a wild card so just return next matcher results with
// negative offset.
for len(nextRes) > 0 {
matchedRes = append(matchedRes, nextRes[0]-offset)
nextRes = nextRes[1:]
}
matchedRes = append(matchedRes, baseRes[0])
baseRes = baseRes[1:]
nextRes = nextRes[1:]
}
}
return matchedRes