Skip to content
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
f111798
Absolutely garbage async io POC, it reads correctly but is slower tha…
benwtrent Sep 12, 2025
aa69974
iter
benwtrent Sep 15, 2025
e36d5a4
iter
benwtrent Sep 15, 2025
9f43918
iter
benwtrent Sep 16, 2025
8ccc268
Update docs/changelog/134803.yaml
benwtrent Sep 16, 2025
2ce6dd2
repeatably failing test
benwtrent Sep 18, 2025
74793df
Merge remote-tracking branch 'upstream/main' into exp/async-direct-io
benwtrent Sep 18, 2025
9ed9b4c
fixing bug
benwtrent Sep 18, 2025
c19b9b1
iter
benwtrent Sep 18, 2025
ca6db4a
Delete docs/changelog/134803.yaml
benwtrent Sep 18, 2025
6a5086e
iter
benwtrent Sep 18, 2025
87909c0
Merge branch 'exp/async-direct-io' of github.com:benwtrent/elasticsea…
benwtrent Sep 18, 2025
d1feca4
iter
benwtrent Sep 19, 2025
431fa36
Merge remote-tracking branch 'upstream/main' into exp/async-direct-io
benwtrent Sep 19, 2025
bfd8656
iter
benwtrent Sep 19, 2025
f5c6d7e
prep for merge
benwtrent Sep 24, 2025
ed19e82
iter
benwtrent Sep 24, 2025
89b430d
Merge remote-tracking branch 'upstream/main' into exp/async-direct-io
benwtrent Sep 24, 2025
6a72edc
fix after merge
benwtrent Sep 24, 2025
ad3b64c
Merge branch 'main' into exp/async-direct-io
benwtrent Sep 24, 2025
91a5bd0
fixing compilation
benwtrent Sep 24, 2025
d4fa576
Merge remote-tracking branch 'upstream/main' into exp/async-direct-io
benwtrent Sep 24, 2025
38a153b
iter
benwtrent Sep 24, 2025
04607d2
fixing forbidden
benwtrent Sep 24, 2025
ad17181
addressing PR comments, cleaning up code
benwtrent Sep 25, 2025
d7d36b7
Merge branch 'main' into exp/async-direct-io
benwtrent Sep 25, 2025
0ebdf43
iter
benwtrent Sep 26, 2025
6633f68
Merge branch 'exp/async-direct-io' of github.com:benwtrent/elasticsea…
benwtrent Sep 26, 2025
dd8abc9
Merge branch 'main' into exp/async-direct-io
benwtrent Sep 26, 2025
1ae5dd3
Merge remote-tracking branch 'upstream/main' into exp/async-direct-io
benwtrent Sep 29, 2025
441aa24
Merge branch 'exp/async-direct-io' of github.com:benwtrent/elasticsea…
benwtrent Sep 29, 2025
7b6a822
Merge branch 'main' into exp/async-direct-io
benwtrent Oct 2, 2025
b8afc2b
Merge remote-tracking branch 'upstream/main' into exp/async-direct-io
benwtrent Oct 6, 2025
cdfb99d
Adding a setting and addressing PR comments
benwtrent Oct 6, 2025
7636387
fixing setting
benwtrent Oct 6, 2025
cb5bd7b
Merge branch 'main' into exp/async-direct-io
benwtrent Oct 6, 2025
d7e20bb
Merge branch 'main' into exp/async-direct-io
benwtrent Oct 7, 2025
3e98e35
Merge branch 'main' into exp/async-direct-io
benwtrent Oct 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions qa/vector/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
requires org.elasticsearch.logging;
requires java.management;
requires jdk.management;
requires org.apache.lucene.misc;
requires org.elasticsearch.gpu;
}
69 changes: 2 additions & 67 deletions qa/vector/src/main/java/org/elasticsearch/test/knn/KnnIndexer.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,11 @@
import org.apache.lucene.index.VectorSimilarityFunction;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.IOContext;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.MMapDirectory;
import org.apache.lucene.store.NIOFSDirectory;
import org.apache.lucene.store.NativeFSLockFactory;
import org.apache.lucene.util.PrintStreamInfoStream;
import org.elasticsearch.common.io.Channels;
import org.elasticsearch.core.IOUtils;
import org.elasticsearch.index.store.LuceneFilesExtensions;
import org.elasticsearch.index.store.Store;
import org.elasticsearch.index.store.FsDirectoryFactory;

import java.io.IOException;
import java.io.UncheckedIOException;
Expand Down Expand Up @@ -233,7 +228,7 @@ public boolean isEnabled(String component) {
static Directory getDirectory(Path indexPath) throws IOException {
Directory dir = FSDirectory.open(indexPath);
if (dir instanceof MMapDirectory mmapDir) {
return new HybridDirectory(mmapDir);
return new FsDirectoryFactory.HybridDirectory(NativeFSLockFactory.INSTANCE, mmapDir, 64);
}
return dir;
}
Expand Down Expand Up @@ -375,64 +370,4 @@ synchronized void next(byte[] dest) throws IOException {
bytes.get(dest);
}
}

// Copy of Elastic's HybridDirectory which extends NIOFSDirectory and uses MMapDirectory for certain files.
static final class HybridDirectory extends NIOFSDirectory {
private final MMapDirectory delegate;

HybridDirectory(MMapDirectory delegate) throws IOException {
super(delegate.getDirectory(), NativeFSLockFactory.INSTANCE);
this.delegate = delegate;
}

@Override
public IndexInput openInput(String name, IOContext context) throws IOException {
if (useDelegate(name, context)) {
// we need to do these checks on the outer directory since the inner doesn't know about pending deletes
ensureOpen();
ensureCanRead(name);
// we switch the context here since mmap checks for the READONCE context by identity
context = context == Store.READONCE_CHECKSUM ? IOContext.READONCE : context;
// we only use the mmap to open inputs. Everything else is managed by the NIOFSDirectory otherwise
// we might run into trouble with files that are pendingDelete in one directory but still
// listed in listAll() from the other. We on the other hand don't want to list files from both dirs
// and intersect for perf reasons.
return delegate.openInput(name, context);
} else {
return super.openInput(name, context);
}
}

@Override
public void close() throws IOException {
IOUtils.close(super::close, delegate);
}

private static String getExtension(String name) {
// Unlike FileSwitchDirectory#getExtension, we treat `tmp` as a normal file extension, which can have its own rules for mmaping.
final int lastDotIndex = name.lastIndexOf('.');
if (lastDotIndex == -1) {
return "";
} else {
return name.substring(lastDotIndex + 1);
}
}

static boolean useDelegate(String name, IOContext ioContext) {
if (ioContext == Store.READONCE_CHECKSUM) {
// If we're just reading the footer for the checksum then mmap() isn't really necessary, and it's desperately inefficient
// if pre-loading is enabled on this file.
return false;
}

final LuceneFilesExtensions extension = LuceneFilesExtensions.fromExtension(getExtension(name));
if (extension == null || extension.shouldMmap() == false) {
// Other files are either less performance-sensitive (e.g. stored field index, norms metadata)
// or are large and have a random access pattern and mmap leads to page cache trashing
// (e.g. stored fields and term vectors).
return false;
}
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings {
IndexModule.INDEX_RECOVERY_TYPE_SETTING,
IndexModule.INDEX_QUERY_CACHE_ENABLED_SETTING,
FsDirectoryFactory.INDEX_LOCK_FACTOR_SETTING,
FsDirectoryFactory.ASYNC_PREFETCH_LIMIT,
EngineConfig.INDEX_CODEC_SETTING,
IndexMetadata.SETTING_WAIT_FOR_ACTIVE_SHARDS,
IndexSettings.DEFAULT_PIPELINE,
Expand Down
Loading