Skip to content

Commit 2b55691

Browse files
authored
Merge branch 'main' into main
2 parents 68fcab2 + 15fcc08 commit 2b55691

47 files changed

Lines changed: 4392 additions & 52 deletions

File tree

Some content is hidden

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

.ci/bwcVersions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,4 @@ BWC_VERSION:
5757
- "3.3.2"
5858
- "3.4.0"
5959
- "3.5.0"
60+
- "3.6.0"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.claude
22
CLAUDE.md
33
.cursor*
4+
.kiro*
45

56
# intellij files
67
.idea/

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
2525
- Add new setting property 'Sensitive' for tiering dynamic settings ([#20901](https://github.com/opensearch-project/OpenSearch/pull/20901))
2626
- Add ref_path support for package-based hunspell dictionary loading ([#20840](https://github.com/opensearch-project/OpenSearch/pull/20840))
2727
- Add support for enabling pluggable data formats, starting with phase-1 of decoupling shard from engine, and introducing basic abstractions ([#20675](https://github.com/opensearch-project/OpenSearch/pull/20675))
28+
- Add concurrent queue in libs and composite engine sandbox plugin ([#20909](https://github.com/opensearch-project/OpenSearch/pull/20909))
29+
- Add interface for the Multi format merge flow ([#20908](https://github.com/opensearch-project/OpenSearch/pull/20908))
2830

2931
- Add warmup phase to wait for lag to catch up in pull-based ingestion before serving ([#20526](https://github.com/opensearch-project/OpenSearch/pull/20526))
3032
- Add a new static method to IndicesOptions API to expose `STRICT_EXPAND_OPEN_HIDDEN_FORBID_CLOSED` index option ([#20980](https://github.com/opensearch-project/OpenSearch/pull/20980))
@@ -97,4 +99,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
9799

98100
### Removed
99101

100-
[Unreleased 3.x]: https://github.com/opensearch-project/OpenSearch/compare/3.6...main
102+
[Unreleased 3.x]: https://github.com/opensearch-project/OpenSearch/compare/3.7...main

buildSrc/version.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# Please use ../gradle/libs.versions.toml for dependency management
2-
opensearch = 3.6.0
2+
opensearch = 3.7.0

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[versions]
2-
opensearch = "3.6.0"
2+
opensearch = "3.7.0"
33
lucene = "10.4.0"
44

55
bundled_jdk_vendor = "adoptium"

libs/concurrent-queue/build.gradle

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
/*
10+
* Shared concurrent queue utilities for the composite indexing engine.
11+
* No external dependencies — pure Java concurrency primitives.
12+
*/
13+
14+
// ---- JMH benchmark source set ----
15+
sourceSets {
16+
jmh {
17+
java.srcDirs = ['src/jmh/java']
18+
compileClasspath += sourceSets.main.output
19+
runtimeClasspath += sourceSets.main.output
20+
}
21+
}
22+
23+
dependencies {
24+
/*******
25+
* !!!! NO RUNTIME DEPENDENCIES !!!!
26+
*******/
27+
28+
testImplementation "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
29+
testImplementation "junit:junit:${versions.junit}"
30+
testImplementation "org.hamcrest:hamcrest:${versions.hamcrest}"
31+
32+
testImplementation(project(":test:framework")) {
33+
exclude group: 'org.opensearch', module: 'opensearch-concurrent-queue'
34+
}
35+
36+
// JMH benchmark dependencies
37+
jmhImplementation "org.openjdk.jmh:jmh-core:${versions.jmh}"
38+
jmhAnnotationProcessor "org.openjdk.jmh:jmh-generator-annprocess:${versions.jmh}"
39+
}
40+
41+
testingConventions.enabled = true
42+
43+
tasks.named('forbiddenApisMain').configure {
44+
// :libs:opensearch-concurrent-queue does not depend on server
45+
replaceSignatureFiles 'jdk-signatures'
46+
}
47+
48+
// JMH generated code uses forbidden APIs — skip checking
49+
tasks.matching { it.name == 'forbiddenApisJmh' }.configureEach { enabled = false }
50+
51+
// JMH annotation processor
52+
tasks.named('compileJmhJava').configure {
53+
options.compilerArgs.addAll(["-processor", "org.openjdk.jmh.generators.BenchmarkProcessor"])
54+
}
55+
56+
// Convenience task to run JMH benchmarks
57+
tasks.register('jmh', JavaExec) {
58+
dependsOn jmhClasses
59+
mainClass = 'org.openjdk.jmh.Main'
60+
classpath = sourceSets.jmh.runtimeClasspath
61+
// Pass -Pjmh.includes=<regex> to filter benchmarks
62+
if (project.hasProperty('jmh.includes')) {
63+
args project.property('jmh.includes')
64+
}
65+
}
66+
67+
spotless {
68+
java {
69+
targetExclude 'src/jmh/generated/**/*.java'
70+
}
71+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.common.queue;
10+
11+
import org.openjdk.jmh.annotations.Benchmark;
12+
import org.openjdk.jmh.annotations.BenchmarkMode;
13+
import org.openjdk.jmh.annotations.Fork;
14+
import org.openjdk.jmh.annotations.Level;
15+
import org.openjdk.jmh.annotations.Measurement;
16+
import org.openjdk.jmh.annotations.Mode;
17+
import org.openjdk.jmh.annotations.OutputTimeUnit;
18+
import org.openjdk.jmh.annotations.Param;
19+
import org.openjdk.jmh.annotations.Scope;
20+
import org.openjdk.jmh.annotations.Setup;
21+
import org.openjdk.jmh.annotations.State;
22+
import org.openjdk.jmh.annotations.Threads;
23+
import org.openjdk.jmh.annotations.Warmup;
24+
import org.openjdk.jmh.infra.Blackhole;
25+
26+
import java.util.LinkedList;
27+
import java.util.concurrent.TimeUnit;
28+
import java.util.concurrent.locks.ReentrantLock;
29+
30+
/**
31+
* JMH benchmark for {@link LockableConcurrentQueue} measuring throughput of
32+
* lock-and-poll / add-and-unlock cycles under varying concurrency levels.
33+
*/
34+
@Fork(3)
35+
@Warmup(iterations = 5, time = 1)
36+
@Measurement(iterations = 10, time = 1)
37+
@BenchmarkMode(Mode.Throughput)
38+
@OutputTimeUnit(TimeUnit.MICROSECONDS)
39+
@State(Scope.Benchmark)
40+
@SuppressWarnings("unused")
41+
public class LockableConcurrentQueueBenchmark {
42+
43+
@Param({ "1", "4", "8" })
44+
int concurrency;
45+
46+
@Param({ "16", "64" })
47+
int poolSize;
48+
49+
private LockableConcurrentQueue<LockableEntry> queue;
50+
51+
@Setup(Level.Iteration)
52+
public void setup() {
53+
queue = new LockableConcurrentQueue<>(LinkedList::new, concurrency);
54+
for (int i = 0; i < poolSize; i++) {
55+
LockableEntry entry = new LockableEntry();
56+
entry.lock();
57+
queue.addAndUnlock(entry);
58+
}
59+
}
60+
61+
@Benchmark
62+
@Threads(1)
63+
public LockableEntry pollAndReturn_1thread() {
64+
return pollAndReturn();
65+
}
66+
67+
@Benchmark
68+
@Threads(4)
69+
public LockableEntry pollAndReturn_4threads() {
70+
return pollAndReturn();
71+
}
72+
73+
@Benchmark
74+
@Threads(8)
75+
public LockableEntry pollAndReturn_8threads() {
76+
return pollAndReturn();
77+
}
78+
79+
private LockableEntry pollAndReturn() {
80+
LockableEntry entry = queue.lockAndPoll();
81+
if (entry != null) {
82+
queue.addAndUnlock(entry);
83+
}
84+
return entry;
85+
}
86+
87+
@Benchmark
88+
@Threads(4)
89+
public void writerWorkload_4threads(Blackhole bh) {
90+
writerWorkload(bh);
91+
}
92+
93+
@Benchmark
94+
@Threads(8)
95+
public void writerWorkload_8threads(Blackhole bh) {
96+
writerWorkload(bh);
97+
}
98+
99+
@Benchmark
100+
@Threads(16)
101+
public void writerWorkload_16threads(Blackhole bh) {
102+
writerWorkload(bh);
103+
}
104+
105+
private void writerWorkload(Blackhole bh) {
106+
LockableEntry entry = queue.lockAndPoll();
107+
if (entry != null) {
108+
bh.consume(simulateWork(entry));
109+
queue.addAndUnlock(entry);
110+
}
111+
}
112+
113+
private static long simulateWork(LockableEntry entry) {
114+
long result = entry.hashCode();
115+
for (int i = 0; i < 20; i++) {
116+
result ^= (result << 13);
117+
result ^= (result >> 7);
118+
result ^= (result << 17);
119+
}
120+
return result;
121+
}
122+
123+
static final class LockableEntry implements Lockable {
124+
private final ReentrantLock lock = new ReentrantLock();
125+
126+
@Override
127+
public void lock() {
128+
lock.lock();
129+
}
130+
131+
@Override
132+
public boolean tryLock() {
133+
return lock.tryLock();
134+
}
135+
136+
@Override
137+
public void unlock() {
138+
lock.unlock();
139+
}
140+
}
141+
}

0 commit comments

Comments
 (0)