Uh oh!
There was an error while loading. Please reload this page.
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.
jean-philippe-martin
commented
Mar 26, 2018
@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. |
pongad
left a comment
There was a problem hiding this comment.
@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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| // 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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| * @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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| */ | ||
| 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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| // 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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| 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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| 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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
jean-philippe-martin
commented
Mar 27, 2018
In case you'd like extra eyes, @jart is familiar with this code and may be willing to help review. |
jabubake
commented
Mar 27, 2018
@frankyn FYI |
pongad
commented
Mar 28, 2018
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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| exec = Executors.newFixedThreadPool(1, threadFactory); | ||
| } | ||
| public String getStatistics() { |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| .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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| // 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.
Uh oh!
There was an error while loading. Please reload this page.
| */ | ||
| @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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| * 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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| .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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
| * (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.
Uh oh!
There was an error while loading. Please reload this page.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
* chore: manual update of update_generation_config.sh * chore: generate libraries at Thu Jul 24 18:09:38 UTC 2025 * Revert "chore: generate libraries at Thu Jul 24 18:09:38 UTC 2025" This reverts commit 9726a59d037322332a1fa0c097de6aefb663d68e. --------- Co-authored-by: cloud-java-bot <cloud-java-bot@google.com>
* chore: manual update of update_generation_config.sh * chore: generate libraries at Thu Jul 24 18:09:38 UTC 2025 * Revert "chore: generate libraries at Thu Jul 24 18:09:38 UTC 2025" This reverts commit 9726a59d037322332a1fa0c097de6aefb663d68e. --------- Co-authored-by: cloud-java-bot <cloud-java-bot@google.com>
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.
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.
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.