From 4fabada037590ba464d4d1a3d85dc3a6fe8c055f Mon Sep 17 00:00:00 2001 From: Tian Jiang Date: Fri, 11 Sep 2026 14:04:21 +0800 Subject: [PATCH] Cache type service readers in page readers --- .../tsfile/read/reader/page/PageReader.java | 33 ++++++--- .../read/reader/page/ValuePageReader.java | 68 +++++++++++++------ 2 files changed, 69 insertions(+), 32 deletions(-) diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java index 60a877a41..cdd45c4b2 100644 --- a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java +++ b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/PageReader.java @@ -60,6 +60,11 @@ public class PageReader implements IPageReader { /** decoder for value column */ private final Decoder valueDecoder; + // Reuse type-specific readers and the deletion predicate across repeated page reads. + private PageDataValueReader batchDataValueReader; + private PageDataBlockValueReader blockValueReader; + private final LongPredicate deletePredicate = this::isDeleted; + /** decoder for time column */ private final Decoder timeDecoder; @@ -156,13 +161,20 @@ public BatchData getAllSatisfiedPageData(boolean ascending) throws IOException { uncompressDataIfNecessary(); BatchData pageData = BatchDataFactory.createBatchData(dataType, ascending, false); boolean allSatisfy = recordFilter == null || recordFilter.allSatisfy(this); - PageDataValueReader valueReader = - TypeServices.READ_PAGE_VALUE_TO_BATCHDATA_SERVICE.call(Type.fromTsDataType(dataType)); - LongPredicate isDeleted = this::isDeleted; + if (batchDataValueReader == null) { + batchDataValueReader = + TypeServices.READ_PAGE_VALUE_TO_BATCHDATA_SERVICE.call(Type.fromTsDataType(dataType)); + } while (timeDecoder.hasNext(timeBuffer)) { long timestamp = timeDecoder.readLong(timeBuffer); - valueReader.read( - valueDecoder, valueBuffer, recordFilter, pageData, timestamp, allSatisfy, isDeleted); + batchDataValueReader.read( + valueDecoder, + valueBuffer, + recordFilter, + pageData, + timestamp, + allSatisfy, + deletePredicate); } return pageData.flip(); } @@ -185,20 +197,21 @@ public TsBlock getAllSatisfiedData(LongConsumer filterRowsRecorder) throws IOExc long allFilteredRows = 0; boolean allSatisfy = recordFilter == null || recordFilter.allSatisfy(this); - PageDataBlockValueReader valueReader = - TypeServices.READ_PAGE_VALUE_TO_TSBLOCK_SERVICE.call(Type.fromTsDataType(dataType)); - LongPredicate isDeleted = this::isDeleted; + if (blockValueReader == null) { + blockValueReader = + TypeServices.READ_PAGE_VALUE_TO_TSBLOCK_SERVICE.call(Type.fromTsDataType(dataType)); + } while (timeDecoder.hasNext(timeBuffer)) { long timestamp = timeDecoder.readLong(timeBuffer); PageDataReadStatus status = - valueReader.read( + blockValueReader.read( valueDecoder, valueBuffer, recordFilter, builder, timestamp, allSatisfy, - isDeleted, + deletePredicate, paginationController); if (status == PageDataReadStatus.FILTERED) { allFilteredRows++; diff --git a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java index cd0799f3f..5151d25de 100644 --- a/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java +++ b/java/tsfile/src/main/java/org/apache/tsfile/read/reader/page/ValuePageReader.java @@ -54,6 +54,16 @@ public class ValuePageReader { /** decoder for value column */ private final Decoder valueDecoder; + // Reuse the type-specific reader across per-row nextValue calls. + private PageDataTsPrimitiveValueReader valueReader; + + // Reuse readers for batch and column-builder APIs across repeated page reads. + private PageDataValueReader batchDataValueReader; + private PageDataColumnBuilderValueReader columnBuilderValueReader; + + // Reuse the bound predicate across page reads instead of creating a method reference per call. + private final LongPredicate deletePredicate = this::isDeleted; + private byte[] bitmap; private int size; @@ -118,17 +128,18 @@ public BatchData nextBatch(long[] timeBatch, boolean ascending, Filter filter) throws IOException { uncompressDataIfNecessary(); BatchData pageData = BatchDataFactory.createBatchData(dataType, ascending, false); - PageDataValueReader valueReader = - TypeServices.READ_PAGE_VALUE_TO_BATCHDATA_SERVICE.call(Type.fromTsDataType(dataType)); + if (batchDataValueReader == null) { + batchDataValueReader = + TypeServices.READ_PAGE_VALUE_TO_BATCHDATA_SERVICE.call(Type.fromTsDataType(dataType)); + } boolean allSatisfy = filter == null; - LongPredicate isDeleted = this::isDeleted; for (int i = 0; i < timeBatch.length; i++) { if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) { continue; } long timestamp = timeBatch[i]; - valueReader.read( - valueDecoder, valueBuffer, filter, pageData, timestamp, allSatisfy, isDeleted); + batchDataValueReader.read( + valueDecoder, valueBuffer, filter, pageData, timestamp, allSatisfy, deletePredicate); } return pageData.flip(); } @@ -138,9 +149,12 @@ public TsPrimitiveType nextValue(long timestamp, int timeIndex) throws IOExcepti if (valueBuffer == null || ((bitmap[timeIndex / 8] & 0xFF) & (MASK >>> (timeIndex % 8))) == 0) { return null; } - PageDataTsPrimitiveValueReader valueReader = - TypeServices.READ_PAGE_VALUE_TO_TSPRIMITIVETYPE_SERVICE.call(Type.fromTsDataType(dataType)); - return valueReader.read(valueDecoder, valueBuffer, timestamp, this::isDeleted); + if (valueReader == null) { + valueReader = + TypeServices.READ_PAGE_VALUE_TO_TSPRIMITIVETYPE_SERVICE.call( + Type.fromTsDataType(dataType)); + } + return valueReader.read(valueDecoder, valueBuffer, timestamp, deletePredicate); } /** @@ -153,14 +167,16 @@ public TsPrimitiveType[] nextValueBatch(long[] timeBatch) throws IOException { if (valueBuffer == null) { return valueBatch; } - PageDataTsPrimitiveValueReader valueReader = - TypeServices.READ_PAGE_VALUE_TO_TSPRIMITIVETYPE_SERVICE.call(Type.fromTsDataType(dataType)); - LongPredicate isDeleted = this::isDeleted; + if (valueReader == null) { + valueReader = + TypeServices.READ_PAGE_VALUE_TO_TSPRIMITIVETYPE_SERVICE.call( + Type.fromTsDataType(dataType)); + } for (int i = 0; i < size; i++) { if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) { continue; } - valueBatch[i] = valueReader.read(valueDecoder, valueBuffer, timeBatch[i], isDeleted); + valueBatch[i] = valueReader.read(valueDecoder, valueBuffer, timeBatch[i], deletePredicate); } return valueBatch; } @@ -177,8 +193,10 @@ public void writeColumnBuilderWithNextBatch( } return; } - PageDataColumnBuilderValueReader valueReader = - TypeServices.READ_PAGE_VALUE_TO_COLUMNBUILDER_SERVICE.call(Type.fromTsDataType(dataType)); + if (columnBuilderValueReader == null) { + columnBuilderValueReader = + TypeServices.READ_PAGE_VALUE_TO_COLUMNBUILDER_SERVICE.call(Type.fromTsDataType(dataType)); + } for (int i = 0; i < readEndIndex; i++) { if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) { if (keepCurrentRow[i]) { @@ -186,7 +204,8 @@ public void writeColumnBuilderWithNextBatch( } continue; } - valueReader.read(valueDecoder, valueBuffer, columnBuilder, keepCurrentRow[i], isDeleted[i]); + columnBuilderValueReader.read( + valueDecoder, valueBuffer, columnBuilder, keepCurrentRow[i], isDeleted[i]); } } @@ -201,8 +220,10 @@ public void writeColumnBuilderWithNextBatch( } return; } - PageDataColumnBuilderValueReader valueReader = - TypeServices.READ_PAGE_VALUE_TO_COLUMNBUILDER_SERVICE.call(Type.fromTsDataType(dataType)); + if (columnBuilderValueReader == null) { + columnBuilderValueReader = + TypeServices.READ_PAGE_VALUE_TO_COLUMNBUILDER_SERVICE.call(Type.fromTsDataType(dataType)); + } for (int i = 0; i < readEndIndex; i++) { if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) { if (keepCurrentRow[i]) { @@ -210,7 +231,8 @@ public void writeColumnBuilderWithNextBatch( } continue; } - valueReader.read(valueDecoder, valueBuffer, columnBuilder, keepCurrentRow[i], false); + columnBuilderValueReader.read( + valueDecoder, valueBuffer, columnBuilder, keepCurrentRow[i], false); } } @@ -221,12 +243,14 @@ public void writeColumnBuilderWithNextBatch( columnBuilder.appendNull(readEndIndex - readStartIndex); return; } - PageDataColumnBuilderValueReader valueReader = - TypeServices.READ_PAGE_VALUE_TO_COLUMNBUILDER_SERVICE.call(Type.fromTsDataType(dataType)); + if (columnBuilderValueReader == null) { + columnBuilderValueReader = + TypeServices.READ_PAGE_VALUE_TO_COLUMNBUILDER_SERVICE.call(Type.fromTsDataType(dataType)); + } // skip useless data for (int i = 0; i < readStartIndex; i++) { if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) != 0) { - valueReader.read(valueDecoder, valueBuffer, columnBuilder, false, false); + columnBuilderValueReader.read(valueDecoder, valueBuffer, columnBuilder, false, false); } } for (int i = readStartIndex; i < readEndIndex; i++) { @@ -234,7 +258,7 @@ public void writeColumnBuilderWithNextBatch( columnBuilder.appendNull(); continue; } - valueReader.read(valueDecoder, valueBuffer, columnBuilder, true, false); + columnBuilderValueReader.read(valueDecoder, valueBuffer, columnBuilder, true, false); } }