Skip to content

Conversation

@smiroslav
Copy link
Contributor

@reschke reschke changed the title Segment prefetching for CachingSegmentReader OAK-11932: Segment prefetching for CachingSegmentReader Sep 16, 2025
return out;
}

private void schedulePrefetch(long msb, long lsb, Buffer buffer) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nfsantos made a good remark that this method, from the start, should be executed in a separate thread context, so it does not impact execution time for the thread invoking CachingSegmentArchiveReader#readSegment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, my tests with #2519, which implements a similar mechanism, but on a different level of abstraction, showed that dispatching from the caller thread hurts performance.

I even opted to trigger preloading only from within the load-callback, so preloading is completely off the critical path for cache hits.

Of course that's a trade-off, as it requires the caller thread to load one segment before any preloading happens.

Copy link
Contributor

@jsedding jsedding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I think some benchmarking is needed to ensure the added overhead is worthwhile.

return out;
}

private void schedulePrefetch(long msb, long lsb, Buffer buffer) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, my tests with #2519, which implements a similar mechanism, but on a different level of abstraction, showed that dispatching from the caller thread hurts performance.

I even opted to trigger preloading only from within the load-callback, so preloading is completely off the critical path for cache hits.

Of course that's a trade-off, as it requires the caller thread to load one segment before any preloading happens.

}

// Drop prefetch if already in progress for this segment
boolean registered = inFlightPrefetch.add(ref);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea! I missed this trick so far in #2519 🙂

Comment on lines +95 to +97
List<UUID> refs = extractReferences(buffer);
int limit = Math.min(refs.size(), prefetchMaxRefs);
for (int i = 0; i < limit; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are getting a list with all the references but then potentially iterate over only a subset of them. You could save some work by extracting only the references that will be prefetched, this could also avoid allocating an array with all the refs. Using streams with limit()may be an easy way of implementing this optimization, as streams are computed lazily.

Comment on lines +103 to +105
if (persistentCache.containsSegment(rMsb, rLsb)) {
continue;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's better to do this check in the worker thread, just before the segment is downloaded? The task that is scheduled to download the segment might not execute for a while, if the worker pool is busy, so from this point until the actual download, the segment might have been added to the cache. Or we can leave the check here and do another one before trying to download.
It would also be better to have a mechanism similar to the Guava loading cache, where thread requesting a segment that is not in the cache but is being downloaded will block waiting for the first download to complete, instead of starting a new download. This would avoid duplicate downloads.

@jsedding
Copy link
Contributor

jsedding commented Oct 9, 2025

As indicated in #2569, this approach is limited in that a CachingSegmentArchiveReader has only got access to a single archive, and thus cannot read segments from other archives.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants