CMV: Rust's time handling is overengineered
This commit is contained in:
commit
050ea0c1cd
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
.idea
|
|
@ -0,0 +1,126 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.112"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||
|
||||
[[package]]
|
||||
name = "no-std-net"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bcece43b12349917e096cddfa66107277f123e6c96a5aea78711dc601a47152"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||
|
||||
[[package]]
|
||||
name = "sntp-yield"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"sntpc",
|
||||
"spin_sleep",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sntpc"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dd9ef0de174c00dfc61054e7402b8b133a03943c2c9697c497650c4d2cf52f3"
|
||||
dependencies = [
|
||||
"no-std-net",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin_sleep"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a98101bdc3833e192713c2af0b0dd2614f50d1cf1f7a97c5221b7aac052acc7"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "sntp-yield"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
spin_sleep = "1.0"
|
||||
sntpc = "0.3"
|
||||
chrono = "0.4"
|
|
@ -0,0 +1,92 @@
|
|||
use std::io::{stdout, Write};
|
||||
use sntpc::{Error, NtpContext, NtpTimestampGenerator, NtpUdpSocket, Result};
|
||||
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
use chrono::NaiveDateTime;
|
||||
use spin_sleep::LoopHelper;
|
||||
|
||||
#[derive(Copy, Clone, Default)]
|
||||
struct StdTimestampGen {
|
||||
duration: Duration,
|
||||
}
|
||||
|
||||
impl NtpTimestampGenerator for StdTimestampGen {
|
||||
fn init(&mut self) {
|
||||
self.duration = std::time::SystemTime::now()
|
||||
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn timestamp_sec(&self) -> u64 {
|
||||
self.duration.as_secs()
|
||||
}
|
||||
|
||||
fn timestamp_subsec_micros(&self) -> u32 {
|
||||
self.duration.subsec_micros()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct UdpSocketWrapper(UdpSocket);
|
||||
|
||||
impl NtpUdpSocket for UdpSocketWrapper {
|
||||
fn send_to<T: ToSocketAddrs>(
|
||||
&self,
|
||||
buf: &[u8],
|
||||
addr: T,
|
||||
) -> Result<usize> {
|
||||
match self.0.send_to(buf, addr) {
|
||||
Ok(usize) => Ok(usize),
|
||||
Err(_) => Err(Error::Network),
|
||||
}
|
||||
}
|
||||
|
||||
fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
|
||||
match self.0.recv_from(buf) {
|
||||
Ok((size, addr)) => Ok((size, addr)),
|
||||
Err(_) => Err(Error::Network),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn stable_abs_diff(a: u64, b: u64) -> u64 {
|
||||
if a < b {
|
||||
b - a
|
||||
} else {
|
||||
a - b
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Synchronizing with Google Atomic Clock...");
|
||||
let mut loop_helper = LoopHelper::builder().report_interval_s(2.0).build_with_target_rate(20);
|
||||
let mut current_fps: f64 = 0.0;
|
||||
let socket = UdpSocket::bind("0.0.0.0:0")
|
||||
.expect("Unable to crate UDP socket");
|
||||
socket.set_read_timeout(Some(Duration::from_secs(2)))
|
||||
.expect("Unable to set UDP socket read timeout");
|
||||
let sock_wrapper = UdpSocketWrapper(socket);
|
||||
let ntp_context = NtpContext::new(StdTimestampGen::default());
|
||||
|
||||
let result = sntpc::get_time("time.google.com:123", sock_wrapper, ntp_context);
|
||||
let start = SystemTime::now();
|
||||
let native_timestamp = start.duration_since(UNIX_EPOCH).unwrap().as_millis() as u64;
|
||||
match result {
|
||||
Ok(time) => {
|
||||
let timestamp = (time.seconds as u64 * 1000) + ((time.seconds_fraction as u64 * 1000) >> 32);
|
||||
println!("Roundtrip: {}us\nNTP Timestamp: {}ms\nNative timestamp: {}ms\nDelta: {}ms\nNTP Delta: {}us\n\nCurrent time:", time.roundtrip, timestamp, native_timestamp, stable_abs_diff(timestamp, native_timestamp), time.offset);
|
||||
loop {
|
||||
let frame_delta = loop_helper.loop_start();
|
||||
if let Some(fps) = loop_helper.report_rate() {
|
||||
current_fps = fps;
|
||||
}
|
||||
let formatted_time = NaiveDateTime::from_timestamp(timestamp as i64, 0).format("%Y-%m-%d %H:%M:%S");
|
||||
println!("{} @ {} fps ({}ms frametime)\r", formatted_time, current_fps, frame_delta.as_millis());
|
||||
stdout().flush().unwrap();
|
||||
loop_helper.loop_sleep();
|
||||
}
|
||||
}
|
||||
Err(err) => println!("Could not get time from the NTP server: {:?}", err),
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue