latency when calling read() for server-initiated stream

141 views
Skip to first unread message

Tanjin

unread,
Dec 28, 2020, 3:30:18 AM12/28/20
to web-transport-dev
Hi Everyone,

I am a newbie to web development and WebTransport. May I ask a question which might be stupid? I am learning to use WebTransport from this sample https://github.com/GoogleChrome/samples/tree/gh-pages/webtransport. When I send a datagram from the client side (WebTransport), the client can receive the reply from the server (aioquic) immediately, which is the length of the data in this sample. However, when I try to send a datagram from the server side directly, it takes 5~10 seconds for the client to receive the data. In both cases, I used connection.send_datagram_frame(message) on the server side and var reader = transport.datagramReadable.getReader(); await reader.read() on the client side, just the same as the sample. May I ask why such a delay of 5~10 seconds happens?

I used localhost in the test so I think it is not due to network problem. I also tried UnidirectionalStream and had the same problem. I'd like to develop a real-time communication web app so I wish to avoid this delay.

Best,
Tanjin

 

guest271314

unread,
Dec 28, 2020, 9:23:28 AM12/28/20
to web-transport-dev, Tanjin

>  May I ask why such a delay of 5~10 seconds happens?

> I also tried UnidirectionalStream and had the same problem. 

How do you measure 5-10 seconds? 

Victor Vasiliev

unread,
Dec 28, 2020, 4:18:26 PM12/28/20
to Tanjin, web-transport-dev
The most likely cause here is that the server needs some kind of explicit "flush" call in its API (this is often required for streams so that multiple small writes on different streams can be coalesced into a single packet).  I believe it's "self.protocol.transmit()" in aioquic.

If you want to see if the data was actually received by the Chromium network stack, you could export the debug log following the instructions at https://www.chromium.org/for-testers/providing-network-details.

--
You received this message because you are subscribed to the Google Groups "web-transport-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to web-transport-...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/web-transport-dev/46c9e441-8fa7-48d6-bfb0-5df157c62623n%40chromium.org.

Tanjin

unread,
Dec 28, 2020, 10:37:47 PM12/28/20
to web-transport-dev, guest...@gmail.com
I output the time when I call connection.send_datagram_frame(message) on the server side and when I call await reader.read() on the client side. Then I calculate the time difference, which is typically 5~10 seconds. Victor's reply solved my problem. I need to call self.protocol.transmit() after send_datagram_frame() if I want to send the message immediately instead of buffering it in a stream. Thank both of you for the quick and instructive response!

Tanjin

unread,
Dec 28, 2020, 10:42:41 PM12/28/20
to web-transport-dev, Victor Vasiliev, web-transport-dev, Tanjin
Hi Victor, indeed! You've solved my problem! Yes, everything works as expected after I call self.protocol.transmit() following your suggestion. Thank you so much for the quick reply and accurate diagnosis!

guest271314

unread,
Nov 21, 2021, 10:43:53 AM11/21/21
to web-transport-dev, Tanjin, Victor Vasiliev, web-transport-dev
Where did you call self.protocol.transmit()? I am trying to live-stream to Chromium yet have not been able to do so.

Tanjin He

unread,
Nov 30, 2021, 2:31:37 AM11/30/21
to guest271314, web-transport-dev, Victor Vasiliev
Hello! If I have a = Protocol(). Every time after I call a.handler.send_message(), I call a.transmit(). An example of a.handler is QuicClientHandler() in my code. Hope this helps!

Jukka Jylänki

unread,
Jan 20, 2022, 11:57:43 AM1/20/22
to web-transport-dev, Tanjin, web-transport-dev, Victor Vasiliev, guest...@gmail.com
Thanks for building this thread - this was a life saver. I'd imagine that most applications that are looking to send datagrams will care about low latency - so much that it would probably make sense to expose the use of the .transmit() function in the WebTransport sample code.

I am experimenting with a real time low latency gaming scenario, sending datagrams to synchronize game actor/object positions, and the .transmit() functionality on the python server sure came in handy.

guest271314

unread,
Jan 20, 2022, 8:13:36 PM1/20/22
to web-transport-dev, juk...@unity3d.com, Tanjin, web-transport-dev, Victor Vasiliev, guest271314
Do you have an example of successfully streaming with WebTransport?

Jukka Jylänki

unread,
Jan 21, 2022, 3:39:35 AM1/21/22
to guest271314, web-transport-dev, Tanjin, Victor Vasiliev
Sorry, if I understand your ask correctly, unfortunately my test does not create WebTransport streams (no SendStream/ReceiveStream usage), but it sends a continuous "stream" of datagrams bidirectionally back and forth - basically I am following this use case/example in the spec: https://w3c.github.io/webtransport/#example-fixed-rate

