snapview/tungstenite-rs

`connect` on Windows 10 takes a significant amount of time to connect

rster2002 opened this issue · 6 comments

Hi!

I've been working on a project that uses websockets using tungstenite. I noticed however that creating a connection using the connect function takes a lot longer on windows then when I develop on MacOS it's a lot faster.

MacOS:

$ time RUSTFLAGS=-Awarnings cargo run --release -- client sync Test-vault ws://localhost:9001
    Finished release [optimized] target(s) in 0.09s
     Running `target/release/cli client sync Test-vault 'ws://localhost:9001'`
[cli/src/main.rs:57] result = Ok(
    (),
)
RUSTFLAGS=-Awarnings cargo run --release -- client sync Test-vault   0.09s user 0.05s system 56% cpu 0.254 total

Windows:

$ time RUSTFLAGS=-Awarnings cargo run --release -- client sync Test-vault ws://localhost:9001
    Finished release [optimized] target(s) in 0.22s
     Running `target\release\cli.exe client sync Test-vault 'ws://localhost:9001'`
[cli\src\main.rs:57] result = Ok(
    (),
)

real    0m2.333s
user    0m0.000s
sys     0m0.015s

I'm using tokio-tungstenite but did test using tungstenite-rs with the same result so that's why I'm creating the issue here instead of the tokio-tungstenite repo.

Code in question:

// Imports

pub struct TungsteniteWsClient {
    sender: Sender<WsClientOutgoing>,
    receiver: Receiver<WsClientIncoming>,
}

#[async_trait]
impl WsClient<WsClientOutgoing, WsClientIncoming> for TungsteniteWsClient {
    type Err = TungsteniteWsError;

    async fn connect(addr: String) -> Result<Self, Self::Err> {
        let incoming = mpsc::channel::<WsClientIncoming>(64);
        let outgoing = mpsc::channel::<WsClientOutgoing>(64);

        let (mut stream, _) = connect_async(addr)
            .await?;

        tokio::spawn(async move {
            loop {
                tokio::select! {
                    v = stream.next() => {
                        dbg!(v);
                    }
                }
            }
        });

        Ok(Self {
            sender: outgoing.0,
            receiver: incoming.1,
        })
    }

    // Omitted
}

Not included in the code above: but I checked where the performance issue was coming from by placing some dbg!() statements around some code and I zeroed in on the connect_async call.

This might just be something that I'm doing wrong, but I'm very puzzled by the significance of the difference. Any help would be much appreciated

Oh, just noticed I didn't include version information:

MacOS:

  • cargo version: cargo 1.71.0 (cfd3bbd8f 2023-06-08)
  • MacOS: 13.4 (22F66)

Windows:

  • cargo version: cargo 1.71.0 (cfd3bbd8f 2023-06-08)
  • Edition Windows 10 Pro
    Version 22H2
    Installed on ‎31 ‎Aug ‎2022
    OS build 19045.3208
    Experience Windows Feature Experience Pack 1000.19041.1000.0

Hi,

most common causes for connection delays are slow domain name resolution and IPv4/IPv6 protocol switching. Could you please use Wireshark or something similar to check what's going on?

The common part in both tungstenite and tokio-tungstenite that you might have hit with your tests is the URL resolution and establishing a TCP connection. So either of these may have performed poorly on your machine.

That's the relevant part of the tungstenite: https://github.com/snapview/tungstenite-rs/blob/master/src/client.rs#L62
And that's how it tries to connect afterward: https://github.com/snapview/tungstenite-rs/blob/master/src/client.rs#L126

It seems like one of these went slow on your machine. What you could also try is to split the part that connects to the host and that runs WebSockets over it, it feels like it's the first one that takes more time.

Thanks for the comments! Tried running TcpStream::connect and that is also slow, so I'll look into that part. Thanks for the help!

I bet your machine is confugured to use a broken DNS server.

Well, I'm trying to connect to localhost, and connecting with postman does not have this delay, so I'm not sure if this has something to do with DNS. But then again: "it's always DNS"