From a0e8b3f65540bc66e0e6907b039dceeac3ae617d Mon Sep 17 00:00:00 2001 From: "gesong.samuel" Date: Sat, 16 Aug 2025 07:00:25 +0800 Subject: [PATCH 1/7] init --- .../search/BlockMaxConjunctionBulkScorer.java | 10 +++++----- .../apache/lucene/search/DocAndScoreAccBuffer.java | 14 ++++++++++++++ .../apache/lucene/search/MaxScoreBulkScorer.java | 6 +++++- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java index 21f8af990b85..f701cc8703dd 100644 --- a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java @@ -23,6 +23,7 @@ import org.apache.lucene.search.Weight.DefaultBulkScorer; import org.apache.lucene.util.Bits; import org.apache.lucene.util.MathUtil; +import org.apache.lucene.util.VectorUtil; /** * BulkScorer implementation of {@link BlockMaxConjunctionScorer} that focuses on top-level @@ -172,11 +173,13 @@ private void scoreWindowScoreFirst( return; } + int maxOtherDoc = -1; for (scorers[0].nextDocsAndScores(max, acceptDocs, docAndScoreBuffer); docAndScoreBuffer.size > 0; scorers[0].nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { - docAndScoreAccBuffer.copyFrom(docAndScoreBuffer); + int idx = VectorUtil.findNextGEQ(docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size); + docAndScoreAccBuffer.copyFrom(docAndScoreBuffer, idx); for (int i = 1; i < scorers.length; ++i) { double sumOfOtherClause = sumOfOtherClauses[i]; @@ -188,6 +191,7 @@ private void scoreWindowScoreFirst( } ScorerUtil.applyRequiredClause(docAndScoreAccBuffer, iterators[i], scorables[i]); + maxOtherDoc = Math.max(iterators[i].docID(), maxOtherDoc); } for (int i = 0; i < docAndScoreAccBuffer.size; ++i) { @@ -196,10 +200,6 @@ private void scoreWindowScoreFirst( } } - int maxOtherDoc = -1; - for (int i = 1; i < iterators.length; ++i) { - maxOtherDoc = Math.max(iterators[i].docID(), maxOtherDoc); - } if (lead.docID() < maxOtherDoc) { lead.advance(maxOtherDoc); } diff --git a/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java b/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java index ed5ffbc3f9a3..69141a8e87d9 100644 --- a/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java +++ b/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java @@ -74,4 +74,18 @@ public void copyFrom(DocAndFloatFeatureBuffer buffer) { } this.size = buffer.size; } + + /** + * Copy content from the given {@link DocAndFloatFeatureBuffer}, expanding float scores to + * doubles, starting at the given index, + */ + public void copyFrom(DocAndFloatFeatureBuffer buffer, int start) { + int newSize = buffer.size - start; + growNoCopy(newSize); + System.arraycopy(buffer.docs, start, docs, 0, newSize); + for (int i = 0; i < newSize; ++i) { + scores[i] = buffer.features[i + start]; + } + this.size = newSize; + } } diff --git a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java index c723cbe00f13..71a3676bb542 100644 --- a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java @@ -22,6 +22,7 @@ import org.apache.lucene.util.Bits; import org.apache.lucene.util.FixedBitSet; import org.apache.lucene.util.MathUtil; +import org.apache.lucene.util.VectorUtil; final class MaxScoreBulkScorer extends BulkScorer { @@ -246,11 +247,13 @@ private void scoreInnerWindowAsConjunction(LeafCollector collector, Bits acceptD assert essentialQueue.size() == 1; assert lead1 == essentialQueue.top(); + int maxOtherDoc = -1; for (lead1.scorer.nextDocsAndScores(max, acceptDocs, docAndScoreBuffer); docAndScoreBuffer.size > 0; lead1.scorer.nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { - docAndScoreAccBuffer.copyFrom(docAndScoreBuffer); + int idx = VectorUtil.findNextGEQ(docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size); + docAndScoreAccBuffer.copyFrom(docAndScoreBuffer, idx); for (int i = allScorers.length - 2; i >= firstRequiredScorer; --i) { @@ -264,6 +267,7 @@ private void scoreInnerWindowAsConjunction(LeafCollector collector, Bits acceptD DisiWrapper scorer = allScorers[i]; ScorerUtil.applyRequiredClause(docAndScoreAccBuffer, scorer.iterator, scorer.scorable); + maxOtherDoc = Math.max(maxOtherDoc, scorer.iterator.docID()); } scoreNonEssentialClauses(collector, docAndScoreAccBuffer, firstRequiredScorer); From be1e03af25dd96b41d776a58688c3eea5ee138a7 Mon Sep 17 00:00:00 2001 From: "gesong.samuel" Date: Sat, 16 Aug 2025 09:00:25 +0800 Subject: [PATCH 2/7] changes & tidy & revert MaxScoreBulkScorer --- lucene/CHANGES.txt | 2 ++ .../apache/lucene/search/BlockMaxConjunctionBulkScorer.java | 3 ++- .../java/org/apache/lucene/search/MaxScoreBulkScorer.java | 6 +----- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 4fcd66db0753..1b6194f55b03 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -241,6 +241,8 @@ Optimizations * GITHUB#15004: Wraps all iterator with likelyImpactsEnum under BlockMaxConjunctionBulkScorer. (Ge Song) +* GITHUB#15081: Filter by maxOtherDoc first to reduce the overhead of filterCompetitiveHits. (Ge Song) + Changes in Runtime Behavior --------------------- * GITHUB#14823: Decrease TieredMergePolicy's default number of segments per diff --git a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java index f701cc8703dd..7e6179937dd4 100644 --- a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java @@ -178,7 +178,8 @@ private void scoreWindowScoreFirst( docAndScoreBuffer.size > 0; scorers[0].nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { - int idx = VectorUtil.findNextGEQ(docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size); + int idx = + VectorUtil.findNextGEQ(docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size); docAndScoreAccBuffer.copyFrom(docAndScoreBuffer, idx); for (int i = 1; i < scorers.length; ++i) { diff --git a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java index 71a3676bb542..c723cbe00f13 100644 --- a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java @@ -22,7 +22,6 @@ import org.apache.lucene.util.Bits; import org.apache.lucene.util.FixedBitSet; import org.apache.lucene.util.MathUtil; -import org.apache.lucene.util.VectorUtil; final class MaxScoreBulkScorer extends BulkScorer { @@ -247,13 +246,11 @@ private void scoreInnerWindowAsConjunction(LeafCollector collector, Bits acceptD assert essentialQueue.size() == 1; assert lead1 == essentialQueue.top(); - int maxOtherDoc = -1; for (lead1.scorer.nextDocsAndScores(max, acceptDocs, docAndScoreBuffer); docAndScoreBuffer.size > 0; lead1.scorer.nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { - int idx = VectorUtil.findNextGEQ(docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size); - docAndScoreAccBuffer.copyFrom(docAndScoreBuffer, idx); + docAndScoreAccBuffer.copyFrom(docAndScoreBuffer); for (int i = allScorers.length - 2; i >= firstRequiredScorer; --i) { @@ -267,7 +264,6 @@ private void scoreInnerWindowAsConjunction(LeafCollector collector, Bits acceptD DisiWrapper scorer = allScorers[i]; ScorerUtil.applyRequiredClause(docAndScoreAccBuffer, scorer.iterator, scorer.scorable); - maxOtherDoc = Math.max(maxOtherDoc, scorer.iterator.docID()); } scoreNonEssentialClauses(collector, docAndScoreAccBuffer, firstRequiredScorer); From 5cd0f01cc2675ecf09ba46fce720a066109ad905 Mon Sep 17 00:00:00 2001 From: "gesong.samuel" Date: Sat, 16 Aug 2025 09:04:21 +0800 Subject: [PATCH 3/7] refactor --- .../org/apache/lucene/search/DocAndScoreAccBuffer.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java b/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java index 69141a8e87d9..3f2b66c20662 100644 --- a/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java +++ b/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java @@ -67,12 +67,7 @@ public void grow(int minSize) { * doubles. */ public void copyFrom(DocAndFloatFeatureBuffer buffer) { - growNoCopy(buffer.size); - System.arraycopy(buffer.docs, 0, docs, 0, buffer.size); - for (int i = 0; i < buffer.size; ++i) { - scores[i] = buffer.features[i]; - } - this.size = buffer.size; + copyFrom(buffer, 0); } /** From 4fd22eba173ddb3056a43939b9d4e7c88a6c84ac Mon Sep 17 00:00:00 2001 From: "gesong.samuel" Date: Sat, 16 Aug 2025 09:33:09 +0800 Subject: [PATCH 4/7] only filter when minCompetitveScore > 0 --- .../lucene/search/BlockMaxConjunctionBulkScorer.java | 5 ++++- .../org/apache/lucene/search/MaxScoreBulkScorer.java | 10 +++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java index 7e6179937dd4..68ad540debf0 100644 --- a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java @@ -179,7 +179,10 @@ private void scoreWindowScoreFirst( scorers[0].nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { int idx = - VectorUtil.findNextGEQ(docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size); + scorable.minCompetitiveScore > 0 + ? VectorUtil.findNextGEQ( + docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size) + : 0; docAndScoreAccBuffer.copyFrom(docAndScoreBuffer, idx); for (int i = 1; i < scorers.length; ++i) { diff --git a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java index c723cbe00f13..0fb8f1f48d4e 100644 --- a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java @@ -22,6 +22,7 @@ import org.apache.lucene.util.Bits; import org.apache.lucene.util.FixedBitSet; import org.apache.lucene.util.MathUtil; +import org.apache.lucene.util.VectorUtil; final class MaxScoreBulkScorer extends BulkScorer { @@ -246,11 +247,17 @@ private void scoreInnerWindowAsConjunction(LeafCollector collector, Bits acceptD assert essentialQueue.size() == 1; assert lead1 == essentialQueue.top(); + int maxOtherDoc = -1; for (lead1.scorer.nextDocsAndScores(max, acceptDocs, docAndScoreBuffer); docAndScoreBuffer.size > 0; lead1.scorer.nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { - docAndScoreAccBuffer.copyFrom(docAndScoreBuffer); + int idx = + scorable.minCompetitiveScore > 0 + ? VectorUtil.findNextGEQ( + docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size) + : 0; + docAndScoreAccBuffer.copyFrom(docAndScoreBuffer, idx); for (int i = allScorers.length - 2; i >= firstRequiredScorer; --i) { @@ -264,6 +271,7 @@ private void scoreInnerWindowAsConjunction(LeafCollector collector, Bits acceptD DisiWrapper scorer = allScorers[i]; ScorerUtil.applyRequiredClause(docAndScoreAccBuffer, scorer.iterator, scorer.scorable); + maxOtherDoc = Math.max(maxOtherDoc, scorer.iterator.docID()); } scoreNonEssentialClauses(collector, docAndScoreAccBuffer, firstRequiredScorer); From 78a7b7937fcd8e785ec58db26e770b40c5b3b762 Mon Sep 17 00:00:00 2001 From: "gesong.samuel" Date: Sun, 17 Aug 2025 00:27:29 +0800 Subject: [PATCH 5/7] revert --- .../apache/lucene/search/BlockMaxConjunctionBulkScorer.java | 5 +---- .../java/org/apache/lucene/search/MaxScoreBulkScorer.java | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java index 68ad540debf0..7e6179937dd4 100644 --- a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java @@ -179,10 +179,7 @@ private void scoreWindowScoreFirst( scorers[0].nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { int idx = - scorable.minCompetitiveScore > 0 - ? VectorUtil.findNextGEQ( - docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size) - : 0; + VectorUtil.findNextGEQ(docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size); docAndScoreAccBuffer.copyFrom(docAndScoreBuffer, idx); for (int i = 1; i < scorers.length; ++i) { diff --git a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java index 0fb8f1f48d4e..7f21847d7aac 100644 --- a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java @@ -253,10 +253,7 @@ private void scoreInnerWindowAsConjunction(LeafCollector collector, Bits acceptD lead1.scorer.nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { int idx = - scorable.minCompetitiveScore > 0 - ? VectorUtil.findNextGEQ( - docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size) - : 0; + VectorUtil.findNextGEQ(docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size); docAndScoreAccBuffer.copyFrom(docAndScoreBuffer, idx); for (int i = allScorers.length - 2; i >= firstRequiredScorer; --i) { From 5810408740dd5913495521f6ffe1bb7e6d5cee3b Mon Sep 17 00:00:00 2001 From: "gesong.samuel" Date: Mon, 18 Aug 2025 23:24:07 +0800 Subject: [PATCH 6/7] remove findNextGEQ --- .../search/BlockMaxConjunctionBulkScorer.java | 5 +--- .../lucene/search/DocAndScoreAccBuffer.java | 28 +++++++++++-------- .../lucene/search/MaxScoreBulkScorer.java | 5 +--- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java index 7e6179937dd4..2a66428dd247 100644 --- a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java @@ -23,7 +23,6 @@ import org.apache.lucene.search.Weight.DefaultBulkScorer; import org.apache.lucene.util.Bits; import org.apache.lucene.util.MathUtil; -import org.apache.lucene.util.VectorUtil; /** * BulkScorer implementation of {@link BlockMaxConjunctionScorer} that focuses on top-level @@ -178,9 +177,7 @@ private void scoreWindowScoreFirst( docAndScoreBuffer.size > 0; scorers[0].nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { - int idx = - VectorUtil.findNextGEQ(docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size); - docAndScoreAccBuffer.copyFrom(docAndScoreBuffer, idx); + docAndScoreAccBuffer.copyWithMinDocRequired(docAndScoreBuffer, maxOtherDoc); for (int i = 1; i < scorers.length; ++i) { double sumOfOtherClause = sumOfOtherClauses[i]; diff --git a/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java b/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java index 3f2b66c20662..747ffd1ba657 100644 --- a/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java +++ b/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java @@ -67,19 +67,25 @@ public void grow(int minSize) { * doubles. */ public void copyFrom(DocAndFloatFeatureBuffer buffer) { - copyFrom(buffer, 0); + growNoCopy(buffer.size); + System.arraycopy(buffer.docs, 0, docs, 0, buffer.size); + for (int i = 0; i < buffer.size; ++i) { + scores[i] = buffer.features[i]; + } + this.size = buffer.size; } - /** - * Copy content from the given {@link DocAndFloatFeatureBuffer}, expanding float scores to - * doubles, starting at the given index, - */ - public void copyFrom(DocAndFloatFeatureBuffer buffer, int start) { - int newSize = buffer.size - start; - growNoCopy(newSize); - System.arraycopy(buffer.docs, start, docs, 0, newSize); - for (int i = 0; i < newSize; ++i) { - scores[i] = buffer.features[i + start]; + public void copyWithMinDocRequired(DocAndFloatFeatureBuffer buffer, int minDocInclusive) { + growNoCopy(buffer.size); + int newSize = 0; + for (int i = 0; i < buffer.size; ++i) { + int doc = buffer.docs[i]; + double score = buffer.features[i]; + docs[newSize] = doc; + scores[newSize] = score; + if (doc >= minDocInclusive) { + newSize++; + } } this.size = newSize; } diff --git a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java index 7f21847d7aac..2de1513b70c6 100644 --- a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java @@ -22,7 +22,6 @@ import org.apache.lucene.util.Bits; import org.apache.lucene.util.FixedBitSet; import org.apache.lucene.util.MathUtil; -import org.apache.lucene.util.VectorUtil; final class MaxScoreBulkScorer extends BulkScorer { @@ -252,9 +251,7 @@ private void scoreInnerWindowAsConjunction(LeafCollector collector, Bits acceptD docAndScoreBuffer.size > 0; lead1.scorer.nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { - int idx = - VectorUtil.findNextGEQ(docAndScoreBuffer.docs, maxOtherDoc, 0, docAndScoreBuffer.size); - docAndScoreAccBuffer.copyFrom(docAndScoreBuffer, idx); + docAndScoreAccBuffer.copyWithMinDocRequired(docAndScoreBuffer, maxOtherDoc); for (int i = allScorers.length - 2; i >= firstRequiredScorer; --i) { From 5fe0f0ab3921ca5ee32516754c76707e88720885 Mon Sep 17 00:00:00 2001 From: "gesong.samuel" Date: Wed, 20 Aug 2025 23:27:11 +0800 Subject: [PATCH 7/7] tmp --- .../lucene/search/DocAndScoreAccBuffer.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java b/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java index 747ffd1ba657..36fe7e12c990 100644 --- a/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java +++ b/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java @@ -76,16 +76,15 @@ public void copyFrom(DocAndFloatFeatureBuffer buffer) { } public void copyWithMinDocRequired(DocAndFloatFeatureBuffer buffer, int minDocInclusive) { - growNoCopy(buffer.size); - int newSize = 0; - for (int i = 0; i < buffer.size; ++i) { - int doc = buffer.docs[i]; - double score = buffer.features[i]; - docs[newSize] = doc; - scores[newSize] = score; - if (doc >= minDocInclusive) { - newSize++; - } + int i = 0; + for (; i < buffer.size && buffer.docs[i] < minDocInclusive; ++i) { + // skip entries with doc IDs below the minimum + } + int newSize = buffer.size - i; + growNoCopy(newSize); + System.arraycopy(buffer.docs, i, docs, 0, newSize); + for (int j = i; j < buffer.size; ++j) { + scores[j - i] = buffer.features[j]; } this.size = newSize; }