use rusty_time_core::client::SyncController;
use rusty_time_core::filter::Sample;
use rusty_time_core::{ClockCommand, DisciplineConfig};
const SESSIONS: usize = 40;
const EXCHANGES: usize = 400;
struct Lcg(u64);
impl Lcg {
fn next(&mut self) -> u64 {
self.0 = self
.0
.wrapping_mul(6_364_136_223_846_793_005)
.wrapping_add(1_442_695_040_888_963_407);
self.0 >> 33
}
fn unit(&mut self) -> f64 {
(self.next() & 0xff_ffff) as f64 / 16_777_216.0
}
fn jitter(&mut self) -> f64 {
let u = self.unit().max(1.0 / 16_777_216.0);
-u.ln()
}
}
fn fold(sum: &mut u64, v: f64) {
*sum = sum
.rotate_left(7)
.wrapping_mul(0x100_0000_01b3)
.wrapping_add(v.to_bits());
}
fn main() {
let mut cfg = DisciplineConfig::default();
let guarded = std::env::var_os("RUSTY_TIME_BENCH_MAXCHANGE").is_some();
if guarded {
cfg.max_change_s = Some(1.0e6);
cfg.max_change_start = 1;
cfg.max_change_ignore = -1;
}
let mut checksum: u64 = 0xcbf2_9ce4_8422_2325;
let mut plans: u64 = 0;
let mut steps: u64 = 0;
for session in 0..SESSIONS {
let mut lcg = Lcg(0x5eed_0000 + session as u64);
let mut controller = SyncController::new(cfg);
let mut true_offset = 0.5;
let freq_ppm = 20.0;
let mut applied_ppm = 0.0;
let mut t = 0.0f64;
let mut next_poll = 2.0f64;
for _ in 0..EXCHANGES {
t += next_poll;
true_offset -= (freq_ppm - applied_ppm) * 1e-6 * next_poll;
let d1 = 100e-6 + 10e-6 * lcg.jitter();
let d2 = 100e-6 + 10e-6 * lcg.jitter();
let sample = Sample {
t,
offset: true_offset + (d1 - d2) / 2.0,
delay: d1 + d2,
dispersion: 1e-6,
};
if let Some(ClockCommand::Slew { freq_ppm: f, .. }) = controller.poll_drain(t) {
fold(&mut checksum, f);
plans += 1;
}
let step = controller.on_sample(t, sample);
steps += 1;
applied_ppm = step.applied_ppm;
fold(&mut checksum, step.applied_ppm);
fold(&mut checksum, step.estimate_offset_s);
fold(&mut checksum, step.plan.next_poll_s);
checksum = checksum
.rotate_left(11)
.wrapping_add(step.samples_used as u64);
match step.plan.command {
ClockCommand::Step { add_seconds } => {
true_offset -= add_seconds;
checksum = checksum.rotate_left(3).wrapping_add(1);
fold(&mut checksum, add_seconds);
}
ClockCommand::Slew {
freq_ppm: f,
drain_offset,
drain_rate_ppm,
} => {
checksum = checksum.rotate_left(3).wrapping_add(2);
fold(&mut checksum, f);
fold(&mut checksum, drain_offset);
fold(&mut checksum, drain_rate_ppm);
}
}
plans += 1;
next_poll = step.plan.next_poll_s;
}
}
println!("maxchange {}", if guarded { "on" } else { "off" });
println!("sessions {SESSIONS}");
println!("steps {steps}");
println!("plans {plans}");
println!("CHECKSUM {checksum:016x}");
}