13 ms·
Comparing TCP and QUIC
- stevewatson301 4y agoOne of the best writeups about QUIC, and my new go to reference for anyone who asks about the topic (since the QUIC RFCs are obtuse, and I say that as someone who's read many RFCs to troubleshoot networking issues).
- quietbritishjim 4y agoA great writeup, but just to take issue (or at least discuss) this one point: > There may be some performance penalty of shifting the transport code from the kernel to user space This makes it sound like a kernel has potential for slightly more optimised implementation. But I think it's more than that - the transport code can be completely offloaded from the CPU to the network card/processor. That can only happen if it's abstracted behind syscalls, not written in user space.
- jacob019 4y agoHere's a relevant discussion from 2021: https://lore.kernel.org/netdev/CAK-6q+id+CJgoSHaMGMs=d1Lr81bukrdjbszhujVEYnimtnq8w@mail.gmail.com/T/ https://lore.kernel.org/netdev/CAK-6q+id+CJgoSHaMGMs=d1Lr81b... If QUIC sees wide adoption then it's just a matter of time before the protocol starts moving up stack.
- hinkley 4y agoWhen I read about eBPF there always seems to be an implication that we could move this logic to the NIC. I don’t know enough about it to know if that’s aspirational or an active project. But the idea of being able to push code to the “right” side of bottlenecks is a running theme, including in questions of user space versus kernel space. Chatty communication kills throughout and/or latency.
- mdaverde 4y agoThe NICs I could find that enable this behavior belong to Netronome: https://www.netronome.com/products/agilio-cx/ https://www.netronome.com/products/agilio-cx/ I've been meaning to get my hand on one of these to play around with eBPF offload. There is also XDP (a subsystem of eBPF) which lets you take action before the packets run up the entire network stack.
- hinkley 4y agoI thought we had a couple options now? Well that sucks then. Netronome doesn’t print their prices. That’s not a great sign. If you have to ask, you can’t afford them.
- superkuh 4y agoUnder "QUIC Issues" it mentions "Private QUIC" and offhandedly remarks that there is no way to use QUIC without CA based TLS which is built in. This means that QUIC cannot be used without the continuing approval of a third party incorporated entity. This is a very serious problem when QUIC takes over in user software (made by megacorps) and eventually drops HTTP/1.1 support. It will be the end of the open web and the beginning of a corporate controlled one. Ignoring this extremely dangerous outcome of a QUIC only world, this write-up is excellent and really clears things up.
- jacob019 4y agoDoes QUIC not work with self-signed certificates?
- dinosaurdynasty 4y agoBrowsers probably won't support it. I know quinn (a rust QUIC library) definitely does, though you have to enable custom verification as a compile option (which is reasonable).
- zekica 4y agoBrowsers support QUIC with self signed certificates. It doesn't work with HSTS but that is by-design.
- jmillikin 4y agoOperating a private CA is trivial, there are packages to automate it at every level from simple manual scripting to fully-automated ACME servers such as Boulder[0]. For proprietary software it's idiomatic to use a private CA for securing connections to a central server, to avoid the risk of DNS hijacking or a malicious third-party CA. For open-source software it will, definitionally, allow substituting different server key validation options for users who prefer to run their own servers. The only real problem QUIC's mandatory TLS causes is that localhost development becomes marginally more difficult, but even as someone who loves running my in-development stuff on localhost it's clear that the security of the internet as a whole is of far greater value. [0] https://github.com/letsencrypt/boulder https://github.com/letsencrypt/boulder
- zackmorris 4y agoThis is great! I've tried writing reliable stream implementations over UDP for games but always got lost in the weeds. The main use case I need is to have reliable streams and unreliable datagrams that continue working even if either peer's IP address changes. Something like that would allow cell phones to form scalable p2p mesh networks, for example. It needs to be encrypted and punch through NAT in a fully automated way, falling back to a (secure/anonymous) matching server if both peers are behind NAT. I don't know about that last part, but it appears that WebTransport over HTTP/3 over QUIC over UDP might be able to do most of that and be a potential replacement for WebRTC data channels: https://web.dev/webtransport/ https://web.dev/webtransport/ https://www.w3.org/TR/webtransport/ https://www.w3.org/TR/webtransport/
- superkuh 4y agoGames that use QUIC (no connections without CA TLS) will have a higher chance of eventually stopping working because they'll have to maintain the infrastructure to update their leased TLS cert from the CA every $x days. This is less important now than in the past because most games have moved to a microtransactions model that is (mostly, see exceptions like Team Fortress 2) incompatible with hosting your own server. So usually the company kills the game or goes under itself first. But for those games that do use QUIC and do have private servers, hacks will be needed to keep the games going long term (20+ years). Retro-gaming is going to be much harder in the future.
- Sean-Der 4y agoWhat caused you to get lost in the weeds before, would love to help! Was it a software or technical resources problem. I work on https://github.com/pion/webrtc https://github.com/pion/webrtc and https://webrtcforthecurious.com https://webrtcforthecurious.com and love solving both problem :) WebRTC has a really cool feature called `ICE Restart` that solves the 'walk out the door' problem.
- zackmorris 4y agoOh nice, I didn't know about ICE Restart before. Is there a way to make it automatic or set the timeout? I just skimmed the docs and it looks like it takes 30 seconds to realize that the peers aren't talking anymore. For a game, I might make that a few seconds to stay below the roughly 7 second attention span of most people. But ya, I got windowing working, and came up with a scheme to store the app's identifier (4 digit creator code on macOS) in a checksum by subtracting the actual checksum to be left with a remainder like 'app1'. So the game would transmit on checksum app1 instead of port 12345 for example. But I realized the overhead of computing the checksum might make it vulnerable to denial of service attacks, so maybe a separate field might have been better for faster filtering. I halfway implemented some slow start and Nagle algorithm stuff too. But NAT negotiation with STUN/TURN/UPnP/NAT-PMP or similar killed the project. That's so hard to solve for humans that I wouldn't even try now, I would probably enter all of the states in a giant truth table or graph and write a stateless solution with the time element removed instead. This was over 15 years ago though so the C++ code isn't really any good anymore. Also because of buffer overrun exploits in C, I think it's better to use a proven (formally tested?) framework like WebRTC instead, even for low-level stuff like games. We have GHz processors now that can handle any level of complexity around ~1500 byte packets and still saturate pipes, so trying to go bare-metal there strikes me as premature optimization that isn't usually worth the risk it exposes. The next thing that got me was, I didn't know about coroutines. So I had incredibly elaborate state machines for the game logic that quickly became unmaintainable even for the simple puzzle games I was prototyping. Today I would use a state manager like Redux or a software-transactional memory (STM) or a conflict-free replicated data type (CRDT), maybe distributed with Raft/Paxos somehow so that all peers can see the same state. An event-driven interface like the one used by Firebase/RethinkDB/Supabase, maybe CouchDB or similar, would be good too. I got stuck on solving consensus, like when 2 people hit each other at the same time, but maybe that's been solved. And then there's the matchmaking/lounge server. I cobbled something together using an IRC-style syntax, but was never happy with it. Maybe something like Matrix would work there. Believe it or not, I haven't actually used WebRTC yet, but want to. I also don't want a competing standard in WebTransport. I think what I was always looking for was a connectionless reliable stream, which was never a thing on the web, which set innovation back perhaps 25 years because only a handful of apps like Skype managed to pull it off. It appears that QUIC comes closest. And if WebRTC is the only one that's solved NAT and the connectionless part with ICE Restart and peer identifiers, then I'll consider that the standard. <rant> Sorry this got a little long, I'm just passionate about the injustice of stuff like NAT. I feel that the lack of solutions around this stuff was deliberate by the telecom industry. It all but ruined my game development career by making it difficult to compete with large AAA studios after the mid-2000s (until the arrival of Unreal/Unity perhaps). This is 1 of 100 rabbit holes that I've been down only to fail. So I appreciate that people like you are shedding light on this stuff so that maybe the next generation will be able to work feely without artificial barriers holding them back.
- Animats 4y agoNo performance numbers, though. I was hoping for third party benchmarks. QUIC is optimized for Google's use case - Google client talking to Google servers, with many Google streams combined into one big pipe. This is not the normal non-Google case. Early performance numbers from Google only indicated a relatively small gain (15%?) even for that case.
- quietbritishjim 4y agoAs I understood it: QUIC, or more accurately HTTP/3 over QUIC, is optimised for consumer web browser, mainly mobile devices over lossy network. That is not (only) Google's use case at all. If you're loading several images over the same HTTP2/TCP connection and you miss a packet of one then you have to get later packets resent for all of them. Even if the delayed packet does eventually arrive without needing to be resent, it still has the effect of holding up all the other streams. With HTTP3/QUIC, a missed or delayed packet does still affect the stream it's from within that connection (still a pity) but at least the other streams carry on unaffected. This problem in TCP is called head-of-line blocking: https://en.wikipedia.org/wiki/Head-of-line_blocking https://en.wikipedia.org/wiki/Head-of-line_blocking
- Animats 4y agoEven if the delayed packet does eventually arrive without needing to be resent, it still has the effect of holding up all the other streams. Only if you're multiplexing multiple streams inside one TCP connection. Multiple TCP connections will not affect each other.
- quietbritishjim 4y agoYes, that is exactly what HTTP allows: multiple data streams over a single TCP connection. In general, that's a good thing: if you have a page with dozens of small files (icon images, CSS, JS fragments, etc.) then you don't want to instantiate a new TCP connection for every one. Browsers typically have multiple HTTP connections open as a compromise so that you don't need a new TCP connection for every file but don't have the head of line problem so severely. But it's not as good as fixing the underlying problem.
- iamcalledrob 4y agoI often see QUIC described as "faster than TCP", but in my experience this has only been the case when it comes to handshake latency. Throughput-wise, I've found in real-world testing that QUIC is often slower than TCP: (1) QUIC uses more CPU, due to the processing in user-space. 1Gbps required 3 CPU cores. On my 1x-CPU VPS, QUIC maxed out at 400Mbps due to the CPU. With TCP+TLS, I could comfortably achieve 5Gbps. (2) QUIC was less resilient to packet loss (surprisingly). This was particularly noticeable on mobile devices. If your use-case is to move bytes between powerful servers over a reliable, wired connection, QUIC may beat TCP in most ways that matter. But for use in real-world mobile apps, TCP may still offer better throughput. Caveat: This is all data from using the quic-go package. The C libraries may well be more efficient :)
- skissane 4y ago> QUIC uses more CPU, due to the processing in user-space. That’s not inherent to the QUIC protocol itself though, that’s an implementation decision. There is no fundamental reason why QUIC couldn’t be implemented in kernel-space, such an implementation would still be conforming.
- iamcalledrob 4y agoAbsolutely, and it would be great if there was OS support here. TCP processing can be also offloaded to network cards today, so the same might need to happen for QUIC to be similarly efficient.
- drewg123 4y agoWhat nobody talks about is the lack of server-side offloads for QUIC. Things like TSO, LRO, and even hardware offloaded kTLS. Without those offloads, I estimate I'd be lucky to get 200Gb/s out of the same Netflix CDN server hardware that can serve TLS-encrypted TCP at over 700Gb/s. Do the benefits of QUIC really justify the economic and environmental impacts of that kind of loss of inefficiency on the server side? And yes, I know that some of these offloads are being worked on, but they are not here today.
- miohtama 4y agoA good question. Here is 2021 study: “Takeaway: We observe that QUIC provides significant improvements over TLS/TCP in low-bandwidth and high-RTT regions for video downloads. QUIC handshakes towards YouTube media servers offer an improvement of 534 ms (IN) and 406 ms (DE) when compared with TLS/TCP. We also observe that the overall download rate for TLS/TCP is higher than QUIC partly due to kernel optimizations such as LRO available for the TCP stack. QUIC provides a better video streaming experience with a lesser number and duration of stall events compared to TLS/TCP. We observe that TLS/TCP exhibits up to 50% longer stall durations compared to QUIC at 50th percentile for high loss networks.“ https://vaibhavbajpai.com/documents/papers/proceedings/quic-tnsm-2022.pdf https://vaibhavbajpai.com/documents/papers/proceedings/quic-... Also the study discussed about the server-side CPU usage. If you are worried about server-side offloading, you can still stick to TCP/IP until the hardware acceleration and other offloading catches up.
- drewg123 4y agoI skimmed the paper, but I could not determine what TCP congestion control method they were testing against. Given the stall time, I expect that it was not BBR (which is the congestion control used by QUIC). If you improve TCP's congestion control and can also control the client TCP stack, most of BBR's advantages over TCP disappear.
- matsur 4y agoQUIC doesn't imply BBR as congestion control. eg. Our (Cloudflare's) QUIC implementation supports multiple algorithms. https://blog.cloudflare.com/cubic-and-hystart-support-in-quiche/ https://blog.cloudflare.com/cubic-and-hystart-support-in-qui...