Add readAheadBuffer hint to ReadableChannel

This hint allows an underlying implementation to read more bytes when
possible and buffer them locally for future read calls to consume.

Change-Id: Ia986a1bb8640eecb91cfbd515c61fa1ff1574a6f
This commit is contained in:
Shawn Pearce 2015-04-23 21:59:23 -07:00
parent 3fa520b653
commit 1553a6ff55
3 changed files with 37 additions and 7 deletions

View File

@ -516,7 +516,9 @@ private long copyPackThroughCache(PackOutputStream out, DfsReader ctx,
private long copyPackBypassCache(PackOutputStream out, DfsReader ctx,
MessageDigest md) throws IOException {
try (ReadableChannel rc = ctx.db.openFile(packDesc, PACK)) {
ByteBuffer buf = newCopyBuffer(out, rc, ctx);
ByteBuffer buf = newCopyBuffer(out, rc);
if (ctx.getOptions().getStreamPackBufferSize() > 0)
rc.setReadAheadBytes(ctx.getOptions().getStreamPackBufferSize());
long position = 12;
long remaining = length - (12 + 20);
while (0 < remaining) {
@ -547,13 +549,8 @@ else if (n > remaining)
}
}
private ByteBuffer newCopyBuffer(PackOutputStream out, ReadableChannel rc,
DfsReader ctx) {
private ByteBuffer newCopyBuffer(PackOutputStream out, ReadableChannel rc) {
int bs = blockSize(rc);
int bufferSize = ctx.getOptions().getStreamPackBufferSize();
if (bufferSize > bs)
bs = (bufferSize / bs) * bs;
byte[] copyBuf = out.getCopyBuffer();
if (bs > copyBuf.length)
copyBuf = new byte[bs];

View File

@ -227,6 +227,10 @@ public long size() {
public int blockSize() {
return 0;
}
public void setReadAheadBytes(int b) {
// Unnecessary on a byte array.
}
}
private class MemRefDatabase extends DfsRefDatabase {

View File

@ -100,4 +100,33 @@ public interface ReadableChannel extends ReadableByteChannel {
* not need to be a power of 2.
*/
public int blockSize();
/**
* Recommend the channel maintain a read-ahead buffer.
* <p>
* A read-ahead buffer of approximately {@code bufferSize} in bytes may be
* allocated and used by the channel to smooth out latency for read.
* <p>
* Callers can continue to read in smaller than {@code bufferSize} chunks.
* With read-ahead buffering enabled read latency may fluctuate in a pattern
* of one slower read followed by {@code (bufferSize / readSize) - 1} fast
* reads satisfied by the read-ahead buffer. When summed up overall time to
* read the same contiguous range should be lower than if read-ahead was not
* enabled, as the implementation can combine reads to increase throughput.
* <p>
* To avoid unnecessary IO callers should only enable read-ahead if the
* majority of the channel will be accessed in order.
* <p>
* Implementations may chose to read-ahead using asynchronous APIs or
* background threads, or may simply aggregate reads using a buffer.
* <p>
* This read ahead stays in effect until the channel is closed or the buffer
* size is set to 0.
*
* @param bufferSize
* requested size of the read ahead buffer, in bytes.
* @throws IOException
* if the read ahead cannot be adjusted.
*/
public void setReadAheadBytes(int bufferSize) throws IOException;
}