[WIP] JetStream: Make timestamp-based seeks O(log n) with binary search in filestore#7352
Closed
darioalessandro wants to merge 3 commits intonats-io:mainfrom
Closed
[WIP] JetStream: Make timestamp-based seeks O(log n) with binary search in filestore#7352darioalessandro wants to merge 3 commits intonats-io:mainfrom
darioalessandro wants to merge 3 commits intonats-io:mainfrom
Conversation
neilalexander
added a commit
that referenced
this pull request
Sep 26, 2025
This updates the filestore `GetSeqFromTime` function to use a binary search, such that the computational complexity is more predictable. This closes #7352 and fixes #7353 as this is a more idiomatic approach. Beforehand, the benchmark was very fast for earlier timestamps (as expected with a linear scan) but comparatively glacial for later ones: ``` go test -v ./server -run=XXX -bench=BenchmarkFileStoreGetSeqFromTime goos: darwin goarch: arm64 pkg: github.com/nats-io/nats-server/v2/server cpu: Apple M2 Ultra BenchmarkFileStoreGetSeqFromTime BenchmarkFileStoreGetSeqFromTime/Start BenchmarkFileStoreGetSeqFromTime/Start-24 18652426 61.56 ns/op 0 B/op 0 allocs/op BenchmarkFileStoreGetSeqFromTime/Middle BenchmarkFileStoreGetSeqFromTime/Middle-24 114956 10275 ns/op 2 B/op 0 allocs/op BenchmarkFileStoreGetSeqFromTime/End BenchmarkFileStoreGetSeqFromTime/End-24 60656 19740 ns/op 0 B/op 0 allocs/op PASS ok github.com/nats-io/nats-server/v2/server 11.673s ``` After the change, this is now more predictable in the entire range: ``` go test -v ./server -run=XXX -bench=BenchmarkFileStoreGetSeqFromTime goos: darwin goarch: arm64 pkg: github.com/nats-io/nats-server/v2/server cpu: Apple M2 Ultra BenchmarkFileStoreGetSeqFromTime BenchmarkFileStoreGetSeqFromTime/Start BenchmarkFileStoreGetSeqFromTime/Start-24 9555956 130.8 ns/op 0 B/op 0 allocs/op BenchmarkFileStoreGetSeqFromTime/Middle BenchmarkFileStoreGetSeqFromTime/Middle-24 9335430 127.4 ns/op 0 B/op 0 allocs/op BenchmarkFileStoreGetSeqFromTime/End BenchmarkFileStoreGetSeqFromTime/End-24 10001110 118.6 ns/op 0 B/op 0 allocs/op PASS ok github.com/nats-io/nats-server/v2/server 11.296s ``` Signed-off-by: Neil Twigg <neil@nats.io>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Improves timestamp-based message lookups used by JetStream consumers (OptStartTime) by replacing linear scans with binary search.
Block selection (O(log n))
server/filestore.go:selectMsgBlockForStartnow uses binary search acrossfs.blksleveraging each block’slast.ts.Intra-block lookup (O(log n))
server/filestore.go:GetSeqFromTimenow performs a binary search within the selected block viabinarySearchSeqFromTime, probing timestamps withmb.fetchMsgNoCopy.No on-disk format changes; semantics unchanged (lower-bound: first seq with ts ≥ target).
Motivation
Fetching by timestamp was slow due to:
This reduces complexity to O(log #blocks + log #msgs-in-block), speeding consumer startup by timestamp and server APIs using
GetSeqFromTime.Changes
server/filestore.goselectMsgBlockForStartto binary search across blocks.GetSeqFromTimewith a binary search (binarySearchSeqFromTime).server/filestore_binary_search_test.goBenchmark
Prior linear scan was O(n) and significantly slower on large blocks.
Compatibility
Risks/Considerations
Follow-ups (optional)
Signed-off-by: Dario Lencina darioalessandrolencina@gmail.com