Skip to content

Commit 5585fad

Browse files
committed
fix: fixed MAD calculation
1 parent eea43c7 commit 5585fad

File tree

1 file changed

+27
-20
lines changed

1 file changed

+27
-20
lines changed

crates/shadowsocks-service/src/local/loadbalancing/server_stat.rs

+27-20
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub struct ServerStatData {
3434
/// Score's average
3535
pub latency_mean: f64,
3636
/// Score's median absolute deviation
37-
pub latency_mad: f64,
37+
pub latency_mad: u32,
3838
}
3939

4040
/// Statistic of a remote server
@@ -79,7 +79,7 @@ impl ServerStat {
7979
fail_rate: 1.0,
8080
latency_stdev: max_latency_stdev,
8181
latency_mean: max_server_rtt as f64,
82-
latency_mad: max_server_rtt as f64,
82+
latency_mad: max_server_rtt,
8383
},
8484
}
8585
}
@@ -91,7 +91,7 @@ impl ServerStat {
9191
// Normalize stdev
9292
// let nstdev = self.data.latency_stdev / self.max_latency_stdev;
9393
// Mormalize mad
94-
let nmad = self.data.latency_mad / self.max_server_rtt as f64;
94+
let nmad = self.data.latency_mad as f64 / self.max_server_rtt as f64;
9595

9696
const SCORE_RTT_WEIGHT: f64 = 1.0;
9797
const SCORE_FAIL_WEIGHT: f64 = 3.0;
@@ -150,9 +150,10 @@ impl ServerStat {
150150
// Error rate
151151
self.data.fail_rate = cerr as f64 / self.latency_queue.len() as f64;
152152

153+
self.data.latency_median = self.max_server_rtt;
153154
self.data.latency_stdev = self.max_latency_stdev;
154155
self.data.latency_mean = self.max_server_rtt as f64;
155-
self.data.latency_mad = self.max_server_rtt as f64;
156+
self.data.latency_mad = self.max_server_rtt;
156157

157158
if !vlat.is_empty() {
158159
vlat.sort_unstable();
@@ -170,30 +171,36 @@ impl ServerStat {
170171
let n = vlat.len() as f64;
171172

172173
// mean
173-
let mut total_lat = 0;
174-
for s in &vlat {
175-
total_lat += *s;
176-
}
174+
let total_lat: u32 = vlat.iter().sum();
177175
self.data.latency_mean = total_lat as f64 / n;
178176

179177
// STDEV
180-
let mut acc_diff = 0.0;
181-
for s in &vlat {
182-
let diff = *s as f64 - self.data.latency_mean;
183-
acc_diff += diff * diff;
184-
}
178+
let acc_mean_diff_square: f64 = vlat
179+
.iter()
180+
.map(|s| {
181+
let diff = *s as f64 - self.data.latency_mean;
182+
diff * diff
183+
})
184+
.sum();
185185
// Corrected Sample Standard Deviation
186-
self.data.latency_stdev = (acc_diff / (n - 1.0)).sqrt();
186+
self.data.latency_stdev = (acc_mean_diff_square / (n - 1.0)).sqrt();
187187

188188
// MAD
189-
let mut acc_abs_diff = 0.0;
190-
for s in &vlat {
191-
acc_abs_diff += (*s as f64 - self.data.latency_median as f64).abs();
192-
}
193-
self.data.latency_mad = acc_abs_diff / n;
189+
let mut vlat_abs_diff: Vec<u32> = vlat
190+
.iter()
191+
.map(|s| (*s as i32 - self.data.latency_median as i32).abs() as u32)
192+
.collect();
193+
vlat_abs_diff.sort_unstable();
194+
195+
let abs_diff_median_mid = vlat_abs_diff.len() / 2;
196+
self.data.latency_mad = if vlat_abs_diff.len() % 2 == 0 {
197+
(vlat_abs_diff[abs_diff_median_mid] + vlat_abs_diff[abs_diff_median_mid - 1]) / 2
198+
} else {
199+
vlat_abs_diff[abs_diff_median_mid]
200+
};
194201
} else {
195202
self.data.latency_mean = vlat[0] as f64;
196-
self.data.latency_mad = self.data.latency_mean; // mean = median in this case
203+
self.data.latency_mad = 0;
197204
}
198205
}
199206

0 commit comments

Comments
 (0)