From 55ca9f76a06ba025a98cb297db52e21537c55d14 Mon Sep 17 00:00:00 2001 From: Armin Braun Date: Fri, 29 Mar 2024 13:54:04 +0100 Subject: [PATCH] Introduce singleton for PackedInts.NullReader of size 256 (#13232) Size 256 is very common here throguh the monotonic long values default page size. In ES we're seing many MB O(10M) of duplicate instances of this size relatively quickly. => adding a singleton for it to save some heap --- lucene/CHANGES.txt | 2 ++ .../org/apache/lucene/util/packed/PackedInts.java | 12 +++++++++++- .../apache/lucene/util/packed/PackedLongValues.java | 2 +- .../apache/lucene/util/packed/TestPackedInts.java | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index e4eb94238b64..d50e00912baf 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -62,6 +62,8 @@ Optimizations * GITHUB#13224: Use singleton for all-zeros DirectMonotonicReader.Meta (Armin Braun) +* GITHUB#13232 : Introduce singleton for PackedInts.NullReader of size 256 (Armin Braun) + Bug Fixes --------------------- diff --git a/lucene/core/src/java/org/apache/lucene/util/packed/PackedInts.java b/lucene/core/src/java/org/apache/lucene/util/packed/PackedInts.java index 468a1c50600d..702d40984b06 100644 --- a/lucene/core/src/java/org/apache/lucene/util/packed/PackedInts.java +++ b/lucene/core/src/java/org/apache/lucene/util/packed/PackedInts.java @@ -566,10 +566,20 @@ public String toString() { /** A {@link Reader} which has all its values equal to 0 (bitsPerValue = 0). */ public static final class NullReader extends Reader { + private static final NullReader DEFAULT_PACKED_LONG_VALUES_PAGE_SIZE = + new NullReader(PackedLongValues.DEFAULT_PAGE_SIZE); + private final int valueCount; + public static NullReader forCount(int valueCount) { + if (valueCount == PackedLongValues.DEFAULT_PAGE_SIZE) { + return DEFAULT_PACKED_LONG_VALUES_PAGE_SIZE; + } + return new NullReader(valueCount); + } + /** Sole constructor. */ - public NullReader(int valueCount) { + private NullReader(int valueCount) { this.valueCount = valueCount; } diff --git a/lucene/core/src/java/org/apache/lucene/util/packed/PackedLongValues.java b/lucene/core/src/java/org/apache/lucene/util/packed/PackedLongValues.java index 94abe242a32b..ae7112624340 100644 --- a/lucene/core/src/java/org/apache/lucene/util/packed/PackedLongValues.java +++ b/lucene/core/src/java/org/apache/lucene/util/packed/PackedLongValues.java @@ -276,7 +276,7 @@ void pack(long[] values, int numValues, int block, float acceptableOverheadRatio // build a new packed reader if (minValue == 0 && maxValue == 0) { - this.values[block] = new PackedInts.NullReader(numValues); + this.values[block] = PackedInts.NullReader.forCount(numValues); } else { final int bitsRequired = minValue < 0 ? 64 : PackedInts.bitsRequired(maxValue); final PackedInts.Mutable mutable = diff --git a/lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java b/lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java index 2a524a763fd9..eecdcad7779f 100644 --- a/lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java +++ b/lucene/core/src/test/org/apache/lucene/util/packed/TestPackedInts.java @@ -502,7 +502,7 @@ public void testFill() { public void testPackedIntsNull() { // must be > 10 for the bulk reads below int size = TestUtil.nextInt(random(), 11, 256); - Reader packedInts = new PackedInts.NullReader(size); + Reader packedInts = PackedInts.NullReader.forCount(size); assertEquals(0, packedInts.get(TestUtil.nextInt(random(), 0, size - 1))); long[] arr = new long[size + 10]; int r;