@@ -23,7 +23,7 @@ use arrow::array::{
2323use arrow:: datatypes:: { DataType , Field , Schema } ;
2424use criterion:: { Criterion , criterion_group, criterion_main} ;
2525use datafusion_expr:: function:: AccumulatorArgs ;
26- use datafusion_expr:: { Accumulator , AggregateUDFImpl } ;
26+ use datafusion_expr:: { Accumulator , AggregateUDFImpl , EmitTo } ;
2727use datafusion_functions_aggregate:: count:: Count ;
2828use datafusion_physical_expr:: expressions:: col;
2929use rand:: rngs:: StdRng ;
@@ -87,6 +87,37 @@ fn create_i16_array(n_distinct: usize) -> Int16Array {
8787 . collect ( )
8888}
8989
90+ fn create_group_indices ( num_groups : usize ) -> Vec < usize > {
91+ let mut rng = StdRng :: seed_from_u64 ( 42 ) ;
92+ ( 0 ..BATCH_SIZE )
93+ . map ( |_| rng. random_range ( 0 ..num_groups) )
94+ . collect ( )
95+ }
96+
97+ fn prepare_args ( data_type : DataType ) -> ( Arc < Schema > , AccumulatorArgs < ' static > ) {
98+ let schema = Arc :: new ( Schema :: new ( vec ! [ Field :: new( "f" , data_type, true ) ] ) ) ;
99+ let schema_leaked: & ' static Schema = Box :: leak ( Box :: new ( ( * schema) . clone ( ) ) ) ;
100+ let expr = col ( "f" , schema_leaked) . unwrap ( ) ;
101+ let expr_leaked: & ' static _ = Box :: leak ( Box :: new ( expr) ) ;
102+ let return_field: Arc < Field > = Field :: new ( "f" , DataType :: Int64 , true ) . into ( ) ;
103+ let return_field_leaked: & ' static _ = Box :: leak ( Box :: new ( return_field. clone ( ) ) ) ;
104+ let expr_field = expr_leaked. return_field ( schema_leaked) . unwrap ( ) ;
105+ let expr_field_leaked: & ' static _ = Box :: leak ( Box :: new ( expr_field) ) ;
106+
107+ let accumulator_args = AccumulatorArgs {
108+ return_field : return_field_leaked. clone ( ) ,
109+ schema : schema_leaked,
110+ expr_fields : std:: slice:: from_ref ( expr_field_leaked) ,
111+ ignore_nulls : false ,
112+ order_bys : & [ ] ,
113+ is_reversed : false ,
114+ name : "count(distinct f)" ,
115+ is_distinct : true ,
116+ exprs : std:: slice:: from_ref ( expr_leaked) ,
117+ } ;
118+ ( schema, accumulator_args)
119+ }
120+
90121fn count_distinct_benchmark ( c : & mut Criterion ) {
91122 for pct in [ 80 , 99 ] {
92123 let n_distinct = BATCH_SIZE * pct / 100 ;
@@ -150,5 +181,58 @@ fn count_distinct_benchmark(c: &mut Criterion) {
150181 } ) ;
151182}
152183
153- criterion_group ! ( benches, count_distinct_benchmark) ;
184+ fn count_distinct_groups_benchmark ( c : & mut Criterion ) {
185+ let count_fn = Count :: new ( ) ;
186+
187+ for num_groups in [ 10 , 100 , 1000 ] {
188+ let n_distinct = BATCH_SIZE * 80 / 100 ;
189+ let values = Arc :: new ( create_i64_array ( n_distinct) ) as ArrayRef ;
190+ let group_indices = create_group_indices ( num_groups) ;
191+
192+ let ( _schema, args) = prepare_args ( DataType :: Int64 ) ;
193+
194+ if count_fn. groups_accumulator_supported ( args. clone ( ) ) {
195+ c. bench_function (
196+ & format ! ( "count_distinct_groups i64 {num_groups} groups (GroupsAccumulator)" ) ,
197+ |b| {
198+ b. iter ( || {
199+ let ( _schema, args) = prepare_args ( DataType :: Int64 ) ;
200+ let mut acc = count_fn. create_groups_accumulator ( args) . unwrap ( ) ;
201+ acc. update_batch ( & [ values. clone ( ) ] , & group_indices, None , num_groups)
202+ . unwrap ( ) ;
203+ acc. evaluate ( EmitTo :: All ) . unwrap ( )
204+ } )
205+ } ,
206+ ) ;
207+ } else {
208+ c. bench_function (
209+ & format ! ( "count_distinct_groups i64 {num_groups} groups (N Accumulators)" ) ,
210+ |b| {
211+ b. iter ( || {
212+ let mut accumulators: Vec < _ > = ( 0 ..num_groups)
213+ . map ( |_| prepare_accumulator ( DataType :: Int64 ) )
214+ . collect ( ) ;
215+
216+ let arr = values. as_any ( ) . downcast_ref :: < Int64Array > ( ) . unwrap ( ) ;
217+ for ( idx, group_idx) in group_indices. iter ( ) . enumerate ( ) {
218+ if let Some ( val) = arr. value ( idx) . into ( ) {
219+ let single_val = Arc :: new ( Int64Array :: from ( vec ! [ Some ( val) ] ) ) as ArrayRef ;
220+ accumulators[ * group_idx]
221+ . update_batch ( std:: slice:: from_ref ( & single_val) )
222+ . unwrap ( ) ;
223+ }
224+ }
225+
226+ let _results: Vec < _ > = accumulators
227+ . iter_mut ( )
228+ . map ( |acc| acc. evaluate ( ) . unwrap ( ) )
229+ . collect ( ) ;
230+ } )
231+ } ,
232+ ) ;
233+ }
234+ }
235+ }
236+
237+ criterion_group ! ( benches, count_distinct_benchmark, count_distinct_groups_benchmark) ;
154238criterion_main ! ( benches) ;
0 commit comments