Skip to content

Commit 1c19ecf

Browse files
fix: refactor for single thread multi segment execution
1 parent e044093 commit 1c19ecf

File tree

1 file changed

+60
-33
lines changed

1 file changed

+60
-33
lines changed

benchmarks/src/main/java/org/elasticsearch/benchmark/search/query/range/DateFieldMapperDocValuesSkipperBenchmark.java

Lines changed: 60 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.openjdk.jmh.annotations.Setup;
4242
import org.openjdk.jmh.annotations.State;
4343
import org.openjdk.jmh.annotations.TearDown;
44+
import org.openjdk.jmh.annotations.Threads;
4445
import org.openjdk.jmh.annotations.Warmup;
4546
import org.openjdk.jmh.infra.Blackhole;
4647
import org.openjdk.jmh.profile.AsyncProfiler;
@@ -52,6 +53,8 @@
5253
import java.io.IOException;
5354
import java.nio.file.Files;
5455
import java.util.Random;
56+
import java.util.concurrent.ExecutorService;
57+
import java.util.concurrent.Executors;
5558
import java.util.concurrent.TimeUnit;
5659

5760
/**
@@ -98,10 +101,11 @@
98101
*/
99102
@BenchmarkMode(Mode.SampleTime)
100103
@OutputTimeUnit(TimeUnit.MILLISECONDS)
101-
@State(Scope.Thread)
104+
@State(Scope.Benchmark)
102105
@Fork(1)
103-
@Warmup(iterations = 10)
104-
@Measurement(iterations = 10)
106+
@Threads(1)
107+
@Warmup(iterations = 3)
108+
@Measurement(iterations = 5)
105109
public class DateFieldMapperDocValuesSkipperBenchmark {
106110

107111
public static void main(String[] args) throws RunnerException {
@@ -112,18 +116,21 @@ public static void main(String[] args) throws RunnerException {
112116
new Runner(options).run();
113117
}
114118

115-
@Param("1000000")
119+
@Param("1343120")
116120
private int numberOfDocuments;
117121

118-
@Param("10000")
122+
@Param({"1340", "121300"})
119123
private int batchSize;
120124

121125
@Param("1000")
122126
private int timestampIncrementMillis;
123127

124-
@Param({ "0.2" })
128+
@Param({ "0.01", "0.2", "0.8" })
125129
private double timestampRangeFraction;
126130

131+
@Param({ "7390", "398470" })
132+
private int commitEvery;
133+
127134
@Param("42")
128135
private int seed;
129136

@@ -133,10 +140,9 @@ public static void main(String[] args) throws RunnerException {
133140

134141
private static final Sort QUERY_SORT = new Sort(new SortedNumericSortField(TIMESTAMP_FIELD, SortField.Type.LONG, true));
135142

136-
private Directory tempDirectoryWithoutDocValuesSkipper;
137-
private Directory tempDirectoryWithDocValuesSkipper;
138143
private IndexSearcher indexSearcherWithoutDocValuesSkipper;
139144
private IndexSearcher indexSearcherWithDocValuesSkipper;
145+
private ExecutorService executorService;
140146

141147
/**
142148
* Sets up the benchmark by creating Lucene indexes with and without doc values skipper.
@@ -145,22 +151,26 @@ public static void main(String[] args) throws RunnerException {
145151
*/
146152
@Setup(Level.Trial)
147153
public void setup() throws IOException {
148-
tempDirectoryWithoutDocValuesSkipper = FSDirectory.open(Files.createTempDirectory("temp1-"));
149-
tempDirectoryWithDocValuesSkipper = FSDirectory.open(Files.createTempDirectory("temp2-"));
154+
executorService = Executors.newSingleThreadExecutor();
155+
Directory tempDirectoryWithoutDocValuesSkipper = FSDirectory.open(Files.createTempDirectory("temp1-"));
156+
Directory tempDirectoryWithDocValuesSkipper = FSDirectory.open(Files.createTempDirectory("temp2-"));
150157

151-
indexSearcherWithoutDocValuesSkipper = createIndex(tempDirectoryWithoutDocValuesSkipper, false);
152-
indexSearcherWithDocValuesSkipper = createIndex(tempDirectoryWithDocValuesSkipper, true);
158+
indexSearcherWithoutDocValuesSkipper = createIndex(tempDirectoryWithoutDocValuesSkipper, false, commitEvery);
159+
indexSearcherWithDocValuesSkipper = createIndex(tempDirectoryWithDocValuesSkipper, true, commitEvery);
153160
}
154161

155162
/**
156-
* Creates an index with a specified sorting order and document structure.
163+
* Creates an {@link IndexSearcher} from a newly created {@link IndexWriter}. Documents
164+
* are added to the index and committed in batches of a specified size to generate multiple segments.
157165
*
158-
* @param directory The Lucene directory to store the index.
159-
* @param withDocValuesSkipper Whether to use a sparse doc values index.
160-
* @return An IndexSearcher instance for querying the created index.
161-
* @throws IOException if an error occurs during index writing.
166+
* @param directory the Lucene {@link Directory} where the index will be written
167+
* @param withDocValuesSkipper indicates whether certain fields should skip doc values
168+
* @param commitEvery the number of documents after which to force a commit
169+
* @return an {@link IndexSearcher} that can be used to query the newly created index
170+
* @throws IOException if an I/O error occurs during index writing or reading
162171
*/
163-
private IndexSearcher createIndex(final Directory directory, boolean withDocValuesSkipper) throws IOException {
172+
private IndexSearcher createIndex(final Directory directory, final boolean withDocValuesSkipper, final int commitEvery)
173+
throws IOException {
164174
final IndexWriterConfig config = new IndexWriterConfig(new StandardAnalyzer());
165175
config.setIndexSort(
166176
new Sort(
@@ -169,19 +179,29 @@ private IndexSearcher createIndex(final Directory directory, boolean withDocValu
169179
)
170180
);
171181

172-
final IndexWriter indexWriter = new IndexWriter(directory, config);
173182
final Random random = new Random(seed);
183+
try (IndexWriter indexWriter = new IndexWriter(directory, config)) {
184+
int docCountSinceLastCommit = 0;
185+
for (int i = 0; i < numberOfDocuments; i++) {
186+
final Document doc = new Document();
187+
addFieldsToDocument(doc, i, withDocValuesSkipper, random);
188+
indexWriter.addDocument(doc);
189+
docCountSinceLastCommit++;
174190

175-
for (int i = 0; i < numberOfDocuments; i++) {
176-
final Document doc = new Document();
177-
addFieldsToDocument(doc, i, withDocValuesSkipper, random);
178-
indexWriter.addDocument(doc);
179-
}
191+
// NOTE: make sure we have multiple Lucene segments
192+
if (docCountSinceLastCommit >= commitEvery) {
193+
indexWriter.commit();
194+
docCountSinceLastCommit = 0;
195+
}
196+
}
180197

181-
indexWriter.commit();
182-
final DirectoryReader reader = DirectoryReader.open(indexWriter);
183-
indexWriter.close();
184-
return new IndexSearcher(reader);
198+
indexWriter.commit();
199+
final DirectoryReader reader = DirectoryReader.open(indexWriter);
200+
// NOTE: internally Elasticsearch runs multiple search threads concurrently, (at least) one per Lucene segment.
201+
// Here we simplify the benchmark making sure we have a single-threaded search execution using a single thread
202+
// executor Service.
203+
return new IndexSearcher(reader, executorService);
204+
}
185205
}
186206

187207
private void addFieldsToDocument(final Document doc, int docIndex, boolean withDocValuesSkipper, final Random random) {
@@ -243,10 +263,17 @@ private long rangeQuery(final IndexSearcher searcher, long rangeStartTimestamp,
243263
}
244264

245265
@TearDown(Level.Trial)
246-
public void tearDown() throws IOException {
247-
indexSearcherWithoutDocValuesSkipper.getIndexReader().close();
248-
indexSearcherWithDocValuesSkipper.getIndexReader().close();
249-
tempDirectoryWithoutDocValuesSkipper.close();
250-
tempDirectoryWithDocValuesSkipper.close();
266+
public void tearDown() {
267+
if (executorService != null) {
268+
executorService.shutdown();
269+
try {
270+
if (executorService.awaitTermination(30, TimeUnit.SECONDS) == false) {
271+
executorService.shutdownNow();
272+
}
273+
} catch (InterruptedException e) {
274+
executorService.shutdownNow();
275+
Thread.currentThread().interrupt();
276+
}
277+
}
251278
}
252279
}

0 commit comments

Comments
 (0)