Skip to content

Commit 569e484

Browse files
committed
Merge branch 'main' into jackson221
2 parents 2ff43ca + f58790c commit 569e484

File tree

837 files changed

+19590
-6037
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

837 files changed

+19590
-6037
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
# claude
33
.claude
44

5+
# JetBrainsAI/Junie
6+
.junie/
7+
58
# intellij files
69
.idea/
710
*.iml

benchmarks/src/main/java/org/elasticsearch/benchmark/_nightly/esql/ValuesSourceReaderBenchmark.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ private void setupPages() {
488488
blockFactory.newConstantIntBlockWith(0, end - begin).asVector(),
489489
blockFactory.newConstantIntBlockWith(ctx.ord, end - begin).asVector(),
490490
docs.build(),
491-
true
491+
DocVector.config().singleSegmentNonDecreasing(true)
492492
).asBlock()
493493
)
494494
);
@@ -525,7 +525,7 @@ record ItrAndOrd(PrimitiveIterator.OfInt itr, int ord) {}
525525
blockFactory.newConstantIntVector(0, size),
526526
leafs.build(),
527527
docs.build(),
528-
null
528+
DocVector.config()
529529
).asBlock()
530530
)
531531
);
@@ -543,7 +543,7 @@ record ItrAndOrd(PrimitiveIterator.OfInt itr, int ord) {}
543543
blockFactory.newConstantIntBlockWith(0, size).asVector(),
544544
leafs.build().asBlock().asVector(),
545545
docs.build(),
546-
null
546+
DocVector.config()
547547
).asBlock()
548548
)
549549
);
@@ -570,7 +570,7 @@ record ItrAndOrd(PrimitiveIterator.OfInt itr, int ord) {}
570570
blockFactory.newConstantIntVector(0, 1),
571571
blockFactory.newConstantIntVector(next.ord, 1),
572572
blockFactory.newConstantIntVector(next.itr.nextInt(), 1),
573-
true
573+
DocVector.config().singleSegmentNonDecreasing(true)
574574
).asBlock()
575575
)
576576
);

benchmarks/src/main/java/org/elasticsearch/benchmark/vector/scorer/VectorScorerInt7uOperationBenchmark.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public void init() {
9797
case DOT_PRODUCT -> VectorSimilarityFunctions.Function.DOT_PRODUCT;
9898
case EUCLIDEAN -> VectorSimilarityFunctions.Function.SQUARE_DISTANCE;
9999
default -> throw new IllegalArgumentException(function.toString());
100-
}, VectorSimilarityFunctions.DataType.INT7, VectorSimilarityFunctions.Operation.SINGLE);
100+
}, VectorSimilarityFunctions.DataType.INT7U, VectorSimilarityFunctions.Operation.SINGLE);
101101
}
102102

