hey, I'm having a hard time tuning a web server to handle incoming websocket connections as fast as possible, hopefully someone here knows what I'm doing wrong. I'm using Warp's websocket example and when I was not getting the performance I was expecting I tried to bind warp to multiple ports:
let mut futures = Vec::new();
for i in 0..30 {
let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 3030 + i);
futures.push(warp::serve(routes.clone()).bind(socket));
}
futures::future::join_all(futures).await;
When I adjusted the stress testing client to use multiple ports I got a massive speed improvement (like: opening 50k new connections in 2 seconds instead of 20), which I guess means that Warp is not doing any kind of socket multiplexing.
As I don't want to configure a load balancer in front of the app for now, I tried to recreate the same setup with a single port, but there's virtually no difference in performance:
let mut handles = Vec::new();
for i in 1..30 {
let routes_clone = routes.clone();
let tcp = TcpBuilder::new_v4().unwrap();
let listener = tcp.reuse_address(true).unwrap()
.reuse_port(true).unwrap()
.bind("0.0.0.0:3030").unwrap()
.listen(1000).unwrap();
let handle = tokio::task::spawn(async move {
let mut listener = TcpListener::from_std(listener).unwrap();
let stream = listener.incoming();
warp::serve(routes_clone.clone()).run_incoming(stream).await
});
handles.push(handle);
}
futures::future::join_all(handles).await;
What am I doing wrong? I'm guessing I should spawn those tasks handling incoming connections on different threads (ie. force them to each work in its own thread), but I'm not sure if there's a way to ensure those tasks are running on different threads. I tried also block_in_place
, but then inside the block_in_place
I still need to spawn a task, which I guess ends up on another thread anyway.