guest271314

unread,
Jan 21, 2022, 7:56:33 AM1/21/22
to Jukka Jylänki, web-transport-dev, Tanjin, Victor Vasiliev
A continuous stream of datagrams to the client would suffice for my use case. Every time I tried to send an indefinite datagram stream the server and browser errors https://github.com/guest271314/samples-1/tree/guest271314-trying-to-stream-1/webtransport, https://github.com/guest271314/samples-1/tree/guest271314-trying-to-stream-2/webtransport. Can you link to the code you are using?

Jukka Jylänki

unread,
Jan 24, 2022, 12:28:58 PM1/24/22
to guest271314, web-transport-dev, Tanjin, Victor Vasiliev
I have now uploaded my experiment over to https://github.com/juj/last_frontier . You can find the server code there in files game_server.py and webtransport.py, and the client code in file site/index.html.

Glancing your links, not sure what might be wrong there, though hopefully cross-referencing the code in detail can give a hint towards a solution.

guest271314

unread,
Jan 25, 2022, 8:35:43 AM1/25/22
to web-transport-dev, juk...@unity3d.com, web-transport-dev, Tanjin, Victor Vasiliev, guest271314
Same result as GoogleChrome/samples webtransport_server.py. The datagrams stop transmitting to client after 27th write/read https://github.com/guest271314/last_frontier/tree/trying-to-stream-1.

You can open client.html at file: protocol.

I suspect some timer is involved. Though am not certain.

Screenshot_2022-01-25_05-24-22.png



guest271314

unread,
Jan 25, 2022, 9:11:48 AM1/25/22
to web-transport-dev, guest271314, juk...@unity3d.com, web-transport-dev, Tanjin, Victor Vasiliev
Looking at net log I notice idle timeout. Is that why the stream stops?

Screenshot_2022-01-25_06-10-26.png

Victor Vasiliev

unread,
Jan 25, 2022, 5:28:24 PM1/25/22
to guest271314, web-transport-dev, juk...@unity3d.com, Tanjin
Unlikely, given that the idle timeout will not activate while the WebTransport session is alive.

What does the CONNECTION_CLOSE look like in this case?  You can find it in the Events tab of the net-log.
Message has been deleted

guest271314

unread,
Jan 26, 2022, 1:11:14 AM1/26/22
to web-transport-dev, Victor Vasiliev, web-transport-dev, juk...@unity3d.com, Tanjin, guest271314
I could not locate CONNECTION_CLOSE text in WEB_TRANSPORT_CLIENT

Is running the code at file: protocol an issue?

  +HOST_RESOLVER_MANAGER_REQUEST [dt=0]                --> network_isolation_key = "file:// [internally: file://] file:// [internally: file://]" 

[st= 0] QUIC_SESSION_TRANSPORT_PARAMETERS_SENT
                    --> quic_transport_parameters = "[Client legacy[version 00000001] [chosen_version 00000001 other_versions 00000001] max_idle_timeout 30000 max_udp_payload_size 1472 initial_max_data 15728640 initial_max_stream_data_bidi_local 6291456 initial_max_stream_data_bidi_remote 6291456 initial_max_stream_data_uni 6291456 initial_max_streams_bidi 100 initial_max_streams_uni 103 initial_source_connection_id 0 max_datagram_frame_size 65536]"

guest271314

unread,
Jan 26, 2022, 7:33:56 AM1/26/22
to web-transport-dev, Victor Vasiliev, juk...@unity3d.com, Tanjin
Does anybody get a different result running the same code?

guest271314

unread,
Jan 26, 2022, 9:44:17 AM1/26/22
to web-transport-dev, guest271314, Victor Vasiliev, juk...@unity3d.com, Tanjin
When I set idle_timeout to a value greater than 60 https://github.com/aiortc/aioquic/blob/725ff50172f3a1eb5415458e231bdc1d92282904/src/aioquic/quic/configuration.py

  configuration = aioquic.quic.configuration.QuicConfiguration(alpn_protocols=aioquic.h3.connection.H3_ALPN, is_client=False, idle_timeout=240.0, max_datagram_frame_size=65536)

the setting is evidently not set and the following error occurs

Failed to establish a connection to https://localhost:4433/: net::ERR_QUIC_PROTOCOL_ERROR.QUIC_NETWORK_IDLE_TIMEOUT (No recent network activity after 4000093us. Timeout:4snum_undecryptable_packets: 0 {}).
client.html:1 Uncaught (in promise) WebTransportError: Opening handshake failed.

Reply all
Reply to author
Forward
0 new messages