Skip to content

Commit d553989

Browse files
authored
Specialize skip for InputStreamIndexInput (#118436) (#118477)
Skip would previously defer to the default implementation that reads bytes unnecessarily and may be slow. We now specialize it so that it seeks quickly. Closes ES-10234
1 parent 494cae9 commit d553989

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

server/src/main/java/org/elasticsearch/common/lucene/store/InputStreamIndexInput.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,15 @@ public synchronized void reset() throws IOException {
8888
indexInput.seek(markPointer);
8989
counter = markCounter;
9090
}
91+
92+
@Override
93+
public long skip(long n) throws IOException {
94+
long skipBytes = Math.min(n, Math.min(indexInput.length() - indexInput.getFilePointer(), limit - counter));
95+
if (skipBytes <= 0) {
96+
return 0;
97+
}
98+
indexInput.skipBytes(skipBytes);
99+
counter += skipBytes;
100+
return skipBytes;
101+
}
91102
}

server/src/test/java/org/elasticsearch/common/lucene/store/InputStreamIndexInputTests.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ public void testReadMultiFourBytesLimit() throws IOException {
218218
assertThat(is.read(read), equalTo(-1));
219219
}
220220

221-
public void testMarkRest() throws Exception {
221+
public void testMarkReset() throws Exception {
222222
Directory dir = new ByteBuffersDirectory();
223223
IndexOutput output = dir.createOutput("test", IOContext.DEFAULT);
224224
for (int i = 0; i < 3; i++) {
@@ -243,6 +243,41 @@ public void testMarkRest() throws Exception {
243243
assertThat(is.read(), equalTo(2));
244244
}
245245

246+
public void testSkipBytes() throws Exception {
247+
Directory dir = new ByteBuffersDirectory();
248+
IndexOutput output = dir.createOutput("test", IOContext.DEFAULT);
249+
int bytes = randomIntBetween(10, 100);
250+
for (int i = 0; i < bytes; i++) {
251+
output.writeByte((byte) i);
252+
}
253+
output.close();
254+
255+
int limit = randomIntBetween(0, bytes * 2);
256+
int initialReadBytes = randomIntBetween(0, limit);
257+
int skipBytes = randomIntBetween(0, limit);
258+
int seekExpected = Math.min(Math.min(initialReadBytes + skipBytes, limit), bytes);
259+
int skipBytesExpected = Math.max(seekExpected - initialReadBytes, 0);
260+
logger.debug(
261+
"bytes: {}, limit: {}, initialReadBytes: {}, skipBytes: {}, seekExpected: {}, skipBytesExpected: {}",
262+
bytes,
263+
limit,
264+
initialReadBytes,
265+
skipBytes,
266+
seekExpected,
267+
skipBytesExpected
268+
);
269+
270+
IndexInput input = dir.openInput("test", IOContext.DEFAULT);
271+
InputStreamIndexInput is = new InputStreamIndexInput(input, limit);
272+
is.readNBytes(initialReadBytes);
273+
assertThat(is.skip(skipBytes), equalTo((long) skipBytesExpected));
274+
275+
int remainingBytes = Math.min(bytes, limit) - seekExpected;
276+
for (int i = seekExpected; i < seekExpected + remainingBytes; i++) {
277+
assertThat(is.read(), equalTo(i));
278+
}
279+
}
280+
246281
public void testReadZeroShouldReturnZero() throws IOException {
247282
try (Directory dir = new ByteBuffersDirectory()) {
248283
try (IndexOutput output = dir.createOutput("test", IOContext.DEFAULT)) {

0 commit comments

Comments
 (0)