Files
sol-trade-sdk/src/common/fast_timing.rs
T
2026-03-14 18:16:55 +02:00

196 lines
5.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 🚀 快速计时模块 - 减少 Instant::now() 系统调用开销
//!
//! 使用 syscall_bypass 提供的快速时间戳避免频繁的系统调用
use crate::perf::syscall_bypass::SystemCallBypassManager;
use once_cell::sync::Lazy;
use std::time::{Duration, Instant};
/// 全局快速时间提供器
static FAST_TIMER: Lazy<FastTimer> = Lazy::new(|| FastTimer::new());
/// 快速计时器 - 减少系统调用开销
pub struct FastTimer {
bypass_manager: SystemCallBypassManager,
_base_instant: Instant,
_base_nanos: u64,
}
impl FastTimer {
fn new() -> Self {
use crate::perf::syscall_bypass::SyscallBypassConfig;
let bypass_manager = SystemCallBypassManager::new(SyscallBypassConfig::default())
.expect("Failed to create SystemCallBypassManager");
let base_instant = Instant::now();
let base_nanos = bypass_manager.fast_timestamp_nanos();
Self { bypass_manager, _base_instant: base_instant, _base_nanos: base_nanos }
}
/// 🚀 获取当前时间戳(纳秒) - 使用快速系统调用绕过
#[inline(always)]
pub fn now_nanos(&self) -> u64 {
self.bypass_manager.fast_timestamp_nanos()
}
/// 🚀 获取当前时间戳(微秒)
#[inline(always)]
pub fn now_micros(&self) -> u64 {
self.now_nanos() / 1_000
}
/// 🚀 获取当前时间戳(毫秒)
#[inline(always)]
pub fn now_millis(&self) -> u64 {
self.now_nanos() / 1_000_000
}
/// 🚀 计算从开始到现在的耗时(纳秒)
#[inline(always)]
pub fn elapsed_nanos(&self, start_nanos: u64) -> u64 {
self.now_nanos().saturating_sub(start_nanos)
}
/// 🚀 计算从开始到现在的耗时(Duration)
#[inline(always)]
pub fn elapsed_duration(&self, start_nanos: u64) -> Duration {
Duration::from_nanos(self.elapsed_nanos(start_nanos))
}
}
/// 🚀 快速获取当前时间戳(纳秒)- 全局函数
///
/// 使用 syscall_bypass 避免频繁的 clock_gettime 系统调用
#[inline(always)]
pub fn fast_now_nanos() -> u64 {
FAST_TIMER.now_nanos()
}
/// 🚀 快速获取当前时间戳(微秒)
#[inline(always)]
pub fn fast_now_micros() -> u64 {
FAST_TIMER.now_micros()
}
/// 🚀 快速获取当前时间戳(毫秒)
#[inline(always)]
pub fn fast_now_millis() -> u64 {
FAST_TIMER.now_millis()
}
/// 🚀 计算耗时(纳秒)
#[inline(always)]
pub fn fast_elapsed_nanos(start_nanos: u64) -> u64 {
FAST_TIMER.elapsed_nanos(start_nanos)
}
/// 🚀 计算耗时(Duration
#[inline(always)]
pub fn fast_elapsed(start_nanos: u64) -> Duration {
FAST_TIMER.elapsed_duration(start_nanos)
}
/// 快速计时器句柄 - 用于测量代码块耗时
pub struct FastStopwatch {
start_nanos: u64,
#[allow(dead_code)]
label: &'static str,
}
impl FastStopwatch {
/// 创建并启动计时器
#[inline(always)]
pub fn start(label: &'static str) -> Self {
Self { start_nanos: fast_now_nanos(), label }
}
/// 获取已耗时(纳秒)
#[inline(always)]
pub fn elapsed_nanos(&self) -> u64 {
fast_elapsed_nanos(self.start_nanos)
}
/// 获取已耗时(Duration
#[inline(always)]
pub fn elapsed(&self) -> Duration {
fast_elapsed(self.start_nanos)
}
/// 获取已耗时(微秒)
#[inline(always)]
pub fn elapsed_micros(&self) -> u64 {
self.elapsed_nanos() / 1_000
}
/// 获取已耗时(毫秒)
#[inline(always)]
pub fn elapsed_millis(&self) -> u64 {
self.elapsed_nanos() / 1_000_000
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fast_timing() {
let start = fast_now_nanos();
std::thread::sleep(Duration::from_millis(10));
let elapsed = fast_elapsed_nanos(start);
// 应该大约是 10ms = 10,000,000 纳秒
assert!(elapsed >= 9_000_000 && elapsed <= 12_000_000);
}
#[test]
fn test_stopwatch() {
let sw = FastStopwatch::start("test");
std::thread::sleep(Duration::from_millis(10));
let elapsed_ms = sw.elapsed_millis();
assert!(elapsed_ms >= 9 && elapsed_ms <= 12);
}
#[test]
fn test_fast_now_overhead() {
// 测试调用开销
let iterations = 10_000;
let start = Instant::now();
for _ in 0..iterations {
let _ = fast_now_nanos();
}
let total_elapsed = start.elapsed();
let avg_per_call = total_elapsed.as_nanos() / iterations;
if crate::common::sdk_log::sdk_log_enabled() {
println!("Average fast_now_nanos() call: {}ns", avg_per_call);
}
// 快速时间戳应该非常快(< 100ns per call
assert!(avg_per_call < 100);
}
#[test]
fn test_instant_now_overhead() {
// 对比标准 Instant::now() 的开销
let iterations = 10_000;
let start = Instant::now();
for _ in 0..iterations {
let _ = Instant::now();
}
let total_elapsed = start.elapsed();
let avg_per_call = total_elapsed.as_nanos() / iterations;
if crate::common::sdk_log::sdk_log_enabled() {
println!("Average Instant::now() call: {}ns", avg_per_call);
}
}
}