perf(core): use quanta::Instant for hot-path timing (#2384)

Replace std::time::Instant with quanta::Instant on per-packet, per-RPC,
and per-session paths. TSC-based, ~5ns vs ~25ns per now() call.

Reuses the existing `extern crate self as hotpath` alias so
`use hotpath::instant::Instant;` resolves to the same quanta type with
or without the hotpath feature. Leaves tokio::time::Instant and
smoltcp::time::Instant untouched.
This commit is contained in:
fanyang
2026-06-28 10:43:55 +08:00
committed by GitHub
parent be2034dd06
commit 7205517160
32 changed files with 123 additions and 80 deletions
+9 -8
View File
@@ -5,6 +5,7 @@ use std::sync::{Arc, Mutex};
use bytes::Bytes;
use dashmap::DashMap;
use guarden::defer;
use hotpath::instant::Instant;
use prost::Message;
use tokio::sync::mpsc;
use tokio::task::JoinSet;
@@ -52,7 +53,7 @@ struct InflightRequestKey {
struct InflightRequest {
sender: RpcPacketSender,
merger: PacketMerger,
start_time: std::time::Instant,
start_time: Instant,
}
impl std::fmt::Debug for InflightRequest {
@@ -65,14 +66,14 @@ impl std::fmt::Debug for InflightRequest {
}
#[derive(Debug, Clone, Default)]
pub struct PeerInfo {
pub(crate) struct PeerInfo {
pub peer_id: PeerId,
pub compression_info: RpcCompressionInfo,
pub last_active: Option<std::time::Instant>,
pub last_active: Option<Instant>,
}
type InflightRequestTable = Arc<DashMap<InflightRequestKey, InflightRequest>>;
pub type PeerInfoTable = Arc<DashMap<PeerId, PeerInfo>>;
pub(crate) type PeerInfoTable = Arc<DashMap<PeerId, PeerInfo>>;
pub struct Client {
mpsc: Mutex<MpscTunnel<Box<dyn Tunnel>>>,
@@ -123,7 +124,7 @@ impl Client {
tasks.spawn(async move {
loop {
tokio::time::sleep(std::time::Duration::from_secs(30)).await;
let now = std::time::Instant::now();
let now = Instant::now();
peer_infos.retain(|_, v| {
if let Some(last_active) = v.last_active {
return now.duration_since(last_active)
@@ -230,7 +231,7 @@ impl Client {
method: <Self::Descriptor as ServiceDescriptor>::Method,
input: bytes::Bytes,
) -> Result<bytes::Bytes> {
let start_time = std::time::Instant::now();
let start_time = Instant::now();
let transaction_id = CUR_TID.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
let (tx, mut rx) = mpsc::unbounded_channel();
let key = InflightRequestKey {
@@ -314,7 +315,7 @@ impl Client {
PeerInfo {
peer_id: self.to_peer_id,
compression_info,
last_active: Some(std::time::Instant::now()),
last_active: Some(Instant::now()),
},
);
@@ -385,7 +386,7 @@ impl Client {
self.inflight_requests.len()
}
pub fn peer_info_table(&self) -> PeerInfoTable {
pub(crate) fn peer_info_table(&self) -> PeerInfoTable {
self.peer_info.clone()
}
}
+7 -5
View File
@@ -1,5 +1,7 @@
use prost::{Message as _, length_delimiter_len};
use hotpath::instant::Instant;
use crate::{
common::{PeerId, compressor::DefaultCompressor},
proto::{
@@ -42,10 +44,10 @@ pub async fn decompress_packet(
Ok(decompressed)
}
pub struct PacketMerger {
pub(crate) struct PacketMerger {
first_piece: Option<RpcPacket>,
pieces: Vec<RpcPacket>,
last_updated: std::time::Instant,
last_updated: Instant,
}
impl Default for PacketMerger {
@@ -59,7 +61,7 @@ impl PacketMerger {
Self {
first_piece: None,
pieces: Vec::new(),
last_updated: std::time::Instant::now(),
last_updated: Instant::now(),
}
}
@@ -132,12 +134,12 @@ impl PacketMerger {
.resize(total_pieces as usize, Default::default());
self.pieces[piece_idx as usize] = rpc_packet;
self.last_updated = std::time::Instant::now();
self.last_updated = Instant::now();
Ok(self.try_merge_pieces())
}
pub fn last_updated(&self) -> std::time::Instant {
pub(crate) fn last_updated(&self) -> Instant {
self.last_updated
}
}
+2 -1
View File
@@ -5,6 +5,7 @@ use std::{
use bytes::Bytes;
use dashmap::DashMap;
use hotpath::instant::Instant;
use prost::Message;
use tokio::{task::JoinSet, time::timeout};
use tokio_stream::StreamExt;
@@ -233,7 +234,7 @@ impl Server {
}
let mut resp_msg = RpcResponse::default();
let now = std::time::Instant::now();
let now = Instant::now();
let compression_info = packet.compression_info;
let resp_bytes = Self::handle_rpc_request(packet, reg, tunnel_info).await;