Skip to main content

sol_parser_sdk/core/
clock.rs

1//! 高性能时钟模块
2//!
3//! 提供微秒级精度的时间戳获取,避免频繁的系统调用开销。
4//!
5//! ## 设计原理
6//!
7//! 传统方式使用 `chrono::Utc::now()` 每次都需要系统调用(微秒级开销),
8//! 高性能时钟使用单调时钟 `Instant` + 基准时间戳,将开销降低到纳秒级。
9//!
10//! ## 性能优势
11//!
12//! - **减少 90%+ 开销**: 从系统调用(1-2μs)降低到内存计算(10-50ns)
13//! - **自动校准**: 每 5 分钟自动校准一次,防止时钟漂移
14//! - **线程安全**: 使用 `OnceCell` 实现全局单例
15//!
16//! ## 使用示例
17//!
18//! ```rust
19//! use sol_parser_sdk::core::clock::{now_micros, elapsed_micros_since};
20//!
21//! // 获取当前时间戳(微秒)
22//! let start = now_micros();
23//!
24//! // ... 执行解析操作 ...
25//!
26//! // 计算耗时
27//! let elapsed = elapsed_micros_since(start);
28//! println!("解析耗时: {} μs", elapsed);
29//! ```
30
31use std::time::Instant;
32
33/// 高性能时钟管理器
34///
35/// 使用单调时钟 + 基准时间戳,避免频繁的系统调用
36#[derive(Debug)]
37pub struct HighPerformanceClock {
38    /// 基准时间点(程序启动时的单调时钟时间)
39    base_instant: Instant,
40    /// 基准时间点对应的 UTC 时间戳(微秒)
41    base_timestamp_us: i64,
42    /// 上次校准时间(用于检测是否需要重新校准)
43    last_calibration: Instant,
44    /// 校准间隔(秒)
45    calibration_interval_secs: u64,
46}
47
48impl HighPerformanceClock {
49    /// 创建新的高性能时钟(默认 5 分钟校准一次)
50    pub fn new() -> Self {
51        Self::new_with_calibration_interval(300)
52    }
53
54    /// 创建带自定义校准间隔的高性能时钟
55    ///
56    /// # 参数
57    /// - `calibration_interval_secs`: 校准间隔(秒)
58    ///
59    /// # 实现细节
60    /// 通过多次采样来减少初始化误差,选择延迟最小的样本
61    pub fn new_with_calibration_interval(calibration_interval_secs: u64) -> Self {
62        // 通过多次采样来减少初始化误差
63        let mut best_offset = i64::MAX;
64        let mut best_instant = Instant::now();
65        let mut best_timestamp = chrono::Utc::now().timestamp_micros();
66
67        // 进行 3 次采样,选择延迟最小的
68        for _ in 0..3 {
69            let instant_before = Instant::now();
70            let timestamp = chrono::Utc::now().timestamp_micros();
71            let instant_after = Instant::now();
72
73            let sample_latency = instant_after.duration_since(instant_before).as_nanos() as i64;
74
75            if sample_latency < best_offset {
76                best_offset = sample_latency;
77                best_instant = instant_before;
78                best_timestamp = timestamp;
79            }
80        }
81
82        Self {
83            base_instant: best_instant,
84            base_timestamp_us: best_timestamp,
85            last_calibration: best_instant,
86            calibration_interval_secs,
87        }
88    }
89
90    /// 获取当前时间戳(微秒)
91    ///
92    /// 使用单调时钟计算,避免系统调用
93    ///
94    /// # 性能
95    /// - 仅需 10-50ns(纳秒级)
96    /// - 相比 `chrono::Utc::now()` 快 20-100 倍
97    #[inline(always)]
98    pub fn now_micros(&self) -> i64 {
99        let elapsed = self.base_instant.elapsed();
100        self.base_timestamp_us + elapsed.as_micros() as i64
101    }
102
103    /// 获取高精度当前时间戳(微秒),在必要时进行校准
104    ///
105    /// # 校准机制
106    /// 每隔 `calibration_interval_secs` 秒自动校准一次,防止时钟漂移
107    pub fn now_micros_with_calibration(&mut self) -> i64 {
108        // 检查是否需要重新校准
109        if self.last_calibration.elapsed().as_secs() >= self.calibration_interval_secs {
110            self.recalibrate();
111        }
112        self.now_micros()
113    }
114
115    /// 重新校准时钟,减少累积漂移
116    ///
117    /// # 校准策略
118    /// - 计算预期 UTC 时间戳(基于单调时钟)
119    /// - 与实际 UTC 时间戳对比
120    /// - 如果漂移超过 1ms,重新设置基准
121    fn recalibrate(&mut self) {
122        let current_monotonic = Instant::now();
123        let current_utc = chrono::Utc::now().timestamp_micros();
124
125        // 计算预期的 UTC 时间戳(基于单调时钟)
126        let expected_utc = self.base_timestamp_us
127            + current_monotonic.duration_since(self.base_instant).as_micros() as i64;
128
129        // 计算漂移量
130        let drift_us = current_utc - expected_utc;
131
132        // 如果漂移超过 1 毫秒,进行校准
133        if drift_us.abs() > 1000 {
134            self.base_instant = current_monotonic;
135            self.base_timestamp_us = current_utc;
136        }
137
138        self.last_calibration = current_monotonic;
139    }
140
141    /// 计算从指定时间戳到现在的消耗时间(微秒)
142    ///
143    /// # 参数
144    /// - `start_timestamp_us`: 起始时间戳(微秒)
145    ///
146    /// # 返回
147    /// 消耗时间(微秒)
148    #[inline(always)]
149    pub fn elapsed_micros_since(&self, start_timestamp_us: i64) -> i64 {
150        self.now_micros() - start_timestamp_us
151    }
152
153    /// 获取高精度纳秒时间戳
154    #[inline(always)]
155    pub fn now_nanos(&self) -> i128 {
156        let elapsed = self.base_instant.elapsed();
157        (self.base_timestamp_us as i128 * 1000) + elapsed.as_nanos() as i128
158    }
159
160    /// 重置时钟(强制重新初始化)
161    pub fn reset(&mut self) {
162        *self = Self::new_with_calibration_interval(self.calibration_interval_secs);
163    }
164}
165
166impl Default for HighPerformanceClock {
167    fn default() -> Self {
168        Self::new()
169    }
170}
171
172/// 全局高性能时钟实例
173static HIGH_PERF_CLOCK: once_cell::sync::OnceCell<HighPerformanceClock> =
174    once_cell::sync::OnceCell::new();
175
176/// 获取当前时间戳(微秒)
177///
178/// 使用全局高性能时钟实例,避免系统调用开销
179///
180/// # 性能
181/// - 首次调用:初始化时钟(约 100μs)
182/// - 后续调用:仅需 10-50ns
183///
184/// # 示例
185/// ```rust
186/// use sol_parser_sdk::core::clock::now_micros;
187///
188/// let grpc_recv_us = now_micros();
189/// println!("gRPC 接收时间: {} μs", grpc_recv_us);
190/// ```
191#[inline(always)]
192pub fn now_micros() -> i64 {
193    let clock = HIGH_PERF_CLOCK.get_or_init(HighPerformanceClock::new);
194    clock.now_micros()
195}
196
197/// 计算从指定时间戳到现在的消耗时间(微秒)
198///
199/// # 参数
200/// - `start_timestamp_us`: 起始时间戳(微秒)
201///
202/// # 返回
203/// 消耗时间(微秒)
204///
205/// # 示例
206/// ```rust
207/// use sol_parser_sdk::core::clock::{now_micros, elapsed_micros_since};
208///
209/// let start = now_micros();
210/// // ... 执行解析操作 ...
211/// let tx_parser_us = elapsed_micros_since(start);
212/// println!("解析耗时: {} μs", tx_parser_us);
213/// ```
214#[inline(always)]
215pub fn elapsed_micros_since(start_timestamp_us: i64) -> i64 {
216    now_micros() - start_timestamp_us
217}
218
219/// 获取高精度纳秒时间戳
220///
221/// 用于需要纳秒级精度的场景
222#[inline(always)]
223pub fn now_nanos() -> i128 {
224    let clock = HIGH_PERF_CLOCK.get_or_init(HighPerformanceClock::new);
225    clock.now_nanos()
226}
227
228// 平台差异:Windows 使用 now_micros();Linux 使用 CLOCK_REALTIME_COARSE;其他使用 CLOCK_REALTIME
229#[inline(always)]
230pub fn now_us() -> i64 {
231    #[cfg(target_os = "windows")]
232    {
233        now_micros()
234    }
235
236    #[cfg(not(target_os = "windows"))]
237    {
238        let clock_id = {
239            #[cfg(target_os = "linux")]
240            {
241                libc::CLOCK_REALTIME_COARSE
242            }
243
244            #[cfg(not(target_os = "linux"))]
245            {
246                libc::CLOCK_REALTIME
247            }
248        };
249
250        let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 };
251        unsafe {
252            libc::clock_gettime(clock_id, &mut ts);
253        }
254        (ts.tv_sec as i64) * 1_000_000 + (ts.tv_nsec as i64) / 1_000
255    }
256}
257
258#[cfg(test)]
259mod tests {
260    use super::*;
261    use std::thread;
262    use std::time::Duration;
263
264    #[test]
265    fn test_high_performance_clock_basic() {
266        let clock = HighPerformanceClock::new();
267        let t1 = clock.now_micros();
268        thread::sleep(Duration::from_millis(10));
269        let t2 = clock.now_micros();
270
271        let elapsed = t2 - t1;
272        assert!(elapsed >= 10_000, "elapsed: {} μs", elapsed); // 至少 10ms
273        assert!(elapsed < 20_000, "elapsed: {} μs", elapsed); // 不超过 20ms
274    }
275
276    #[test]
277    fn test_elapsed_micros_since() {
278        let clock = HighPerformanceClock::new();
279        let start = clock.now_micros();
280        thread::sleep(Duration::from_millis(5));
281        let elapsed = clock.elapsed_micros_since(start);
282
283        assert!(elapsed >= 5_000, "elapsed: {} μs", elapsed);
284        assert!(elapsed < 10_000, "elapsed: {} μs", elapsed);
285    }
286
287    #[test]
288    fn test_global_clock() {
289        let t1 = now_micros();
290        thread::sleep(Duration::from_millis(1));
291        let t2 = now_micros();
292
293        assert!(t2 > t1);
294        assert!(t2 - t1 >= 1_000); // 至少 1ms
295    }
296
297    #[test]
298    fn test_elapsed_global() {
299        let start = now_micros();
300        thread::sleep(Duration::from_millis(2));
301        let elapsed = elapsed_micros_since(start);
302
303        assert!(elapsed >= 2_000, "elapsed: {} μs", elapsed);
304        assert!(elapsed < 5_000, "elapsed: {} μs", elapsed);
305    }
306
307    #[test]
308    fn test_clock_precision() {
309        let clock = HighPerformanceClock::new();
310        let mut timestamps = Vec::new();
311
312        // 快速连续获取 100 个时间戳
313        for _ in 0..100 {
314            timestamps.push(clock.now_micros());
315        }
316
317        // 验证时间戳单调递增
318        for i in 1..timestamps.len() {
319            assert!(timestamps[i] >= timestamps[i - 1], "时间戳应该单调递增");
320        }
321    }
322
323    #[test]
324    fn test_calibration() {
325        let mut clock = HighPerformanceClock::new_with_calibration_interval(0); // 立即校准
326        let t1 = clock.now_micros_with_calibration();
327        thread::sleep(Duration::from_millis(10));
328        let t2 = clock.now_micros_with_calibration();
329
330        let elapsed = t2 - t1;
331        assert!(elapsed >= 10_000, "elapsed: {} μs", elapsed);
332    }
333}