@@ -108,20 +108,18 @@ public void aggregate(int length, AggregationResultHolder aggregationResultHolde
108108 if (blockValSet .getValueType () == DataType .BYTES ) {
109109 // Serialized TDigest
110110 byte [][] bytesValues = blockValSet .getBytesValuesSV ();
111- foldNotNull (length , blockValSet , ( TDigest ) aggregationResultHolder . getResult (), ( tDigest , from , toEx ) -> {
112- if ( tDigest != null ) {
113- for ( int i = from ; i < toEx ; i ++ ) {
114- tDigest . add ( ObjectSerDeUtils . TDIGEST_SER_DE . deserialize ( bytesValues [i ]) );
115- }
116- } else {
117- tDigest = ObjectSerDeUtils . TDIGEST_SER_DE . deserialize ( bytesValues [ 0 ]);
118- aggregationResultHolder . setValue ( tDigest );
119- for ( int i = 1 ; i < length ; i ++) {
120- tDigest . add ( ObjectSerDeUtils . TDIGEST_SER_DE . deserialize ( bytesValues [ i ])) ;
111+ foldNotNull (length , blockValSet ,
112+ ( PercentileTDigestAccumulator ) aggregationResultHolder . getResult (), ( current , from , toExclusive ) -> {
113+ if ( current == null ) {
114+ current = PercentileTDigestAccumulator . forSerializedTDigestWithMergeBuffers ( bytesValues [from ] );
115+ aggregationResultHolder . setValue ( current );
116+ }
117+ for ( int i = from ; i < toExclusive ; i ++) {
118+ current . addSerializedTDigest ( bytesValues [ i ] );
119+ }
120+ return current ;
121121 }
122- }
123- return tDigest ;
124- });
122+ );
125123 return ;
126124 }
127125
@@ -134,22 +132,17 @@ public void aggregate(int length, AggregationResultHolder aggregationResultHolde
134132
135133 protected void aggregateSV (int length , AggregationResultHolder aggregationResultHolder , BlockValSet blockValSet ) {
136134 double [] doubleValues = blockValSet .getDoubleValuesSV ();
137- TDigest tDigest = getDefaultTDigest (aggregationResultHolder , _compressionFactor );
138- forEachNotNull (length , blockValSet , (from , to ) -> {
139- for (int i = from ; i < to ; i ++) {
140- tDigest .add (doubleValues [i ]);
141- }
142- });
135+ PercentileTDigestAccumulator accumulator = getAccumulator (aggregationResultHolder , _compressionFactor );
136+ forEachNotNull (length , blockValSet , (from , to ) -> accumulator .add (doubleValues , from , to ));
143137 }
144138
145139 protected void aggregateMV (int length , AggregationResultHolder aggregationResultHolder , BlockValSet blockValSet ) {
146140 double [][] valuesArray = blockValSet .getDoubleValuesMV ();
147- TDigest tDigest = getDefaultTDigest (aggregationResultHolder , _compressionFactor );
141+ PercentileTDigestAccumulator accumulator = getAccumulator (aggregationResultHolder , _compressionFactor );
148142 forEachNotNull (length , blockValSet , (from , to ) -> {
149143 for (int i = from ; i < to ; i ++) {
150- for (double value : valuesArray [i ]) {
151- tDigest .add (value );
152- }
144+ double [] values = valuesArray [i ];
145+ accumulator .add (values , 0 , values .length );
153146 }
154147 });
155148 }
@@ -163,14 +156,9 @@ public void aggregateGroupBySV(int length, int[] groupKeyArray, GroupByResultHol
163156 byte [][] bytesValues = blockValSet .getBytesValuesSV ();
164157 forEachNotNull (length , blockValSet , (from , to ) -> {
165158 for (int i = from ; i < to ; i ++) {
166- TDigest value = ObjectSerDeUtils .TDIGEST_SER_DE .deserialize (bytesValues [i ]);
167159 int groupKey = groupKeyArray [i ];
168- TDigest tDigest = groupByResultHolder .getResult (groupKey );
169- if (tDigest != null ) {
170- tDigest .add (value );
171- } else {
172- groupByResultHolder .setValueForKey (groupKey , value );
173- }
160+ getSerializedAccumulator (groupByResultHolder , groupKey , bytesValues [i ])
161+ .addSerializedTDigest (bytesValues [i ]);
174162 }
175163 });
176164 return ;
@@ -213,17 +201,17 @@ public void aggregateGroupByMV(int length, int[][] groupKeysArray, GroupByResult
213201 if (blockValSet .getValueType () == DataType .BYTES ) {
214202 // Serialized TDigest
215203 byte [][] bytesValues = blockValSet .getBytesValuesSV ();
204+ PercentileTDigestAccumulator .SerializedTDigestInput input =
205+ new PercentileTDigestAccumulator .SerializedTDigestInput ();
216206 forEachNotNull (length , blockValSet , (from , to ) -> {
217207 for (int i = from ; i < to ; i ++) {
218- TDigest value = ObjectSerDeUtils .TDIGEST_SER_DE .deserialize (bytesValues [i ]);
219- for (int groupKey : groupKeysArray [i ]) {
220- TDigest tDigest = groupByResultHolder .getResult (groupKey );
221- if (tDigest != null ) {
222- tDigest .add (value );
223- } else {
224- // Create a new TDigest for the group
225- groupByResultHolder .setValueForKey (groupKey , ObjectSerDeUtils .TDIGEST_SER_DE .deserialize (bytesValues [i ]));
226- }
208+ int [] groupKeys = groupKeysArray [i ];
209+ if (groupKeys .length == 0 ) {
210+ continue ;
211+ }
212+ input .reset (bytesValues [i ]);
213+ for (int groupKey : groupKeys ) {
214+ getSerializedAccumulator (groupByResultHolder , groupKey , input ).addSerializedTDigest (input );
227215 }
228216 }
229217 });
@@ -268,21 +256,21 @@ protected void aggregateMVGroupByMV(int length, int[][] groupKeysArray, GroupByR
268256
269257 @ Override
270258 public TDigest extractAggregationResult (AggregationResultHolder aggregationResultHolder ) {
271- TDigest tDigest = aggregationResultHolder .getResult ();
272- if (tDigest == null ) {
259+ PercentileTDigestAccumulator accumulator = aggregationResultHolder .getResult ();
260+ if (accumulator == null ) {
273261 return TDigest .createMergingDigest (_compressionFactor );
274262 } else {
275- return tDigest ;
263+ return accumulator ;
276264 }
277265 }
278266
279267 @ Override
280268 public TDigest extractGroupByResult (GroupByResultHolder groupByResultHolder , int groupKey ) {
281- TDigest tDigest = groupByResultHolder .getResult (groupKey );
282- if (tDigest == null ) {
269+ Object result = groupByResultHolder .getResult (groupKey );
270+ if (result == null ) {
283271 return TDigest .createMergingDigest (_compressionFactor );
284272 } else {
285- return tDigest ;
273+ return ( TDigest ) result ;
286274 }
287275 }
288276
@@ -294,8 +282,15 @@ public TDigest merge(TDigest intermediateResult1, TDigest intermediateResult2) {
294282 if (intermediateResult2 .size () == 0L ) {
295283 return intermediateResult1 ;
296284 }
297- intermediateResult1 .add (intermediateResult2 );
298- return intermediateResult1 ;
285+ if (intermediateResult1 instanceof PercentileTDigestAccumulator ) {
286+ intermediateResult1 .add (intermediateResult2 );
287+ return intermediateResult1 ;
288+ }
289+ PercentileTDigestAccumulator accumulator =
290+ PercentileTDigestAccumulator .forReduction (intermediateResult1 .compression ());
291+ accumulator .add (intermediateResult1 );
292+ accumulator .add (intermediateResult2 );
293+ return accumulator ;
299294 }
300295
301296 @ Override
@@ -305,13 +300,18 @@ public ColumnDataType getIntermediateResultColumnType() {
305300
306301 @ Override
307302 public SerializedIntermediateResult serializeIntermediateResult (TDigest tDigest ) {
308- return new SerializedIntermediateResult (ObjectSerDeUtils .ObjectType .TDigest .getValue (),
309- ObjectSerDeUtils .TDIGEST_SER_DE .serialize (tDigest ));
303+ byte [] bytes ;
304+ if (tDigest instanceof PercentileTDigestAccumulator ) {
305+ bytes = ((PercentileTDigestAccumulator ) tDigest ).serialize ();
306+ } else {
307+ bytes = ObjectSerDeUtils .TDIGEST_SER_DE .serialize (tDigest );
308+ }
309+ return new SerializedIntermediateResult (ObjectSerDeUtils .ObjectType .TDigest .getValue (), bytes );
310310 }
311311
312312 @ Override
313313 public TDigest deserializeIntermediateResult (CustomObject customObject ) {
314- return ObjectSerDeUtils . TDIGEST_SER_DE . deserialize (customObject .getBuffer ());
314+ return PercentileTDigestAccumulator . forSerializedTDigest (customObject .getBuffer ());
315315 }
316316
317317 @ Override
@@ -353,6 +353,36 @@ protected static TDigest getDefaultTDigest(AggregationResultHolder aggregationRe
353353 return tDigest ;
354354 }
355355
356+ private static PercentileTDigestAccumulator getAccumulator (AggregationResultHolder aggregationResultHolder ,
357+ int compressionFactor ) {
358+ PercentileTDigestAccumulator accumulator = aggregationResultHolder .getResult ();
359+ if (accumulator == null ) {
360+ accumulator = new PercentileTDigestAccumulator (compressionFactor );
361+ aggregationResultHolder .setValue (accumulator );
362+ }
363+ return accumulator ;
364+ }
365+
366+ private static PercentileTDigestAccumulator getSerializedAccumulator (GroupByResultHolder groupByResultHolder ,
367+ int groupKey , byte [] bytes ) {
368+ PercentileTDigestAccumulator accumulator = groupByResultHolder .getResult (groupKey );
369+ if (accumulator == null ) {
370+ accumulator = PercentileTDigestAccumulator .forSerializedTDigest (bytes );
371+ groupByResultHolder .setValueForKey (groupKey , accumulator );
372+ }
373+ return accumulator ;
374+ }
375+
376+ private static PercentileTDigestAccumulator getSerializedAccumulator (GroupByResultHolder groupByResultHolder ,
377+ int groupKey , PercentileTDigestAccumulator .SerializedTDigestInput input ) {
378+ PercentileTDigestAccumulator accumulator = groupByResultHolder .getResult (groupKey );
379+ if (accumulator == null ) {
380+ accumulator = PercentileTDigestAccumulator .forSerializedTDigest (input );
381+ groupByResultHolder .setValueForKey (groupKey , accumulator );
382+ }
383+ return accumulator ;
384+ }
385+
356386 /**
357387 * Returns the TDigest for the given group key if exists, or creates a new one with default compression.
358388 *
0 commit comments