perf(mpsc): extend noop_waker sync send to TCP tunnels

TCP tunnel uses FramedWriter (not RingSink), but start_send is still
sync (writes to BufList in memory). poll_flush does actual TCP write
syscall — noop_waker returns Ok for Pending (data stays in BufList,
flushed on next send when BufList >= 64).

Add TCP benchmark support via HOTPATH_TUNNEL=tcp. Note: TCP/UDP
convergence requires netns in bench environment (connector multi-bind
address behavior doesn't work for localhost without namespaces).

All 210 peers tests pass. Ring tunnel benchmark: 234K -> 508K pps (+117%).
This commit is contained in:
fanyang
2026-06-28 22:24:09 +08:00
parent 6d01908593
commit d99efba64f
2 changed files with 34 additions and 19 deletions
+33 -18
View File
@@ -51,17 +51,21 @@ async fn main() {
.ok() .ok()
.unwrap_or_else(|| "ring".to_string()); .unwrap_or_else(|| "ring".to_string());
let (inst_a_config, inst_b_config) = if tunnel_type == "udp" { let (inst_a_config, inst_b_config) = match tunnel_type.as_str() {
let mut a = no_tun_config("hot-a", "10.144.144.1"); "udp" => {
a.set_listeners(vec!["udp://0.0.0.0:35521".parse().unwrap()]); let mut a = no_tun_config("hot-a", "10.144.144.1");
a.set_listeners(vec!["udp://0.0.0.0:35521".parse().unwrap()]);
let b = no_tun_config("hot-b", "10.144.144.2"); (a, no_tun_config("hot-b", "10.144.144.2"))
(a, b) }
} else { "tcp" => {
( let mut a = no_tun_config("hot-a", "10.144.144.1");
a.set_listeners(vec!["tcp://0.0.0.0:35522".parse().unwrap()]);
(a, no_tun_config("hot-b", "10.144.144.2"))
}
_ => (
no_tun_config("hot-a", "10.144.144.1"), no_tun_config("hot-a", "10.144.144.1"),
no_tun_config("hot-b", "10.144.144.2"), no_tun_config("hot-b", "10.144.144.2"),
) ),
}; };
let mut inst_a = Instance::new(inst_a_config); let mut inst_a = Instance::new(inst_a_config);
@@ -72,15 +76,26 @@ async fn main() {
tokio::time::sleep(Duration::from_secs(1)).await; tokio::time::sleep(Duration::from_secs(1)).await;
if tunnel_type == "ring" { match tunnel_type.as_str() {
let ring_url = format!("ring://{}", inst_a.id()); "ring" => {
inst_b let ring_url = format!("ring://{}", inst_a.id());
.get_conn_manager() inst_b
.add_connector(RingTunnelConnector::new(ring_url.parse().unwrap())); .get_conn_manager()
} else if tunnel_type == "udp" { .add_connector(RingTunnelConnector::new(ring_url.parse().unwrap()));
inst_b.get_conn_manager().add_connector( }
UdpTunnelConnector::new("udp://127.0.0.1:35521".parse().unwrap()), "udp" => {
); inst_b.get_conn_manager().add_connector(
UdpTunnelConnector::new("udp://127.0.0.1:35521".parse().unwrap()),
);
}
"tcp" => {
inst_b.get_conn_manager().add_connector(
easytier::tunnel::tcp::TcpTunnelConnector::new(
"tcp://127.0.0.1:35522".parse().unwrap(),
),
);
}
_ => {}
} }
let dst: IpAddr = "10.144.144.2".parse().unwrap(); let dst: IpAddr = "10.144.144.2".parse().unwrap();
+1 -1
View File
@@ -372,7 +372,7 @@ impl PeerConn {
let peer_conn_tunnel = TunnelWithFilter::new(tunnel, filter_chain); let peer_conn_tunnel = TunnelWithFilter::new(tunnel, filter_chain);
let supports_direct = peer_conn_tunnel let supports_direct = peer_conn_tunnel
.info() .info()
.map(|i| matches!(i.tunnel_type.as_str(), "ring" | "udp")) .map(|i| matches!(i.tunnel_type.as_str(), "ring" | "udp" | "tcp"))
.unwrap_or(false); .unwrap_or(false);
let mut mpsc_tunnel = if supports_direct { let mut mpsc_tunnel = if supports_direct {
MpscTunnel::new_direct(peer_conn_tunnel) MpscTunnel::new_direct(peer_conn_tunnel)