Skip to content

ESQL: Split large pages on load sometimes (#131053) #132036

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

Merged
merged 3 commits into from
Jul 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions benchmarks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,10 @@ exit
Grab the async profiler from https://github.com/jvm-profiling-tools/async-profiler
and run `prof async` like so:
```
gradlew -p benchmarks/ run --args 'LongKeyedBucketOrdsBenchmark.multiBucket -prof "async:libPath=/home/nik9000/Downloads/async-profiler-3.0-29ee888-linux-x64/lib/libasyncProfiler.so;dir=/tmp/prof;output=flamegraph"'
gradlew -p benchmarks/ run --args 'LongKeyedBucketOrdsBenchmark.multiBucket -prof "async:libPath=/home/nik9000/Downloads/async-profiler-4.0-linux-x64/lib/libasyncProfiler.so;dir=/tmp/prof;output=flamegraph"'
```

Note: As of January 2025 the latest release of async profiler doesn't work
with our JDK but the nightly is fine.
Note: As of July 2025 the 4.0 release of the async profiler works well.

If you are on Mac, this'll warn you that you downloaded the shared library from
the internet. You'll need to go to settings and allow it to run.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.NumericUtils;
import org.elasticsearch.common.breaker.NoopCircuitBreaker;
import org.elasticsearch.common.logging.LogConfigurator;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.compute.data.BlockFactory;
import org.elasticsearch.compute.data.BytesRefBlock;
Expand Down Expand Up @@ -84,10 +86,13 @@
@State(Scope.Thread)
@Fork(1)
public class ValuesSourceReaderBenchmark {
static {
LogConfigurator.configureESLogging();
}

private static final int BLOCK_LENGTH = 16 * 1024;
private static final int INDEX_SIZE = 10 * BLOCK_LENGTH;
private static final int COMMIT_INTERVAL = 500;
private static final BigArrays BIG_ARRAYS = BigArrays.NON_RECYCLING_INSTANCE;
private static final BlockFactory blockFactory = BlockFactory.getInstance(
new NoopCircuitBreaker("noop"),
BigArrays.NON_RECYCLING_INSTANCE
Expand Down Expand Up @@ -296,6 +301,7 @@ private static BlockLoader numericBlockLoader(WhereAndBaseName w, NumberFieldMap
public void benchmark() {
ValuesSourceReaderOperator op = new ValuesSourceReaderOperator(
blockFactory,
ByteSizeValue.ofMb(1).getBytes(),
fields(name),
List.of(new ValuesSourceReaderOperator.ShardContext(reader, () -> {
throw new UnsupportedOperationException("can't load _source here");
Expand Down
5 changes: 5 additions & 0 deletions docs/changelog/131053.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 131053
summary: Split large pages on load sometimes
area: ES|QL
type: bug
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ protected void writeExtent(BlockLoader.IntBuilder builder, Extent extent) {
public BlockLoader.AllReader reader(LeafReaderContext context) throws IOException {
return new BlockLoader.AllReader() {
@Override
public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs docs) throws IOException {
public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException {
var binaryDocValues = context.reader().getBinaryDocValues(fieldName);
var reader = new GeometryDocValueReader();
try (var builder = factory.ints(docs.count())) {
for (int i = 0; i < docs.count(); i++) {
try (var builder = factory.ints(docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
read(binaryDocValues, docs.get(i), reader, builder);
}
return builder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ private static class SingletonLongs extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BlockLoader.LongBuilder builder = factory.longsFromDocValues(docs.count())) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BlockLoader.LongBuilder builder = factory.longsFromDocValues(docs.count() - offset)) {
int lastDoc = -1;
for (int i = 0; i < docs.count(); i++) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < lastDoc) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -172,9 +172,9 @@ private static class Longs extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BlockLoader.LongBuilder builder = factory.longsFromDocValues(docs.count())) {
for (int i = 0; i < docs.count(); i++) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BlockLoader.LongBuilder builder = factory.longsFromDocValues(docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < this.docID) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -258,10 +258,10 @@ private static class SingletonInts extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BlockLoader.IntBuilder builder = factory.intsFromDocValues(docs.count())) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BlockLoader.IntBuilder builder = factory.intsFromDocValues(docs.count() - offset)) {
int lastDoc = -1;
for (int i = 0; i < docs.count(); i++) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < lastDoc) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -307,9 +307,9 @@ private static class Ints extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BlockLoader.IntBuilder builder = factory.intsFromDocValues(docs.count())) {
for (int i = 0; i < docs.count(); i++) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BlockLoader.IntBuilder builder = factory.intsFromDocValues(docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < this.docID) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -407,10 +407,10 @@ private static class SingletonDoubles extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BlockLoader.DoubleBuilder builder = factory.doublesFromDocValues(docs.count())) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BlockLoader.DoubleBuilder builder = factory.doublesFromDocValues(docs.count() - offset)) {
int lastDoc = -1;
for (int i = 0; i < docs.count(); i++) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < lastDoc) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -460,9 +460,9 @@ private static class Doubles extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BlockLoader.DoubleBuilder builder = factory.doublesFromDocValues(docs.count())) {
for (int i = 0; i < docs.count(); i++) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BlockLoader.DoubleBuilder builder = factory.doublesFromDocValues(docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < this.docID) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -541,10 +541,10 @@ private static class DenseVectorValuesBlockReader extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
// Doubles from doc values ensures that the values are in order
try (BlockLoader.FloatBuilder builder = factory.denseVectors(docs.count(), dimensions)) {
for (int i = 0; i < docs.count(); i++) {
try (BlockLoader.FloatBuilder builder = factory.denseVectors(docs.count() - offset, dimensions)) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < floatVectorValues.docID()) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -642,19 +642,19 @@ private BlockLoader.Block readSingleDoc(BlockFactory factory, int docId) throws
if (ordinals.advanceExact(docId)) {
BytesRef v = ordinals.lookupOrd(ordinals.ordValue());
// the returned BytesRef can be reused
return factory.constantBytes(BytesRef.deepCopyOf(v));
return factory.constantBytes(BytesRef.deepCopyOf(v), 1);
} else {
return factory.constantNulls();
return factory.constantNulls(1);
}
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
if (docs.count() == 1) {
return readSingleDoc(factory, docs.get(0));
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
if (docs.count() - offset == 1) {
return readSingleDoc(factory, docs.get(offset));
}
try (BlockLoader.SingletonOrdinalsBuilder builder = factory.singletonOrdinalsBuilder(ordinals, docs.count())) {
for (int i = 0; i < docs.count(); i++) {
try (var builder = factory.singletonOrdinalsBuilder(ordinals, docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < ordinals.docID()) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -697,9 +697,9 @@ private static class Ordinals extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BytesRefBuilder builder = factory.bytesRefsFromDocValues(docs.count())) {
for (int i = 0; i < docs.count(); i++) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BytesRefBuilder builder = factory.bytesRefsFromDocValues(docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < ordinals.docID()) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -777,9 +777,9 @@ private static class BytesRefsFromBinary extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BlockLoader.BytesRefBuilder builder = factory.bytesRefs(docs.count())) {
for (int i = 0; i < docs.count(); i++) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BlockLoader.BytesRefBuilder builder = factory.bytesRefs(docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < docID) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -876,9 +876,9 @@ private static class DenseVectorFromBinary extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BlockLoader.FloatBuilder builder = factory.denseVectors(docs.count(), dimensions)) {
for (int i = 0; i < docs.count(); i++) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BlockLoader.FloatBuilder builder = factory.denseVectors(docs.count() - offset, dimensions)) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < docID) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -960,10 +960,10 @@ private static class SingletonBooleans extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BlockLoader.BooleanBuilder builder = factory.booleansFromDocValues(docs.count())) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BlockLoader.BooleanBuilder builder = factory.booleansFromDocValues(docs.count() - offset)) {
int lastDoc = -1;
for (int i = 0; i < docs.count(); i++) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < lastDoc) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down Expand Up @@ -1009,9 +1009,9 @@ private static class Booleans extends BlockDocValuesReader {
}

@Override
public BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException {
try (BlockLoader.BooleanBuilder builder = factory.booleansFromDocValues(docs.count())) {
for (int i = 0; i < docs.count(); i++) {
public BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
try (BlockLoader.BooleanBuilder builder = factory.booleansFromDocValues(docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
int doc = docs.get(i);
if (doc < this.docID) {
throw new IllegalStateException("docs within same block must be in order");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ interface ColumnAtATimeReader extends Reader {
/**
* Reads the values of all documents in {@code docs}.
*/
BlockLoader.Block read(BlockFactory factory, Docs docs) throws IOException;
BlockLoader.Block read(BlockFactory factory, Docs docs, int offset) throws IOException;
}

interface RowStrideReader extends Reader {
Expand Down Expand Up @@ -149,8 +149,8 @@ public String toString() {
*/
class ConstantNullsReader implements AllReader {
@Override
public Block read(BlockFactory factory, Docs docs) throws IOException {
return factory.constantNulls();
public Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
return factory.constantNulls(docs.count() - offset);
}

@Override
Expand Down Expand Up @@ -183,8 +183,8 @@ public Builder builder(BlockFactory factory, int expectedCount) {
public ColumnAtATimeReader columnAtATimeReader(LeafReaderContext context) {
return new ColumnAtATimeReader() {
@Override
public Block read(BlockFactory factory, Docs docs) {
return factory.constantBytes(value);
public Block read(BlockFactory factory, Docs docs, int offset) {
return factory.constantBytes(value, docs.count() - offset);
}

@Override
Expand Down Expand Up @@ -261,8 +261,8 @@ public ColumnAtATimeReader columnAtATimeReader(LeafReaderContext context) throws
}
return new ColumnAtATimeReader() {
@Override
public Block read(BlockFactory factory, Docs docs) throws IOException {
return reader.read(factory, docs);
public Block read(BlockFactory factory, Docs docs, int offset) throws IOException {
return reader.read(factory, docs, offset);
}

@Override
Expand Down Expand Up @@ -408,13 +408,13 @@ interface BlockFactory {
/**
* Build a block that contains only {@code null}.
*/
Block constantNulls();
Block constantNulls(int count);

/**
* Build a block that contains {@code value} repeated
* {@code size} times.
*/
Block constantBytes(BytesRef value);
Block constantBytes(BytesRef value, int count);

/**
* Build a reader for reading keyword ordinals.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ public int docId() {
}

@Override
public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs docs) throws IOException {
public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException {
// Note that we don't emit falses before trues so we conform to the doc values contract and can use booleansFromDocValues
try (BlockLoader.BooleanBuilder builder = factory.booleans(docs.count())) {
for (int i = 0; i < docs.count(); i++) {
try (BlockLoader.BooleanBuilder builder = factory.booleans(docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
read(docs.get(i), builder);
}
return builder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ public int docId() {
}

@Override
public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs docs) throws IOException {
public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException {
// Note that we don't sort the values sort, so we can't use factory.longsFromDocValues
try (BlockLoader.LongBuilder builder = factory.longs(docs.count())) {
for (int i = 0; i < docs.count(); i++) {
try (BlockLoader.LongBuilder builder = factory.longs(docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
read(docs.get(i), builder);
}
return builder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ public int docId() {
}

@Override
public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs docs) throws IOException {
public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException {
// Note that we don't sort the values sort, so we can't use factory.doublesFromDocValues
try (BlockLoader.DoubleBuilder builder = factory.doubles(docs.count())) {
for (int i = 0; i < docs.count(); i++) {
try (BlockLoader.DoubleBuilder builder = factory.doubles(docs.count() - offset)) {
for (int i = offset; i < docs.count(); i++) {
read(docs.get(i), builder);
}
return builder.build();
Expand Down
Loading