88//! # Examples
99//!
1010//! ```
11- //! use liblumen_alloc::stats::define_histogram;
12- //!
13- //! define_histogram!(10);
11+ //! use liblumen_alloc::stats::Histogram;
12+ //!
13+ //! mod stats {
14+ //! use liblumen_alloc::define_histogram;
15+ //! define_histogram!(10);
16+ //! }
1417//! # fn main() {
1518//! // Create a histogram that will spread the given range over
1619//! // the 10 buckets the `Histogram` type was defined with.
17- //! let mut histogram = Histogram::with_const_width(0, 10_000);
20+ //! let mut histogram = stats:: Histogram::with_const_width(0, 10_000);
1821//!
1922//! // Adds some samples to the histogram.
2023//! for sample in 0..100 {
5659//! // ```
5760//! # }
5861//! ```
59- #![ deny( missing_docs) ]
6062#![ deny( unsafe_code) ]
6163
6264use core:: fmt;
@@ -65,7 +67,7 @@ pub use defaults::Histogram as DefaultHistogram;
6567
6668/// This trait represents the bare minimum functionality needed
6769/// to interact with an implementation by a mutator
68- pub trait Histogram : Clone + Default + fmt:: Display {
70+ pub trait Histogram : fmt:: Display {
6971 /// Add a sample to the histogram.
7072 ///
7173 /// Fails if the sample is out of range of the histogram.
@@ -219,9 +221,36 @@ macro_rules! define_histogram {
219221 pub fn range_max( & self ) -> u64 {
220222 self . range[ Self :: LEN ]
221223 }
224+
225+ /// Return the minimum value observed so far
226+ #[ inline]
227+ pub fn min( & self ) -> u64 {
228+ self . minmax. min( ) . copied( ) . unwrap_or( 0 )
229+ }
230+
231+ /// Return the maximum value observed so far
232+ #[ inline]
233+ pub fn max( & self ) -> u64 {
234+ self . minmax. max( ) . copied( ) . unwrap_or( 0 )
235+ }
236+
237+ #[ inline]
238+ pub fn mean( & self ) -> f64 {
239+ self . stats. mean( )
240+ }
241+
242+ #[ inline]
243+ pub fn stddev( & self ) -> f64 {
244+ self . stats. stddev( )
245+ }
246+
247+ #[ inline]
248+ pub fn variance( & self ) -> f64 {
249+ self . stats. variance( )
250+ }
222251 }
223252
224- impl $crate:: stats:: histogram :: Histogram for Histogram {
253+ impl $crate:: stats:: Histogram for Histogram {
225254 /// Add a sample to the histogram.
226255 ///
227256 /// Fails if the sample is out of range of the histogram.
@@ -274,6 +303,9 @@ macro_rules! define_histogram {
274303 use core:: cmp;
275304 use core:: fmt:: Write ;
276305
306+ #[ cfg( not( test) ) ]
307+ use alloc:: string:: String ;
308+
277309 let num_samples: u64 = self . bins( ) . iter( ) . sum( ) ;
278310 writeln!( f, "# Number of samples = {}" , num_samples) ?;
279311 if num_samples == 0 {
@@ -357,71 +389,79 @@ mod defaults {
357389 // This histogram will spread all allocations across 100 buckets
358390 define_histogram ! ( 100 ) ;
359391 // Provide a default implementation which will focus on the main sizes of concern
360- impl Default for Histogram {
392+ impl Default for self :: Histogram {
361393 fn default ( ) -> Self {
362- let mut ranges = Vec :: with_capacity ( 100 ) ;
394+ use heapless:: Vec ;
395+ use heapless:: consts:: U100 ;
396+ let mut ranges = Vec :: < _ , U100 > :: new ( ) ;
363397 // Use the fibonnaci sequence up to 1TB
364398 let mut n: u64 = 1 ;
365399 let mut m: u64 = 2 ;
366- ranges. push ( m) ;
400+ ranges. push ( m) . unwrap ( ) ;
367401 for _ in 1 ..57u64 {
368402 let new_m = n + m;
369403 n = m;
370- ranges. push ( new_m) ;
404+ ranges. push ( new_m) . unwrap ( ) ;
371405 m = new_m;
372406 }
373407 // Grow by 20% afterwards
374408 for _ in 57 ..99u64 {
375409 let new_m = m + ( m as f64 * 0.2 ) . ceil ( ) as u64 ;
376- ranges. push ( new_m) ;
410+ ranges. push ( new_m) . unwrap ( ) ;
377411 m = new_m;
378412 }
379413 // Add one final range that covers the remaining address space
380- ranges. push ( u64:: max_value ( ) ) ;
381- Self :: from_ranges ( ranges. as_slice ( ) . iter ( ) . cloned ( ) ) . unwrap ( )
414+ ranges. push ( u64:: max_value ( ) ) . unwrap ( ) ;
415+ Self :: from_ranges ( ranges. iter ( ) . cloned ( ) ) . unwrap ( )
382416 }
383417 }
384418}
385419
386420#[ cfg( test) ]
387421mod tests {
388- use super :: * ;
422+ mod defaults {
423+ use crate :: define_histogram;
424+
425+ define_histogram ! ( 10 ) ;
426+ }
389427
390- define_histogram ! ( 10 ) ;
428+ use super :: Histogram ;
429+ use self :: defaults:: Histogram as DefaultHistogram ;
391430
392431 #[ test]
393- fn with_const_width_test ( ) {
394- let mut h = Histogram :: with_const_width ( 0 , 100 ) ;
432+ fn histogram_with_const_width_test ( ) {
433+ let mut h = DefaultHistogram :: with_const_width ( 0 , 100 ) ;
395434 for i in 0 ..100 {
396- h. add ( i) ;
435+ h. add ( i) . ok ( ) ;
397436 }
398437 assert_eq ! ( h. max( ) , 99 ) ;
399438 assert_eq ! ( h. min( ) , 0 ) ;
400- assert_eq ! ( h. mean( ) , 50 ) ;
401- assert_eq ! ( h. bins( ) , & [ 10 , 10 , 10 , 10 , 10 , 10 , 10 , 10 , 10 , 9 ] )
439+ assert_eq ! ( h. mean( ) , 49.5 ) ;
440+ assert_eq ! ( h. bins( ) , & [ 10 , 10 , 10 , 10 , 10 , 10 , 10 , 10 , 10 , 10 ] )
402441 }
403442
404443 #[ test]
405- fn from_ranges_test ( ) {
406- let ranges = [
407- ( 2 , 4 ) ,
408- ( 4 , 8 ) ,
409- ( 8 , 16 ) ,
410- ( 16 , 32 ) ,
411- ( 32 , 64 ) ,
412- ( 64 , 128 ) ,
413- ( 128 , 256 ) ,
414- ( 256 , 512 ) ,
415- ( 512 , 1024 ) ,
416- ( 1024 , 2048 ) ,
444+ fn histogram_from_ranges_test ( ) {
445+ let ranges: [ u64 ; 11 ] = [
446+ 2 ,
447+ 4 ,
448+ 8 ,
449+ 16 ,
450+ 32 ,
451+ 64 ,
452+ 128 ,
453+ 256 ,
454+ 512 ,
455+ 1024 ,
456+ 2048
417457 ] ;
418- let mut h = Histogram :: from_ranges ( & ranges) ;
458+ let mut h = DefaultHistogram :: from_ranges ( ranges. iter ( ) . copied ( ) ) . unwrap ( ) ;
419459 for i in 2 ..2048 {
420- h. add ( i) ;
460+ h. add ( i) . ok ( ) ;
421461 }
422462 assert_eq ! ( h. max( ) , 2047 ) ;
423463 assert_eq ! ( h. min( ) , 2 ) ;
424- assert_eq ! ( h. mean( ) , 50 ) ;
425- assert_eq ! ( h. bins( ) , & [ 10 , 10 , 10 , 10 , 10 , 10 , 10 , 10 , 10 , 9 ] )
464+ assert_eq ! ( h. mean( ) , 1024.5 ) ;
465+ assert_eq ! ( h. bins( ) , & [ 2 , 4 , 8 , 16 , 32 , 64 , 128 , 256 , 512 , 1024 ] )
426466 }
427467}
0 commit comments