103103
@TearDown
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
package org.elasticsearch.benchmark.vector.scorer;
10+
11+
import org.apache.lucene.util.VectorUtil;
12+
import org.elasticsearch.common.logging.LogConfigurator;
13+
import org.elasticsearch.common.logging.NodeNamePatternConverter;
14+
import org.elasticsearch.nativeaccess.NativeAccess;
15+
import org.elasticsearch.nativeaccess.VectorSimilarityFunctions;
16+
import org.elasticsearch.simdvec.VectorSimilarityType;
17+
import org.openjdk.jmh.annotations.Benchmark;
18+
import org.openjdk.jmh.annotations.BenchmarkMode;
19+
import org.openjdk.jmh.annotations.Fork;
20+
import org.openjdk.jmh.annotations.Level;
21+
import org.openjdk.jmh.annotations.Measurement;
22+
import org.openjdk.jmh.annotations.Mode;
23+
import org.openjdk.jmh.annotations.OutputTimeUnit;
24+
import org.openjdk.jmh.annotations.Param;
25+
import org.openjdk.jmh.annotations.Scope;
26+
import org.openjdk.jmh.annotations.Setup;
27+
import org.openjdk.jmh.annotations.State;
28+
import org.openjdk.jmh.annotations.TearDown;
29+
import org.openjdk.jmh.annotations.Warmup;
30+
31+
import java.lang.foreign.Arena;
32+
import java.lang.foreign.MemorySegment;
33+
import java.lang.invoke.MethodHandle;
34+
import java.util.concurrent.ThreadLocalRandom;
35+
import java.util.concurrent.TimeUnit;
36+
37+
import static java.lang.foreign.ValueLayout.JAVA_BYTE;
38+
import static org.elasticsearch.benchmark.vector.scorer.BenchmarkUtils.rethrow;
39+
40+
@Fork(value = 3, jvmArgsPrepend = { "--add-modules=jdk.incubator.vector" })
41+
@BenchmarkMode(Mode.AverageTime)
42+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
43+
@State(Scope.Benchmark)
44+
@Warmup(iterations = 3, time = 1)
45+
@Measurement(iterations = 5, time = 1)
46+
public class VectorScorerInt8OperationBenchmark {
47+
48+
static {
49+
NodeNamePatternConverter.setGlobalNodeName("foo");
50+
LogConfigurator.loadLog4jPlugins();
51+
LogConfigurator.configureESLogging(); // native access requires logging to be initialized
52+
}
53+
54+
byte[] bytesA;
55+
byte[] bytesB;
56+
byte[] scratch;
57+
MemorySegment heapSegA, heapSegB;
58+
MemorySegment nativeSegA, nativeSegB;
59+
60+
Arena arena;
61+
62+
@Param({ "1", "128", "207", "256", "300", "512", "702", "1024", "1536", "2048" })
63+
public int size;
64+
65+
@Param({ "DOT_PRODUCT", "EUCLIDEAN" })
66+
public VectorSimilarityType function;
67+
68+
@FunctionalInterface
69+
private interface LuceneFunction {
70+
float run(byte[] vec1, byte[] vec2);
71+
}
72+
73+
private LuceneFunction luceneImpl;
74+
private MethodHandle nativeImpl;
75+
76+
@Setup(Level.Iteration)
77+
public void init() {
78+
ThreadLocalRandom random = ThreadLocalRandom.current();
79+
80+
bytesA = new byte[size];
81+
bytesB = new byte[size];
82+
scratch = new byte[size];
83+
random.nextBytes(bytesA);
84+
random.nextBytes(bytesB);
85+
heapSegA = MemorySegment.ofArray(bytesA);
86+
heapSegB = MemorySegment.ofArray(bytesB);
87+
88+
arena = Arena.ofConfined();
89+
nativeSegA = arena.allocate(bytesA.length);
90+
MemorySegment.copy(MemorySegment.ofArray(bytesA), JAVA_BYTE, 0L, nativeSegA, JAVA_BYTE, 0L, bytesA.length);
91+
nativeSegB = arena.allocate(bytesB.length);
92+
MemorySegment.copy(MemorySegment.ofArray(bytesB), JAVA_BYTE, 0L, nativeSegB, JAVA_BYTE, 0L, bytesB.length);
93+
94+
luceneImpl = switch (function) {
95+
case DOT_PRODUCT -> VectorUtil::dotProduct;
96+
case EUCLIDEAN -> VectorUtil::squareDistance;
97+
default -> throw new UnsupportedOperationException("Not used");
98+
};
99+
nativeImpl = vectorSimilarityFunctions.getHandle(switch (function) {
100+
case DOT_PRODUCT -> VectorSimilarityFunctions.Function.DOT_PRODUCT;
101+
case EUCLIDEAN -> VectorSimilarityFunctions.Function.SQUARE_DISTANCE;
102+
default -> throw new IllegalArgumentException(function.toString());
103+
}, VectorSimilarityFunctions.DataType.INT8, VectorSimilarityFunctions.Operation.SINGLE);
104+
}
105+
106+
@TearDown
107+
public void teardown() {
108+
arena.close();
109+
}
110+
111+
@Benchmark
112+
public float lucene() {
113+
return luceneImpl.run(bytesA, bytesB);
114+
}
115+
116+
@Benchmark
117+
public float luceneWithCopy() {
118+
// add a copy to better reflect what Lucene has to do to get the target vector on-heap
119+
MemorySegment.copy(nativeSegB, JAVA_BYTE, 0L, scratch, 0, scratch.length);
120+
return luceneImpl.run(bytesA, scratch);
121+
}
122+
123+
@Benchmark
124+
public int nativeWithNativeSeg() {
125+
try {
126+
return (int) nativeImpl.invokeExact(nativeSegA, nativeSegB, size);
127+
} catch (Throwable t) {
128+
throw rethrow(t);
129+
}
130+
}
131+
132+
@Benchmark
133+
public int nativeWithHeapSeg() {
134+
try {
135+
return (int) nativeImpl.invokeExact(heapSegA, heapSegB, size);
136+
} catch (Throwable t) {
137+
throw rethrow(t);
138+
}
139+
}
140+
141+
static final VectorSimilarityFunctions vectorSimilarityFunctions = NativeAccess.instance().getVectorSimilarityFunctions().orElseThrow();
142+
}

