Repository navigation
Open
Description
Line 31 in 469e4fa
| listeners: Mutex<HashMap<Arc<str>, BoxService>>, |
listener 优化说明
- 不建议直接把字段改成
Arc<Mutex<HashMap<...>>>作为性能优化。 Arc解决的是共享所有权,Mutex解决的是互斥访问;加一层Arc不会减少锁竞争,仍然整张表只有一把锁。
如果 DhttpNetwork 已经通过 Arc<DhttpNetwork> 跨线程共享,那么现在的:
listeners: Mutex<HashMap<Arc<str>, BoxService>>,已经能满足共享需求,通常不需要再写成:
// 一般不会带来性能提升
listeners: Arc<Mutex<HashMap<Arc<str>, BoxService>>>,如果确实想优化并发,按目标选择
- 只增删查监听器,且存在明显锁竞争:用
DashMap分片
use dashmap::DashMap;
pub struct DhttpNetwork {
interfaces: interfaces::Interfaces,
listeners: DashMap<Arc<str>, BoxService>,
pool: h3x::Pool<ConnectionKey, QuicTransport, Error>,
}初始化相应改为:
listeners: DashMap::new(),增删查变成:
self.listeners.insert(name.clone(), service);
let exists = self.listeners.contains_key(name);
let removed = self.listeners.remove(name);但需要注意:如果这里的 BoxService 是 tower::util::BoxService,它通常是 Send 但不一定是 Sync,直接放进 DashMap 可能遇到线程安全 trait 约束问题;而且调用 Service 往往需要 &mut self,不能简单理解为“换成分片表后调用就并发了”。
- 希望缩短整张表的持锁时间:表用
DashMap,每个监听器单独加锁
use dashmap::DashMap;
use std::sync::{Arc, Mutex};
type SharedListener = Arc<Mutex<BoxService>>;
pub struct DhttpNetwork {
interfaces: interfaces::Interfaces,
listeners: DashMap<Arc<str>, SharedListener>,
pool: h3x::Pool<ConnectionKey, QuicTransport, Error>,
}查找时只短暂持有 DashMap 的引用,克隆出 Arc 后立即释放表锁:
let listener = self
.listeners
.get(name)
.map(|entry| Arc::clone(entry.value()));随后只锁定目标监听器,不影响其他监听器的增删查。这个模式比 Arc<Mutex<HashMap<...>>> 更能细化锁粒度,但代价是每个服务多一次 Arc 分配和一层锁,是否更快需要压测验证。
异步场景的关键约束
无论用哪种方案,都不要在持有 std::sync::MutexGuard 或 DashMap 的 Ref/RefMut 时直接 .await:
let response_future = {
let listener = listener.ok_or_else(|| /* listener not found */)?;
let mut service = listener.lock().unwrap();
// 根据实际 Service 流程,这里可能还需要先 poll_ready
service.call(request)
}; // 在这里释放服务锁
let response = response_future.await?;如果确实必须跨 .await 持锁,才考虑 tokio::sync::Mutex,但它解决的是异步持锁问题,不是自动带来性能提升。
结论:如果这里的设计,仅为“跨线程操作”不必加内层 Arc;为降低 listeners 锁竞争,优先考虑 DashMap。若调用监听器时不能持有表的分片锁,则采用 DashMap<Arc<str>, Arc<Mutex<BoxService>>> 会更合适。Arc<str> 本身作为键跨线程共享没有问题,不需要再给它套 Mutex。
Metadata
Metadata
Assignees
Labels
No labels
Activity