Skip to content

Commit 4ad6bed

Browse files
committed
Optimise firstMatching by reducing allocations
Signed-off-by: Neil Twigg <[email protected]>
1 parent 5d88269 commit 4ad6bed

File tree

1 file changed

+22
-47
lines changed

1 file changed

+22
-47
lines changed

server/filestore.go

Lines changed: 22 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2486,7 +2486,7 @@ func (mb *msgBlock) firstMatching(filter string, wc bool, start uint64, sm *Stor
24862486
mb.mu.Unlock()
24872487
}()
24882488

2489-
fseq, isAll, subs := start, filter == _EMPTY_ || filter == fwcs, []string{filter}
2489+
fseq, isAll := start, filter == _EMPTY_ || filter == fwcs
24902490

24912491
var didLoad bool
24922492
if mb.fssNotLoaded() {
@@ -2514,18 +2514,15 @@ func (mb *msgBlock) firstMatching(filter string, wc bool, start uint64, sm *Stor
25142514
}
25152515
}
25162516
// Make sure to start at mb.first.seq if fseq < mb.first.seq
2517-
if seq := atomic.LoadUint64(&mb.first.seq); seq > fseq {
2518-
fseq = seq
2519-
}
2517+
fseq = max(fseq, atomic.LoadUint64(&mb.first.seq))
25202518
lseq := atomic.LoadUint64(&mb.last.seq)
25212519

25222520
// Optionally build the isMatch for wildcard filters.
2523-
_tsa, _fsa := [32]string{}, [32]string{}
2524-
tsa, fsa := _tsa[:0], _fsa[:0]
25252521
var isMatch func(subj string) bool
25262522
// Decide to build.
25272523
if wc {
2528-
fsa = tokenizeSubjectIntoSlice(fsa[:0], filter)
2524+
_tsa, _fsa := [32]string{}, [32]string{}
2525+
tsa, fsa := _tsa[:0], tokenizeSubjectIntoSlice(_fsa[:0], filter)
25292526
isMatch = func(subj string) bool {
25302527
tsa = tokenizeSubjectIntoSlice(tsa[:0], subj)
25312528
return isSubsetMatchTokenized(tsa, fsa)
@@ -2545,29 +2542,22 @@ func (mb *msgBlock) firstMatching(filter string, wc bool, start uint64, sm *Stor
25452542

25462543
if !doLinearScan {
25472544
// If we have a wildcard match against all tracked subjects we know about.
2548-
if wc {
2549-
subs = subs[:0]
2550-
mb.fss.Match(stringToBytes(filter), func(bsubj []byte, _ *SimpleState) {
2551-
subs = append(subs, string(bsubj))
2552-
})
2553-
// Check if we matched anything
2554-
if len(subs) == 0 {
2555-
return nil, didLoad, ErrStoreMsgNotFound
2556-
}
2557-
}
25582545
fseq = lseq + 1
2559-
for _, subj := range subs {
2560-
ss, _ := mb.fss.Find(stringToBytes(subj))
2561-
if ss != nil && (ss.firstNeedsUpdate || ss.lastNeedsUpdate) {
2562-
mb.recalculateForSubj(subj, ss)
2563-
}
2564-
if ss == nil || start > ss.Last || ss.First >= fseq {
2565-
continue
2546+
if bfilter := stringToBytes(filter); wc {
2547+
mb.fss.Match(bfilter, func(bsubj []byte, ss *SimpleState) {
2548+
if ss.firstNeedsUpdate || ss.lastNeedsUpdate {
2549+
mb.recalculateForSubj(bytesToString(bsubj), ss)
2550+
}
2551+
if start <= ss.Last {
2552+
fseq = min(fseq, max(start, ss.First))
2553+
}
2554+
})
2555+
} else if ss, _ := mb.fss.Find(bfilter); ss != nil {
2556+
if ss.firstNeedsUpdate || ss.lastNeedsUpdate {
2557+
mb.recalculateForSubj(filter, ss)
25662558
}
2567-
if ss.First < start {
2568-
fseq = start
2569-
} else {
2570-
fseq = ss.First
2559+
if start <= ss.Last {
2560+
fseq = min(fseq, max(start, ss.First))
25712561
}
25722562
}
25732563
}
@@ -2576,13 +2566,6 @@ func (mb *msgBlock) firstMatching(filter string, wc bool, start uint64, sm *Stor
25762566
return nil, didLoad, ErrStoreMsgNotFound
25772567
}
25782568

2579-
// If we guess to not do a linear scan, but the above resulted in alot of subs that will
2580-
// need to be checked for every scanned message, revert.
2581-
// TODO(dlc) - we could memoize the subs across calls.
2582-
if !doLinearScan && len(subs) > int(lseq-fseq) {
2583-
doLinearScan = true
2584-
}
2585-
25862569
// Need messages loaded from here on out.
25872570
if mb.cacheNotLoaded() {
25882571
if err := mb.loadMsgsWithLock(); err != nil {
@@ -2615,18 +2598,10 @@ func (mb *msgBlock) firstMatching(filter string, wc bool, start uint64, sm *Stor
26152598
if isAll {
26162599
return fsm, expireOk, nil
26172600
}
2618-
if doLinearScan {
2619-
if wc && isMatch(sm.subj) {
2620-
return fsm, expireOk, nil
2621-
} else if !wc && fsm.subj == filter {
2622-
return fsm, expireOk, nil
2623-
}
2624-
} else {
2625-
for _, subj := range subs {
2626-
if fsm.subj == subj {
2627-
return fsm, expireOk, nil
2628-
}
2629-
}
2601+
if wc && isMatch(sm.subj) {
2602+
return fsm, expireOk, nil
2603+
} else if !wc && fsm.subj == filter {
2604+
return fsm, expireOk, nil
26302605
}
26312606
// If we are here we did not match, so put the llseq back.
26322607
mb.llseq = llseq

0 commit comments

Comments
 (0)