benchmarks/src/main/java/org/elasticsearch/benchmark/vector/scorer/VectorScorerOSQBenchmark.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ public float[] score() throws IOException {
198198
result.upperInterval(),
199199
result.quantizedComponentSum(),
200200
result.additionalCorrection(),
201-
VectorSimilarityFunction.EUCLIDEAN,
201+
similarityFunction,
202202
centroidDp,
203203
corrections[0],
204204
corrections[1],
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.benchmark.vector.scorer;
11+
12+
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
13+
14+
import org.apache.lucene.util.Constants;
15+
import org.elasticsearch.simdvec.VectorSimilarityType;
16+
import org.elasticsearch.test.ESTestCase;
17+
import org.junit.AssumptionViolatedException;
18+
import org.junit.BeforeClass;
19+
import org.openjdk.jmh.annotations.Param;
20+
21+
import java.util.Arrays;
22+
23+
import static org.elasticsearch.benchmark.vector.scorer.BenchmarkUtils.supportsHeapSegments;
24+
25+
public class VectorScorerInt8OperationBenchmarkTests extends ESTestCase {
26+
27+
private final VectorSimilarityType function;
28+
private final double delta;
29+
private final int size;
30+
31+
public VectorScorerInt8OperationBenchmarkTests(VectorSimilarityType function, int size) {
32+
this.function = function;
33+
this.size = size;
34+
delta = 1e-3 * size;
35+
}
36+
37+
@BeforeClass
38+
public static void skipWindows() {
39+
assumeFalse("doesn't work on windows yet", Constants.WINDOWS);
40+
}
41+
42+
public void test() {
43+
for (int i = 0; i < 100; i++) {
44+
var bench = new VectorScorerInt8OperationBenchmark();
45+
bench.function = function;
46+
bench.size = size;
47+
bench.init();
48+
try {
49+
float expected = switch (function) {
50+
case DOT_PRODUCT -> ScalarOperations.dotProduct(bench.bytesA, bench.bytesB);
51+
case EUCLIDEAN -> ScalarOperations.squareDistance(bench.bytesA, bench.bytesB);
52+
default -> throw new AssumptionViolatedException("Not tested");
53+
};
54+
assertEquals(expected, bench.lucene(), delta);
55+
assertEquals(expected, bench.luceneWithCopy(), delta);
56+
assertEquals(expected, bench.nativeWithNativeSeg(), delta);
57+
if (supportsHeapSegments()) {
58+
assertEquals(expected, bench.nativeWithHeapSeg(), delta);
59+
}
60+
} finally {
61+
bench.teardown();
62+
}
63+
}
64+
}
65+
66+
@ParametersFactory
67+
public static Iterable<Object[]> parametersFactory() {
68+
try {
69+
String[] size = VectorScorerInt8OperationBenchmark.class.getField("size").getAnnotationsByType(Param.class)[0].value();
70+
String[] functions = VectorScorerInt8OperationBenchmark.class.getField("function").getAnnotationsByType(Param.class)[0].value();
71+
return () -> Arrays.stream(size)
72+
.map(Integer::parseInt)
73+
.flatMap(i -> Arrays.stream(functions).map(VectorSimilarityType::valueOf).map(f -> new Object[] { f, i }))
74+
.iterator();
75+
} catch (NoSuchFieldException e) {
76+
throw new AssertionError(e);
77+
}
78+
}
79+
}

benchmarks/src/test/java/org/elasticsearch/benchmark/vector/scorer/VectorScorerOSQBenchmarkTests.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public void testSingleScalarVsVectorized() throws Exception {
7373

7474
float[] result = vectorized.score();
7575

76-
assertArrayEqualsPercent("single scoring, scalar VS vectorized", expected, result, deltaPercent);
76+
assertArrayEqualsPercent("single scoring, scalar VS vectorized", expected, result, deltaPercent, DEFAULT_DELTA);
7777
} finally {
7878
scalar.teardown();
7979
vectorized.teardown();
@@ -93,6 +93,7 @@ public void testBulkScalarVsVectorized() throws Exception {
9393
scalar.dims = dims;
9494
scalar.bits = bits;
9595
scalar.directoryType = directoryType;
96+
scalar.similarityFunction = similarityFunction;
9697
scalar.setup(new Random(seed));
9798

9899
float[] expected = scalar.bulkScore();
@@ -101,11 +102,12 @@ public void testBulkScalarVsVectorized() throws Exception {
101102
vectorized.dims = dims;
102103
vectorized.bits = bits;
103104
vectorized.directoryType = directoryType;
105+
vectorized.similarityFunction = similarityFunction;
104106
vectorized.setup(new Random(seed));
105107

106108
float[] result = vectorized.bulkScore();
107109

108-
assertArrayEqualsPercent("bulk scoring, scalar VS vectorized", expected, result, deltaPercent);
110+
assertArrayEqualsPercent("bulk scoring, scalar VS vectorized", expected, result, deltaPercent, DEFAULT_DELTA);
109111
} finally {
110112
scalar.teardown();
111113
vectorized.teardown();

build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/ElasticsearchJavadocPluginFuncTest.groovy

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class ElasticsearchJavadocPluginFuncTest extends AbstractGradleFuncTest {
5757
def options = normalized(file('some-depending-lib/build/tmp/javadoc/javadoc.options').text)
5858
options.contains('-notimestamp')
5959
options.contains('-quiet')
60-
options.contains("-linkoffline '$expectedLink' './some-lib/build/docs/javadoc/'")
60+
options.contains("-linkoffline '$expectedLink' '../some-lib/build/docs/javadoc/'")
6161

6262
where:
6363
version | versionType | expectedLink
@@ -131,7 +131,7 @@ class ElasticsearchJavadocPluginFuncTest extends AbstractGradleFuncTest {
131131

132132
// normal dependencies handles as usual
133133
result.task(":some-lib:javadoc").outcome == TaskOutcome.SUCCESS
134-
options.contains("-linkoffline 'https://artifacts.elastic.co/javadoc/org/acme/some-lib/1.0' './some-lib/build/docs/javadoc/'")
134+
options.contains("-linkoffline 'https://artifacts.elastic.co/javadoc/org/acme/some-lib/1.0' '../some-lib/build/docs/javadoc/'")
135135
file('some-depending-lib/build/docs/javadoc/org/acme/Something.html').exists() == false
136136

137137
// source of shadowed dependencies are inlined
@@ -179,7 +179,7 @@ class ElasticsearchJavadocPluginFuncTest extends AbstractGradleFuncTest {
179179
def options = normalized(file('some-depending-lib/build/tmp/javadoc/javadoc.options').text)
180180
options.contains('-notimestamp')
181181
options.contains('-quiet')
182-
options.contains("-linkoffline 'https://artifacts.elastic.co/javadoc/org/acme/some-lib/1.0' './some-lib/build/docs/javadoc'") == false
182+
options.contains("-linkoffline 'https://artifacts.elastic.co/javadoc/org/acme/some-lib/1.0' '../some-lib/build/docs/javadoc'") == false
183183
}
184184

185185
def "ensures module dependency in javadoc of projects"() {

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchJavadocPlugin.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,20 +115,21 @@ private void configureDependency(Project project, boolean shadowed, ProjectDepen
115115
var options = (StandardJavadocDocletOptions) javadoc.getOptions();
116116
options.linksOffline(
117117
artifactHost(project) + "/javadoc/" + artifactPath,
118-
upstreamProject.getBuildDir().getPath() + "/docs/javadoc/"
118+
project.getProjectDir().toPath().relativize(upstreamProject.getBuildDir().toPath()) + "/docs/javadoc/"
119119
);
120120
/*
121121
*some dependent javadoc tasks are explicitly skipped. We need to ignore those external links as
122122
* javadoc would fail otherwise.
123123
* Using Action here instead of lambda to keep gradle happy and don't trigger deprecation
124124
*/
125+
File projectDir = project.getProjectDir();
125126
javadoc.doFirst(new Action<Task>() {
126127
@Override
127128
public void execute(Task task) {
128129
List<JavadocOfflineLink> existingJavadocOfflineLinks = ((StandardJavadocDocletOptions) javadoc.getOptions())
129130
.getLinksOffline()
130131
.stream()
131-
.filter(javadocOfflineLink -> new File(javadocOfflineLink.getPackagelistLoc()).exists())
132+
.filter(javadocOfflineLink -> new File(projectDir, javadocOfflineLink.getPackagelistLoc()).exists())
132133
.toList();
133134
((StandardJavadocDocletOptions) javadoc.getOptions()).setLinksOffline(existingJavadocOfflineLinks);
134135

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/EmbeddedProviderExtension.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ void impl(String implName, Project implProject) {
3838
String capitalName = capitalize(projectName);
3939

4040
Configuration implConfig = project.getConfigurations().detachedConfiguration(project.getDependencies().create(implProject));
41-
implConfig.attributes(attrs -> {
42-
attrs.attribute(ARTIFACT_TYPE_ATTRIBUTE, DIRECTORY_TYPE);
43-
attrs.attribute(EmbeddedProviderPlugin.IMPL_ATTR, true);
44-
});
4541

4642
String manifestTaskName = "generate" + capitalName + "ProviderManifest";
4743
Provider<Directory> generatedResourcesRoot = project.getLayout().getBuildDirectory().dir("generated-resources");
@@ -51,11 +47,17 @@ void impl(String implName, Project implProject) {
5147
t.getProviderImplClasspath().from(implConfig);
5248
});
5349
String implTaskName = "generate" + capitalName + "ProviderImpl";
50+
51+
Configuration extractedImplConfig = implConfig.copy();
52+
extractedImplConfig.attributes(attrs -> {
53+
attrs.attribute(ARTIFACT_TYPE_ATTRIBUTE, DIRECTORY_TYPE);
54+
attrs.attribute(EmbeddedProviderPlugin.IMPL_ATTR, true);
55+
});
5456
var generateProviderImpl = project.getTasks().register(implTaskName, Sync.class);
5557
generateProviderImpl.configure(t -> {
5658
t.into(generatedResourcesRoot.map(d -> d.dir(implTaskName)));
5759
t.into("IMPL-JARS/" + implName, spec -> {
58-
spec.from(implConfig);
60+
spec.from(extractedImplConfig);
5961
spec.from(generateProviderManifest);
6062
});
6163
});

0 commit comments

Comments
 (0)