Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check the real memory circuit breaker when building global ordinals #102462

Merged
merged 5 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@

import org.apache.logging.log4j.Logger;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.FilterLeafReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.OrdinalMap;
import org.apache.lucene.index.SortedSetDocValues;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.packed.PackedInts;
import org.elasticsearch.common.breaker.CircuitBreaker;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.index.fielddata.IndexOrdinalsFieldData;
import org.elasticsearch.index.fielddata.LeafOrdinalsFieldData;
import org.elasticsearch.index.fielddata.plain.AbstractLeafOrdinalsFieldData;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.script.field.ToScriptFieldFactory;

import java.io.IOException;
Expand All @@ -37,7 +39,7 @@ public enum GlobalOrdinalsBuilder {
public static IndexOrdinalsFieldData build(
final IndexReader indexReader,
IndexOrdinalsFieldData indexFieldData,
CircuitBreakerService breakerService,
CircuitBreaker breaker,
Logger logger,
ToScriptFieldFactory<SortedSetDocValues> toScriptFieldFactory
) throws IOException {
Expand All @@ -50,9 +52,25 @@ public static IndexOrdinalsFieldData build(
atomicFD[i] = indexFieldData.load(indexReader.leaves().get(i));
subs[i] = atomicFD[i].getOrdinalsValues();
}
final OrdinalMap ordinalMap = OrdinalMap.build(null, subs, PackedInts.DEFAULT);
final TermsEnum[] termsEnums = new TermsEnum[subs.length];
final long[] weights = new long[subs.length];
final long[] counter = new long[1];
iverase marked this conversation as resolved.
Show resolved Hide resolved
for (int i = 0; i < subs.length; ++i) {
termsEnums[i] = new FilterLeafReader.FilterTermsEnum(subs[i].termsEnum()) {
@Override
public BytesRef next() throws IOException {
// check parent circuit breaker every 8192 calls
if ((++counter[0] & 0x1FFF) == 0x1FFF) {
iverase marked this conversation as resolved.
Show resolved Hide resolved
breaker.addEstimateBytesAndMaybeBreak(0L, "Global Ordinals");
}
return in.next();
}
};
weights[i] = subs[i].getValueCount();
}
final OrdinalMap ordinalMap = OrdinalMap.build(null, termsEnums, weights, PackedInts.DEFAULT);
final long memorySizeInBytes = ordinalMap.ramBytesUsed();
breakerService.getBreaker(CircuitBreaker.FIELDDATA).addWithoutBreaking(memorySizeInBytes);
breaker.addWithoutBreaking(memorySizeInBytes);

TimeValue took = new TimeValue(System.nanoTime() - startTimeNS, TimeUnit.NANOSECONDS);
if (logger.isDebugEnabled()) {
Expand Down Expand Up @@ -108,5 +126,4 @@ public void close() {}
took
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.breaker.CircuitBreaker;
import org.elasticsearch.index.fielddata.IndexFieldDataCache;
import org.elasticsearch.index.fielddata.IndexOrdinalsFieldData;
import org.elasticsearch.index.fielddata.LeafOrdinalsFieldData;
Expand Down Expand Up @@ -136,7 +137,13 @@ private IndexOrdinalsFieldData loadGlobalInternal(DirectoryReader indexReader) {

@Override
public IndexOrdinalsFieldData loadGlobalDirect(DirectoryReader indexReader) throws Exception {
return GlobalOrdinalsBuilder.build(indexReader, this, breakerService, logger, toScriptFieldFactory);
return GlobalOrdinalsBuilder.build(
indexReader,
this,
breakerService.getBreaker(CircuitBreaker.FIELDDATA),
logger,
toScriptFieldFactory
);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import org.apache.lucene.index.SortedSetDocValues;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.breaker.CircuitBreaker;
import org.elasticsearch.common.breaker.CircuitBreakingException;
import org.elasticsearch.common.breaker.NoopCircuitBreaker;
import org.elasticsearch.common.lucene.index.ElasticsearchDirectoryReader;
import org.elasticsearch.index.fielddata.plain.PagedBytesIndexFieldData;
import org.elasticsearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData;
Expand Down Expand Up @@ -78,6 +81,52 @@ public void testLoadGlobal_neverCacheIfFieldIsMissing() throws Exception {
dir.close();
}

public void testGlobalOrdinalsCircuitBreaker() throws Exception {
Directory dir = newDirectory();
IndexWriterConfig iwc = new IndexWriterConfig(null);
iwc.setMergePolicy(NoMergePolicy.INSTANCE);
IndexWriter iw = new IndexWriter(dir, iwc);
long numDocs = randomIntBetween(8192, 2 * 8192);

for (int i = 1; i <= numDocs; i++) {
Document doc = new Document();
doc.add(new SortedSetDocValuesField("field1", new BytesRef(String.valueOf(i))));
iw.addDocument(doc);
if (i % 24 == 0) {
iw.commit();
}
}
iw.close();
DirectoryReader ir = ElasticsearchDirectoryReader.wrap(DirectoryReader.open(dir), new ShardId("_index", "_na_", 0));

boolean[] called = new boolean[1];
SortedSetOrdinalsIndexFieldData sortedSetOrdinalsIndexFieldData = new SortedSetOrdinalsIndexFieldData(
new DummyAccountingFieldDataCache(),
"field1",
CoreValuesSourceType.KEYWORD,
new NoneCircuitBreakerService() {
@Override
public CircuitBreaker getBreaker(String name) {
assertThat(name, equalTo(CircuitBreaker.FIELDDATA));
return new NoopCircuitBreaker("test") {
@Override
public void addEstimateBytesAndMaybeBreak(long bytes, String label) throws CircuitBreakingException {
assertThat(label, equalTo("Global Ordinals"));
assertThat(bytes, equalTo(0L));
called[0] = true;
}
};
}
},
MOCK_TO_SCRIPT_FIELD
);
sortedSetOrdinalsIndexFieldData.loadGlobal(ir);
assertThat(called[0], equalTo(true));

ir.close();
dir.close();
}

private SortedSetOrdinalsIndexFieldData createSortedDV(String fieldName, IndexFieldDataCache indexFieldDataCache) {
return new SortedSetOrdinalsIndexFieldData(
indexFieldDataCache,
Expand Down