One of the user of socketioxide, a socket.io implementation made with tokio-tungstenite reported a really high memory usage (around 3GB for 50K sockets) when benchmarking a basic ping/pong socket.io server.
I checked a bit and it appears that there is a big difference between 0.24 and 0.25 versions of tungstenite/tokio-tungstenite. I took the official echo example to do this and benchmarked with 10K sockets echoing messages.
Here is the repository with all the details and results: https://github.com/Totodore/tokio-tungstenite-mem-usage
Recap :
tokio-tungstenite 0.24.0
- Calls to allocation functions: 341,152 (3,694/s)
- Temporary allocations: 60,021 (17.59%, 649/s)
- Peak heap memory usage: 106.1MB
- Peak RSS: 119.6MB
- Total runtime: 1min32s
tokio-tungstenite 0.25.0
- Calls to allocation functions: 324,172 (3,064/s)
- Temporary allocations: 68,341 (21.08%, 646/s)
- Peak heap memory usage: 908MB
- Peak RSS: 936MB
- Total runtime: 1min45s
Tokio-tungstenite 0.25 eats 908MB of RAM vs 106.1MB for 0.24!
Possible causes
0.25 introduces the Bytes struct in the Message API. As it shares data directly received from the internal socket, I suspect that the cause is around this feature. According to the heaptrack trace, it comes from the FrameCodec in_buffer which seems to grows if it doesn't have enough space. But no reference to the message content is kept so the FrameCodec should not grow that much.
I also tried without echoing anything and the results are the same:
let (_write, mut read) = ws_stream.split();
while let Some(_msg) = read.try_next().await.unwrap() {}

One of the user of socketioxide, a socket.io implementation made with tokio-tungstenite reported a really high memory usage (around 3GB for 50K sockets) when benchmarking a basic ping/pong socket.io server.
I checked a bit and it appears that there is a big difference between 0.24 and 0.25 versions of tungstenite/tokio-tungstenite. I took the official echo example to do this and benchmarked with 10K sockets echoing messages.
Here is the repository with all the details and results: https://github.com/Totodore/tokio-tungstenite-mem-usage
Recap :
tokio-tungstenite 0.24.0
tokio-tungstenite 0.25.0
Tokio-tungstenite 0.25 eats 908MB of RAM vs 106.1MB for 0.24!
Possible causes
0.25 introduces the
Bytesstruct in theMessageAPI. As it shares data directly received from the internal socket, I suspect that the cause is around this feature. According to the heaptrack trace, it comes from theFrameCodecin_bufferwhich seems to grows if it doesn't have enough space. But no reference to the message content is kept so theFrameCodecshould not grow that much.I also tried without echoing anything and the results are the same: