Skip to content

Commit

Permalink
Enable MemorySegment in MMapDirectory for Java 22+ and Vectorization …
Browse files Browse the repository at this point in the history
…(incubation) for exact Java 22 (#12706)
  • Loading branch information
uschindler committed Feb 9, 2024
1 parent 6a5dde6 commit f1942c7
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 12 deletions.
2 changes: 1 addition & 1 deletion gradle/generation/extract-jdk-apis.gradle
Expand Up @@ -20,7 +20,7 @@ def resources = scriptResources(buildscript)
configure(rootProject) {
ext {
// also change this in extractor tool: ExtractForeignAPI
vectorIncubatorJavaVersions = [ JavaVersion.VERSION_20, JavaVersion.VERSION_21 ] as Set
vectorIncubatorJavaVersions = [ JavaVersion.VERSION_20, JavaVersion.VERSION_21, JavaVersion.VERSION_22 ] as Set
}
}

Expand Down
11 changes: 11 additions & 0 deletions lucene/CHANGES.txt
Expand Up @@ -37,6 +37,17 @@ New Features
* GITHUB#12336: Index additional data per facet label in the taxonomy. (Shai Erera, Egor Potemkin, Mike McCandless,
Stefan Vodita)

* GITHUB#12706: Add support for the final release of Java foreign memory API in Java 22 (and later).
Lucene's MMapDirectory will now mmap Lucene indexes in chunks of 16 GiB (instead of 1 GiB) starting
from Java 19. Indexes closed while queries are running can no longer crash the JVM.
Support for vectorized implementations of VectorUtil based on jdk.incubator.vector APIs was added
for eactly Java 22. Therefore, applications started with command line parameter
"java --add-modules jdk.incubator.vector" will automatically use the new vectorized implementations
if running on a supported platform (Java 20/21/22 on x86 CPUs with AVX2 or later or ARM NEON CPUs).
This is an opt-in feature and requires explicit Java command line flag! When enabled, Lucene logs
a notice using java.util.logging. Please test thoroughly and report bugs/slowness to Lucene's mailing
list. (Uwe Schindler, Chris Hegarty)

Improvements
---------------------

Expand Down
Expand Up @@ -103,7 +103,7 @@ public static VectorizationProvider getInstance() {
// visible for tests
static VectorizationProvider lookup(boolean testMode) {
final int runtimeVersion = Runtime.version().feature();
if (runtimeVersion >= 20 && runtimeVersion <= 21) {
if (runtimeVersion >= 20 && runtimeVersion <= 22) {
// is locale sane (only buggy in Java 20)
if (isAffectedByJDK8301190()) {
LOG.warning(
Expand Down Expand Up @@ -169,9 +169,9 @@ static VectorizationProvider lookup(boolean testMode) {
} catch (ClassNotFoundException cnfe) {
throw new LinkageError("PanamaVectorizationProvider is missing in Lucene JAR file", cnfe);
}
} else if (runtimeVersion >= 22) {
} else if (runtimeVersion >= 23) {
LOG.warning(
"You are running with Java 22 or later. To make full use of the Vector API, please update Apache Lucene.");
"You are running with Java 23 or later. To make full use of the Vector API, please update Apache Lucene.");
} else if (lookupVectorModule().isPresent()) {
LOG.warning(
"Java vector incubator module was enabled by command line flags, but your Java version is too old: "
Expand Down
Expand Up @@ -417,7 +417,7 @@ private static MMapIndexInputProvider lookupProvider() {
}
final var lookup = MethodHandles.lookup();
final int runtimeVersion = Runtime.version().feature();
if (runtimeVersion >= 19 && runtimeVersion <= 21) {
if (runtimeVersion >= 19) {
try {
final var cls = lookup.findClass("org.apache.lucene.store.MemorySegmentIndexInputProvider");
// we use method handles, so we do not need to deal with setAccessible as we have private
Expand All @@ -437,9 +437,6 @@ private static MMapIndexInputProvider lookupProvider() {
throw new LinkageError(
"MemorySegmentIndexInputProvider is missing in Lucene JAR file", cnfe);
}
} else if (runtimeVersion >= 22) {
LOG.warning(
"You are running with Java 22 or later. To make full use of MMapDirectory, please update Apache Lucene.");
}
return new MappedByteBufferIndexInputProvider();
}
Expand Down
Expand Up @@ -108,10 +108,16 @@ AlreadyClosedException alreadyClosed(RuntimeException e) {
if (this.curSegment == null) {
return new AlreadyClosedException("Already closed: " + this);
}
// ISE can be thrown by MemorySegment and contains "closed" in message:
// in Java 22 or later we can check the isAlive status of all segments
// (see https://bugs.openjdk.org/browse/JDK-8310644):
if (Arrays.stream(segments).allMatch(s -> s.scope().isAlive()) == false) {
return new AlreadyClosedException("Already closed: " + this);
}
// fallback for Java 21: ISE can be thrown by MemorySegment and contains "closed" in message:
if (e instanceof IllegalStateException
&& e.getMessage() != null
&& e.getMessage().contains("closed")) {
// the check is on message only, so preserve original cause for debugging:
return new AlreadyClosedException("Already closed: " + this, e);
}
// otherwise rethrow unmodified NPE/ISE (as it possibly a bug with passing a null parameter to
Expand Down
Expand Up @@ -33,7 +33,7 @@ final class MemorySegmentIndexInputProvider implements MMapDirectory.MMapIndexIn
public MemorySegmentIndexInputProvider() {
var log = Logger.getLogger(getClass().getName());
log.info(
"Using MemorySegmentIndexInput with Java 21; to disable start with -D"
"Using MemorySegmentIndexInput with Java 21 or later; to disable start with -D"
+ MMapDirectory.ENABLE_MEMORY_SEGMENTS_SYSPROP
+ "=false");
}
Expand Down
Expand Up @@ -48,9 +48,9 @@ private static boolean isMemorySegmentImpl() {

public void testCorrectImplementation() {
final int runtimeVersion = Runtime.version().feature();
if (runtimeVersion >= 19 && runtimeVersion <= 21) {
if (runtimeVersion >= 19) {
assertTrue(
"on Java 19, 20, and 21 we should use MemorySegmentIndexInputProvider to create mmap IndexInputs",
"on Java 19 or later we should use MemorySegmentIndexInputProvider to create mmap IndexInputs",
isMemorySegmentImpl());
} else {
assertSame(MappedByteBufferIndexInputProvider.class, MMapDirectory.PROVIDER.getClass());
Expand Down

0 comments on commit f1942c7

Please sign in to comment.