Skip to content

Commit a06cf2c

Browse files
authored
Use cached SourceLookup for FieldScript (#17927)
Signed-off-by: Jay Deng <[email protected]>
1 parent 1b48dbd commit a06cf2c

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

server/src/main/java/org/opensearch/search/lookup/SearchLookup.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.util.LinkedHashSet;
4343
import java.util.Objects;
4444
import java.util.Set;
45+
import java.util.concurrent.ConcurrentHashMap;
4546
import java.util.function.BiFunction;
4647
import java.util.function.Supplier;
4748

@@ -77,10 +78,10 @@ public class SearchLookup {
7778
*/
7879
private final Set<String> fieldChain;
7980
private final DocLookup docMap;
80-
private final SourceLookup sourceLookup;
8181
private final FieldsLookup fieldsLookup;
8282
private final BiFunction<MappedFieldType, Supplier<SearchLookup>, IndexFieldData<?>> fieldDataLookup;
8383
private final int shardId;
84+
private final ConcurrentHashMap<Long, SourceLookup> sourceLookupMap = new ConcurrentHashMap<>();
8485

8586
/**
8687
* Constructor for backwards compatibility. Use the one with explicit shardId argument.
@@ -101,14 +102,22 @@ public SearchLookup(
101102
MapperService mapperService,
102103
BiFunction<MappedFieldType, Supplier<SearchLookup>, IndexFieldData<?>> fieldDataLookup,
103104
int shardId
105+
) {
106+
this(mapperService, fieldDataLookup, shardId, new FieldsLookup(mapperService));
107+
}
108+
109+
public SearchLookup(
110+
MapperService mapperService,
111+
BiFunction<MappedFieldType, Supplier<SearchLookup>, IndexFieldData<?>> fieldDataLookup,
112+
int shardId,
113+
FieldsLookup fieldsLookup
104114
) {
105115
this.fieldChain = Collections.emptySet();
106116
docMap = new DocLookup(
107117
mapperService,
108118
fieldType -> fieldDataLookup.apply(fieldType, () -> forkAndTrackFieldReferences(fieldType.name()))
109119
);
110-
sourceLookup = new SourceLookup();
111-
fieldsLookup = new FieldsLookup(mapperService);
120+
this.fieldsLookup = fieldsLookup;
112121
this.fieldDataLookup = fieldDataLookup;
113122
this.shardId = shardId;
114123
}
@@ -126,7 +135,6 @@ private SearchLookup(SearchLookup searchLookup, Set<String> fieldChain) {
126135
searchLookup.docMap.mapperService(),
127136
fieldType -> searchLookup.fieldDataLookup.apply(fieldType, () -> forkAndTrackFieldReferences(fieldType.name()))
128137
);
129-
this.sourceLookup = searchLookup.sourceLookup;
130138
this.fieldsLookup = searchLookup.fieldsLookup;
131139
this.fieldDataLookup = searchLookup.fieldDataLookup;
132140
this.shardId = searchLookup.shardId;
@@ -160,7 +168,7 @@ public LeafSearchLookup getLeafSearchLookup(LeafReaderContext context) {
160168
return new LeafSearchLookup(
161169
context,
162170
docMap.getLeafDocLookup(context),
163-
new SourceLookup(),
171+
sourceLookupMap.computeIfAbsent(Thread.currentThread().threadId(), K -> new SourceLookup()),
164172
fieldsLookup.getLeafFieldsLookup(context)
165173
);
166174
}
@@ -173,7 +181,7 @@ public DocLookup doc() {
173181
* Returned SourceLookup will be unrelated to any created LeafSearchLookups. Instead, use {@link LeafSearchLookup#source()} to access the related {@link SearchLookup}.
174182
*/
175183
public SourceLookup source() {
176-
return sourceLookup;
184+
return sourceLookupMap.computeIfAbsent(Thread.currentThread().threadId(), K -> new SourceLookup());
177185
}
178186

179187
public int shardId() {

server/src/test/java/org/opensearch/script/ScriptServiceTests.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import org.opensearch.core.common.bytes.BytesReference;
4747
import org.opensearch.core.xcontent.MediaTypeRegistry;
4848
import org.opensearch.env.Environment;
49+
import org.opensearch.search.lookup.FieldsLookup;
50+
import org.opensearch.search.lookup.SearchLookup;
4951
import org.opensearch.test.OpenSearchTestCase;
5052
import org.junit.Before;
5153

@@ -63,10 +65,12 @@
6365
import static org.opensearch.script.ScriptService.SCRIPT_GENERAL_CACHE_SIZE_SETTING;
6466
import static org.opensearch.script.ScriptService.SCRIPT_GENERAL_MAX_COMPILATIONS_RATE_SETTING;
6567
import static org.opensearch.script.ScriptService.SCRIPT_MAX_COMPILATIONS_RATE_SETTING;
68+
import static org.opensearch.search.lookup.SearchLookup.UNKNOWN_SHARD_ID;
6669
import static org.hamcrest.CoreMatchers.containsString;
6770
import static org.hamcrest.Matchers.is;
6871
import static org.hamcrest.Matchers.notNullValue;
6972
import static org.hamcrest.Matchers.sameInstance;
73+
import static org.mockito.Mockito.mock;
7074

7175
public class ScriptServiceTests extends OpenSearchTestCase {
7276

@@ -180,6 +184,22 @@ public void testInlineScriptCompiledOnceCache() throws IOException {
180184
assertThat(factoryScript1, sameInstance(factoryScript2));
181185
}
182186

187+
public void testScriptsUseCachedSourceLookup() throws IOException {
188+
buildScriptService(Settings.EMPTY);
189+
Script script = new Script(ScriptType.INLINE, "test", "1+1", Collections.emptyMap());
190+
FieldScript.Factory factoryScript = scriptService.compile(script, FieldScript.CONTEXT);
191+
192+
FieldScript.LeafFactory leafFactory = factoryScript.newFactory(
193+
new HashMap<>(),
194+
new SearchLookup(null, null, UNKNOWN_SHARD_ID, mock(FieldsLookup.class))
195+
);
196+
197+
FieldScript script1 = leafFactory.newInstance(null);
198+
FieldScript script2 = leafFactory.newInstance(null);
199+
200+
assertThat(script1.getLeafLookup().source(), sameInstance(script2.getLeafLookup().source()));
201+
}
202+
183203
public void testAllowAllScriptTypeSettings() throws IOException {
184204
buildScriptService(Settings.EMPTY);
185205

0 commit comments

Comments
 (0)