-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prefetcher, to read fast. #3054
Conversation
The prefetcher can load data on another thread in between calls, and it can intelligently use its existing buffer to deal with small seeks without having to fetch again.
@pongad, I understand the ball is in your camp? If it isn't then please let me know what you'd like me to do before you look at this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jean-philippe-martin Thank you for the PR! I made a few comments. @garrettjonesgoogle @jabubake Could you also take a look?
@@ -0,0 +1,496 @@ | |||
/* | |||
* Copyright 2016 Google LLC |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
|
||
// statistics, for profiling | ||
// time spent blocking the user because we're waiting on the network | ||
public long msWaitingForData; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
* @param bufSize buffer size in bytes | ||
* @param chan channel to wrap in the prefetcher | ||
*/ | ||
public SeekableByteChannelPrefetcher(SeekableByteChannel chan, int bufSize) throws IOException { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
*/ | ||
public SeekableByteChannelPrefetcher(SeekableByteChannel chan, int bufSize) throws IOException { | ||
if (chan instanceof SeekableByteChannelPrefetcher) { | ||
throw new IllegalArgumentException("Cannot put two prefetchers on the same channel."); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
// if we don't already have that block and the fetching thread is idle, | ||
// make sure it now goes looking for that block index. | ||
private void ensureFetching(long blockIndex) { | ||
if (null != fetching) { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
this.bufSize = bufSize; | ||
} | ||
this.open = true; | ||
int prefetcherIndex = prefetcherCount++; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
fetching = full.remove(0); | ||
fetching.resetForIndex(blockIndex); | ||
bytesRead += bufSize; | ||
fetching.futureBuf = exec.submit(fetching); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
In case you'd like extra eyes, @jart is familiar with this code and may be willing to help review. |
@frankyn FYI |
I'm good with this. @jabubake Do you also want to take a look? |
@@ -0,0 +1,494 @@ | |||
/* | |||
* Copyright 2018 Google LLC |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
exec = Executors.newFixedThreadPool(1, threadFactory); | ||
} | ||
|
||
public String getStatistics() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
.setDaemon(true) | ||
.build(); | ||
// Single thread to ensure no concurrent access to chan. | ||
exec = Executors.newFixedThreadPool(1, threadFactory); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
// Make sure the prefetching thread's name indicate what it is and | ||
// which prefetcher it belongs to (for debugging purposes only, naturally). | ||
String nameFormat = "nio-prefetcher-" + prefetcherIndex + "-thread-%d"; | ||
ThreadFactory threadFactory = new ThreadFactoryBuilder() |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
*/ | ||
@Override | ||
public SeekableByteChannel position(long newPosition) throws IOException { | ||
if (!open) throw new ClosedChannelException(); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
* the entity to grow to accommodate the new bytes; the values of any bytes | ||
* between the previous end-of-file and the newly-written bytes are | ||
* unspecified. | ||
* <p> |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
.build(); | ||
// Single thread to ensure no concurrent access to chan. | ||
exec = Executors.newFixedThreadPool(1, threadFactory); | ||
} |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
* (Of course this is only worthwhile if the underlying SeekableByteChannel doesn't already | ||
* implement prefetching). | ||
*/ | ||
public final class SeekableByteChannelPrefetcher implements SeekableByteChannel { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
The prefetcher can load data on another thread in between calls,
and it can intelligently use its existing buffer to deal with small
seeks without having to fetch again.