Skip to content

Commit 212924e

Browse files
committed
Fix DirectIOIndexInput seek to not read when position is within buffer (#14320)
This commit changes DirectIOIndexInput::seek so that it repositions the indexInput's position without a read, when the new position is within the bounds of the current buffer.
1 parent b7df846 commit 212924e

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

lucene/CHANGES.txt

+2
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ Bug Fixes
133133

134134
* GITHUB#14215: Fix degenerate case in HNSW where all vectors have the same score. (Ben Trent)
135135

136+
* GITHUB#14320: Fix DirectIOIndexInput seek to not read when position is within buffer (Chris Hegarty)
137+
136138
Changes in Runtime Behavior
137139
---------------------
138140
* GITHUB#14189: Bump floor segment size to 16MB in TieredMergePolicy and

lucene/misc/src/java/org/apache/lucene/misc/store/DirectIODirectory.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,13 @@ public long getFilePointer() {
373373
@Override
374374
public void seek(long pos) throws IOException {
375375
if (pos != getFilePointer()) {
376-
seekInternal(pos);
376+
final long absolutePos = pos + offset;
377+
if (absolutePos >= filePos && absolutePos <= filePos + buffer.limit()) {
378+
// the new position is within the existing buffer
379+
buffer.position(Math.toIntExact(absolutePos - filePos));
380+
} else {
381+
seekInternal(pos); // do an actual seek/read
382+
}
377383
}
378384
assert pos == getFilePointer();
379385
}

lucene/misc/src/test/org/apache/lucene/misc/store/TestDirectIODirectory.java

+26
Original file line numberDiff line numberDiff line change
@@ -209,4 +209,30 @@ public void testUseDirectIODefaults() throws Exception {
209209
OptionalLong.of(largeSize)));
210210
}
211211
}
212+
213+
// Ping-pong seeks should be really fast, since the position should be within buffer.
214+
// The test should complete within sub-second times, not minutes.
215+
public void testSeekSmall() throws IOException {
216+
Path tmpDir = createTempDir("testSeekSmall");
217+
try (Directory dir = getDirectory(tmpDir)) {
218+
int len = atLeast(100);
219+
try (IndexOutput o = dir.createOutput("out", newIOContext(random()))) {
220+
byte[] b = new byte[len];
221+
for (int i = 0; i < len; i++) {
222+
b[i] = (byte) i;
223+
}
224+
o.writeBytes(b, 0, len);
225+
}
226+
try (IndexInput in = dir.openInput("out", newIOContext(random()))) {
227+
for (int i = 0; i < 100_000; i++) {
228+
in.seek(2);
229+
assertEquals(2, in.readByte());
230+
in.seek(1);
231+
assertEquals(1, in.readByte());
232+
in.seek(0);
233+
assertEquals(0, in.readByte());
234+
}
235+
}
236+
}
237+
}
212238
}

0 commit comments

Comments
 (0)