diff --git a/server/filestore.go b/server/filestore.go index a6b97b6f62b..f2e8242aadb 100644 --- a/server/filestore.go +++ b/server/filestore.go @@ -6429,7 +6429,10 @@ func (fs *fileStore) LoadNextMsg(filter string, wc bool, start uint64, sm *Store // Nothing found in this block. We missed, if first block (bi) check psim. // Similar to above if start <= first seq. // TODO(dlc) - For v2 track these by filter subject since they will represent filtered consumers. - if i == bi { + // We should not do this at all if we are already on the last block. + // Also if we are a wildcard do not check if large subject space. + const wcMaxSizeToCheck = 64 * 1024 + if i == bi && i < len(fs.blks)-1 && (!wc || fs.psim.Size() < wcMaxSizeToCheck) { nbi, lbi := fs.checkSkipFirstBlock(filter, wc) // Nothing available. if nbi < 0 || lbi <= bi { diff --git a/server/filestore_test.go b/server/filestore_test.go index b7adb8d77de..fa3b92df91a 100644 --- a/server/filestore_test.go +++ b/server/filestore_test.go @@ -7528,6 +7528,37 @@ func Benchmark_FileStoreLoadNextMsgVerySparseMsgsInBetweenWithWildcard(b *testin } } +func Benchmark_FileStoreLoadNextManySubjectsWithWildcardNearLastBlock(b *testing.B) { + fs, err := newFileStore( + FileStoreConfig{StoreDir: b.TempDir()}, + StreamConfig{Name: "zzz", Subjects: []string{"foo.*.*"}, Storage: FileStorage}) + require_NoError(b, err) + defer fs.Stop() + + // Small om purpose. + msg := []byte("ok") + + // Make first msg one that would match as well. + fs.StoreMsg("foo.1.baz", nil, msg) + // Add in a bunch of msgs. + // We need to make sure we have a range of subjects that could kick in a linear scan. + for i := 0; i < 1_000_000; i++ { + subj := fmt.Sprintf("foo.%d.bar", rand.Intn(100_000)+2) + fs.StoreMsg(subj, nil, msg) + } + // Make last msg one that would match as well. + fs.StoreMsg("foo.1.baz", nil, msg) + + b.ResetTimer() + + var smv StoreMsg + for i := 0; i < b.N; i++ { + // Make sure not first seq. + _, _, err := fs.LoadNextMsg("foo.*.baz", true, 999_990, &smv) + require_NoError(b, err) + } +} + func Benchmark_FileStoreLoadNextMsgVerySparseMsgsLargeTail(b *testing.B) { fs, err := newFileStore( FileStoreConfig{StoreDir: b.TempDir()},