diff --git a/src/util/histogram.rs b/src/util/histogram.rs index 5a0145b643c2f0ea58036b1acd525ac21d1d6a7a..f5d76ca4f9d9f4a74d1a7455fa16a23b10a11c10 100644 --- a/src/util/histogram.rs +++ b/src/util/histogram.rs @@ -164,7 +164,7 @@ pub struct Histogram { max: f64, num: f64, sum: f64, - sumSquares: f64, + sum_squares: f64, buckets: [f64; K_NUM_BUCKETS] } @@ -175,7 +175,7 @@ impl Default for Histogram { max: 0.0, num: 0.0, sum: 0.0, - sumSquares: 0.0, + sum_squares: 0.0, buckets: [0.0; K_NUM_BUCKETS] } } @@ -231,7 +231,7 @@ impl Histogram { self.max = 0.0; self.num = 0.0; self.sum = 0.0; - self.sumSquares = 0.0; + self.sum_squares = 0.0; for i in 0..K_NUM_BUCKETS { self.buckets[i] = 0.0; } @@ -265,7 +265,7 @@ impl Histogram { } self.num += 1.0; self.sum += value; - self.sumSquares += value * value; + self.sum_squares += value * value; } /// 合并另一个直方图的数据到当前直方图 /// @@ -291,17 +291,17 @@ impl Histogram { } self.num += other.num; self.sum += other.sum; - self.sumSquares += other.sumSquares; + self.sum_squares += other.sum_squares; for i in 0..K_NUM_BUCKETS { self.buckets[i] += other.buckets[i]; } } - /// + /// 计算处于p%位置的值既第p百分位数 /// /// # Arguments /// - /// * `p`: + /// * `p`:百分位 /// /// returns: f64 /// @@ -311,17 +311,17 @@ impl Histogram { /// /// ``` fn percentile(&self, p :f64) -> f64 { - let threhold = self.num * ( p / 100.0); + let threshold = self.num * ( p / 100.0); let mut sum :f64 = 0.0; for i in 0..K_NUM_BUCKETS { sum += self.buckets[i]; - if sum >= threhold { - let leftPoint :f64 = if i == 0 {0.0} else {K_BUCKET_LIMIT[i - 1]}; - let rightPoint :f64 = K_BUCKET_LIMIT[i]; - let leftSum :f64 = sum - self.buckets[i]; - let rightSum :f64 = sum; - let pos :f64 = (threhold - leftSum) / (rightSum - leftSum); - let mut r :f64 = leftPoint + (rightPoint - leftPoint) * pos; + if sum >= threshold { + let left_point :f64 = if i == 0 {0.0} else {K_BUCKET_LIMIT[i - 1]}; + let right_point :f64 = K_BUCKET_LIMIT[i]; + let left_sum :f64 = sum - self.buckets[i]; + let right_sum :f64 = sum; + let pos :f64 = (threshold - left_sum) / (right_sum - left_sum); + let mut r :f64 = left_point + (right_point - left_point) * pos; if r < self.min { r = self.min; } @@ -334,11 +334,35 @@ impl Histogram { return self.max; } + /// 计算中位数 + /// + /// # Arguments + /// + /// + /// returns: f64 + /// + /// # Examples + /// + /// ``` + /// + /// ``` + #[inline] fn median(&self) -> f64 { return self.percentile(50.0); } - /// 求平均值 + /// 计算平均值 + /// + /// # Arguments + /// + /// + /// returns: f64 + /// + /// # Examples + /// + /// ``` + /// + /// ``` fn average(&self) -> f64 { if self.sum == 0.0 { return 0.0; @@ -346,11 +370,67 @@ impl Histogram { return self.sum / self.num; } + /// 计算标准偏差 + /// + /// # Arguments + /// + /// + /// returns: f64 + /// + /// # Examples + /// + /// ``` + /// + /// ``` fn standard_deviation(&self) -> f64 { if self.sum == 0.0 { return 0.0; } - let variance = (self.sumSquares * self.num - self.sum * self.sum) / (self.num * self.num); + let variance = (self.sum_squares * self.num - self.sum * self.sum) / (self.num * self.num); return variance.sqrt(); } +} + +#[test] +fn test_add() { + let mut histogram = Histogram::default(); + histogram.add(2.0); + histogram.add(20.0); + assert_eq!(2.0, histogram.num); + assert_eq!(22.0, histogram.sum); + assert_eq!(2.0, histogram.min); + assert_eq!(20.0, histogram.max); + assert_eq!(404.0, histogram.sum_squares); + assert_eq!(1.0, histogram.buckets[2]); + assert_eq!(1.0, histogram.buckets[15]); + assert_eq!(11.0, histogram.average()); + assert_eq!(2.6, histogram.percentile(30.0)); + assert_eq!(3.0, histogram.median()); + assert_eq!(11.0, histogram.average()); + assert_eq!(9.0, histogram.standard_deviation()); + print!("{}", histogram.to_string()); +} + +#[test] +fn test_merge() { + let mut histogram = Histogram::default(); + histogram.add(2.0); + let mut other = Histogram::default(); + other.add(20.0); + histogram.merge(&other); + assert_eq!(2.0, histogram.num); + assert_eq!(22.0, histogram.sum); + assert_eq!(2.0, histogram.min); + assert_eq!(20.0, histogram.max); + assert_eq!(404.0, histogram.sum_squares); + assert_eq!(1.0, histogram.buckets[2]); + assert_eq!(1.0, histogram.buckets[15]); + histogram.clear(); + assert_eq!(0.0, histogram.num); + assert_eq!(0.0, histogram.sum); + assert_eq!(1e200, histogram.min); + assert_eq!(0.0, histogram.max); + assert_eq!(0.0, histogram.sum_squares); + assert_eq!(0.0, histogram.buckets[2]); + assert_eq!(0.0, histogram.buckets[15]); } \ No newline at end of file diff --git a/src/util/histogram_test.rs b/src/util/histogram_test.rs index 50c5a58f2a17d8f16fb2c7b369b106e742570419..a4f01e76a5778a4a0688ec0b954567892c2e9d57 100644 --- a/src/util/histogram_test.rs +++ b/src/util/histogram_test.rs @@ -5,9 +5,10 @@ mod test{ #[test] fn test_add() { let mut histogram = Histogram::default(); - histogram.add(1.0); - histogram.add(0.2); - histogram.add(6.0); + histogram.add(2.0); + let mut other = Histogram::default(); + other.add(20.0); print!("{}", histogram.to_string()); + print!("{}", other.to_string()); } } diff --git a/src/util/mod.rs b/src/util/mod.rs index dab1d24d297957f4e18ca59351f54c9339b2759f..d2f931c2a86a20acfec9e7bbe14b1255a7231f66 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -29,3 +29,5 @@ pub mod histogram; mod histogram_test; mod hash; mod hash_test; +mod mutex_lock; +mod mutex_lock_test; diff --git a/src/util/mutex_lock.rs b/src/util/mutex_lock.rs new file mode 100644 index 0000000000000000000000000000000000000000..84e6d65acfc23d92adb8510dbf052674c53f70e1 --- /dev/null +++ b/src/util/mutex_lock.rs @@ -0,0 +1,75 @@ +use std::ops::Deref; +use std::sync::{Arc, LockResult, Mutex, MutexGuard, TryLockResult}; + +pub struct Lock { + lock: Arc>, +} + +/// 线程内使用的锁对象 +impl Lock { + #[inline] + fn new(t: Arc>) -> Self { + Self { + lock: t + } + } + + #[inline] + pub fn lock(&self) -> LockResult> { + self.lock.lock() + } + + #[inline] + pub fn try_lock(&self) -> TryLockResult> { + self.lock.try_lock() + } +} + +/// 互斥锁 +pub struct MutexLock { + mutex_hold: Arc>, +} + +impl MutexLock { + /// 构建互斥锁 + /// + /// # Arguments + /// + /// * `t`: 锁对象 + /// + /// returns: MutexLock + /// + /// # Examples + /// + /// ``` + /// let mutex_lock = MutexLock::new(0); + /// ``` + #[inline] + pub fn new(t: T) -> Self { + Self { + mutex_hold: Arc::new(Mutex::new(t)) + } + } + + /// 获取用于move的锁对象 + /// + /// # Arguments + /// + /// + /// returns: MutexLock + /// + /// # Examples + /// + /// ``` + /// let mutex_lock = MutexLock::new(0); + /// let lock = mutex_lock.get_lock(); + /// let handle = thread::spawn(move || { + /// let mut num = lock.lock().unwrap(); + /// *num += 1; + /// }); + /// ``` + #[inline] + pub fn get_lock(&self) -> Lock { + return Lock::new(Arc::clone(&self.mutex_hold)); + } +} diff --git a/src/util/mutex_lock_test.rs b/src/util/mutex_lock_test.rs new file mode 100644 index 0000000000000000000000000000000000000000..7273a71d7ae2bd90dbf01f4a186800a4cc51a2b4 --- /dev/null +++ b/src/util/mutex_lock_test.rs @@ -0,0 +1,27 @@ +mod test { + use std::thread; + + use crate::util::mutex_lock::MutexLock; + + #[test] + fn test() { + let mutex_lock = MutexLock::new(0); + let mut handles = vec![]; + + for _ in 0..10 { + let lock = mutex_lock.get_lock(); + let handle = thread::spawn(move || { + let mut num = lock.lock().unwrap(); + + *num += 1; + }); + handles.push(handle); + } + + for handle in handles { + handle.join().unwrap(); + } + + println!("Result: {}", mutex_lock.get_lock().lock().unwrap()); + } +} \ No newline at end of file