@@ -7,9 +7,10 @@ use std::collections::HashMap;
77
88#[ cfg( test) ]
99use ordered_float:: OrderedFloat ;
10+ use serde:: { Deserialize , Serialize } ;
1011#[ cfg( test) ]
1112use std:: collections:: HashSet ;
12- use serde :: { Deserialize , Serialize } ;
13+ use std :: num :: NonZeroU32 ;
1314
1415#[ cfg( test) ]
1516extern crate quickcheck;
@@ -57,9 +58,13 @@ impl PartialOrd for SketchHashKey {
5758/// `UDDSketchMetadata` was created to avoid passing along many parameters
5859/// to function calls.
5960pub struct UDDSketchMetadata {
60- pub max_buckets : u32 ,
61+ // `max_buckets` is limited to `PostgreSQL`'s limit: At most 1GB per column.
62+ // As we need 24 bytes to represent any bucket, there are at most something like
63+ // 44 million values possible. It can however never be actually zero.
64+ pub max_buckets : NonZeroU32 ,
6165 pub current_error : f64 ,
62- pub compactions : u32 ,
66+ // Compactions are limited to at most 65
67+ pub compactions : u8 ,
6368 pub values : u64 ,
6469 pub sum : f64 ,
6570}
@@ -259,14 +264,14 @@ pub struct UDDSketch {
259264 buckets : SketchHashMap ,
260265 alpha : f64 ,
261266 gamma : f64 ,
262- compactions : u32 , // should always be smaller than 64
263- max_buckets : u64 ,
267+ compactions : u8 , // should always be smaller than 64
268+ max_buckets : NonZeroU32 , // PostgreSQL limit is 1GB per column, which is roughly 44 million buckets
264269 num_values : u64 ,
265270 values_sum : f64 ,
266271}
267272
268273impl UDDSketch {
269- pub fn new ( max_buckets : u64 , initial_error : f64 ) -> Self {
274+ pub fn new ( max_buckets : NonZeroU32 , initial_error : f64 ) -> Self {
270275 assert ! ( ( 1e-12 ..1.0 ) . contains( & initial_error) ) ;
271276 UDDSketch {
272277 buckets : SketchHashMap :: new ( ) ,
@@ -290,7 +295,7 @@ impl UDDSketch {
290295 alpha : metadata. current_error ,
291296 gamma : gamma ( metadata. current_error ) ,
292297 compactions : metadata. compactions ,
293- max_buckets : metadata. max_buckets as u64 ,
298+ max_buckets : metadata. max_buckets ,
294299 num_values : metadata. values ,
295300 values_sum : metadata. sum ,
296301 } ;
@@ -343,7 +348,7 @@ impl UDDSketch {
343348 pub fn add_value ( & mut self , value : f64 ) {
344349 self . buckets . increment ( self . key ( value) ) ;
345350
346- while self . buckets . len ( ) > self . max_buckets as usize {
351+ while self . buckets . len ( ) > self . max_buckets . get ( ) as usize {
347352 self . compact_buckets ( ) ;
348353 }
349354
@@ -370,7 +375,7 @@ impl UDDSketch {
370375 . abs( )
371376 < 1e-9 // f64::EPSILON too small, see issue #396
372377 ) ;
373- debug_assert_eq ! ( self . max_buckets, other. max_buckets as u64 ) ;
378+ debug_assert_eq ! ( self . max_buckets, other. max_buckets) ;
374379
375380 if other. values == 0 {
376381 return ;
@@ -389,7 +394,7 @@ impl UDDSketch {
389394 self . buckets . entry_upsert ( key, count) ;
390395 }
391396
392- while self . buckets . len ( ) > self . max_buckets as usize {
397+ while self . buckets . len ( ) > self . max_buckets . get ( ) as usize {
393398 self . compact_buckets ( ) ;
394399 }
395400
@@ -433,19 +438,19 @@ impl UDDSketch {
433438 self . buckets . entry_upsert ( key, value) ;
434439 }
435440
436- while self . buckets . len ( ) > self . max_buckets as usize {
441+ while self . buckets . len ( ) > self . max_buckets . get ( ) as usize {
437442 self . compact_buckets ( ) ;
438443 }
439444
440445 self . num_values += other. num_values ;
441446 self . values_sum += other. values_sum ;
442447 }
443448
444- pub fn max_allowed_buckets ( & self ) -> u64 {
445- self . max_buckets
449+ pub fn max_allowed_buckets ( & self ) -> u32 {
450+ self . max_buckets . get ( )
446451 }
447452
448- pub fn times_compacted ( & self ) -> u32 {
453+ pub fn times_compacted ( & self ) -> u8 {
449454 self . compactions
450455 }
451456
@@ -591,7 +596,7 @@ mod tests {
591596
592597 #[ test]
593598 fn build_and_add_values ( ) {
594- let mut sketch = UDDSketch :: new ( 20 , 0.1 ) ;
599+ let mut sketch = UDDSketch :: new ( NonZeroU32 :: new ( 20 ) . unwrap ( ) , 0.1 ) ;
595600 sketch. add_value ( 1.0 ) ;
596601 sketch. add_value ( 3.0 ) ;
597602 sketch. add_value ( 0.5 ) ;
@@ -603,7 +608,7 @@ mod tests {
603608
604609 #[ test]
605610 fn exceed_buckets ( ) {
606- let mut sketch = UDDSketch :: new ( 20 , 0.1 ) ;
611+ let mut sketch = UDDSketch :: new ( NonZeroU32 :: new ( 20 ) . unwrap ( ) , 0.1 ) ;
607612 sketch. add_value ( 1.1 ) ; // Bucket #1
608613 sketch. add_value ( 400.0 ) ; // Bucket #30
609614 let a2 = 0.2 / 1.01 ;
@@ -641,7 +646,7 @@ mod tests {
641646 }
642647
643648 let metadata = UDDSketchMetadata {
644- max_buckets : other. max_buckets as u32 ,
649+ max_buckets : other. max_buckets ,
645650 current_error : other. alpha ,
646651 compactions : other. compactions ,
647652 values : other. num_values ,
@@ -662,7 +667,7 @@ mod tests {
662667 let a4 = 2.0 * a3 / ( 1.0 + f64:: powi ( a3, 2 ) ) ; // alpha for 3 compactions
663668 let a5 = 2.0 * a4 / ( 1.0 + f64:: powi ( a4, 2 ) ) ; // alpha for 4 compactions
664669
665- let mut sketch1 = UDDSketch :: new ( 20 , 0.1 ) ;
670+ let mut sketch1 = UDDSketch :: new ( NonZeroU32 :: new ( 20 ) . unwrap ( ) , 0.1 ) ;
666671 sketch1. add_value ( 1.1 ) ; // Bucket #1
667672 sketch1. add_value ( 1.5 ) ; // Bucket #3
668673 sketch1. add_value ( 1.6 ) ; // Bucket #3
@@ -672,7 +677,7 @@ mod tests {
672677 assert_eq ! ( sketch1. count( ) , 5 ) ;
673678 assert_eq ! ( sketch1. max_error( ) , a1) ;
674679
675- let mut sketch2 = UDDSketch :: new ( 20 , 0.1 ) ;
680+ let mut sketch2 = UDDSketch :: new ( NonZeroU32 :: new ( 20 ) . unwrap ( ) , 0.1 ) ;
676681 sketch2. add_value ( 5.1 ) ; // Bucket #9
677682 sketch2. add_value ( 7.5 ) ; // Bucket #11
678683 sketch2. add_value ( 10.6 ) ; // Bucket #12
@@ -685,7 +690,7 @@ mod tests {
685690 assert_eq ! ( sketch1. count( ) , 10 ) ;
686691 assert_eq ! ( sketch1. max_error( ) , a1) ;
687692
688- let mut sketch3 = UDDSketch :: new ( 20 , 0.1 ) ;
693+ let mut sketch3 = UDDSketch :: new ( NonZeroU32 :: new ( 20 ) . unwrap ( ) , 0.1 ) ;
689694 sketch3. add_value ( 0.8 ) ; // Bucket #-1
690695 sketch3. add_value ( 3.7 ) ; // Bucket #7
691696 sketch3. add_value ( 15.2 ) ; // Bucket #14
@@ -698,7 +703,7 @@ mod tests {
698703 assert_eq ! ( sketch1. count( ) , 15 ) ;
699704 assert_eq ! ( sketch1. max_error( ) , a1) ;
700705
701- let mut sketch4 = UDDSketch :: new ( 20 , 0.1 ) ;
706+ let mut sketch4 = UDDSketch :: new ( NonZeroU32 :: new ( 20 ) . unwrap ( ) , 0.1 ) ;
702707 sketch4. add_value ( 400.0 ) ; // Bucket #30
703708 sketch4. add_value ( 0.004 ) ; // Bucket #-27
704709 sketch4. add_value ( 0.0 ) ; // Zero Bucket
@@ -716,7 +721,7 @@ mod tests {
716721 assert_eq ! ( sketch1. count( ) , 24 ) ;
717722 assert_eq ! ( sketch1. max_error( ) , a2) ;
718723
719- let mut sketch5 = UDDSketch :: new ( 20 , 0.1 ) ;
724+ let mut sketch5 = UDDSketch :: new ( NonZeroU32 :: new ( 20 ) . unwrap ( ) , 0.1 ) ;
720725 for i in 100 ..220 {
721726 sketch5. add_value ( 1.23_f64 . powi ( i) ) ;
722727 }
@@ -731,7 +736,7 @@ mod tests {
731736
732737 #[ test]
733738 fn test_quantile_and_value_estimates ( ) {
734- let mut sketch = UDDSketch :: new ( 50 , 0.1 ) ;
739+ let mut sketch = UDDSketch :: new ( NonZeroU32 :: new ( 50 ) . unwrap ( ) , 0.1 ) ;
735740 for v in 1 ..=10000 {
736741 sketch. add_value ( v as f64 / 100.0 ) ;
737742 }
@@ -771,7 +776,7 @@ mod tests {
771776
772777 #[ test]
773778 fn test_extreme_quantile_at_value ( ) {
774- let mut sketch = UDDSketch :: new ( 50 , 0.1 ) ;
779+ let mut sketch = UDDSketch :: new ( NonZeroU32 :: new ( 50 ) . unwrap ( ) , 0.1 ) ;
775780 for v in 1 ..=10000 {
776781 sketch. add_value ( v as f64 / 100.0 ) ;
777782 }
@@ -786,7 +791,7 @@ mod tests {
786791
787792 #[ test]
788793 fn random_stress ( ) {
789- let mut sketch = UDDSketch :: new ( 1000 , 0.01 ) ;
794+ let mut sketch = UDDSketch :: new ( NonZeroU32 :: new ( 1000 ) . unwrap ( ) , 0.01 ) ;
790795 let seed = rand:: thread_rng ( ) . gen ( ) ;
791796 let mut rng = rand:: rngs:: StdRng :: seed_from_u64 ( seed) ;
792797 let mut bounds = Vec :: new ( ) ;
@@ -917,7 +922,7 @@ mod tests {
917922 if master. len ( ) < 100 {
918923 return TestResult :: discard ( ) ;
919924 }
920- let mut sketch = UDDSketch :: new ( 100 , 0.000001 ) ;
925+ let mut sketch = UDDSketch :: new ( NonZeroU32 :: new ( 100 ) . unwrap ( ) , 0.000001 ) ;
921926 for value in & master {
922927 sketch. add_value ( * value) ;
923928 }
0 commit comments