[HN Gopher] Go-msquic: A new QUIC/HTTP3 library for Go
       ___________________________________________________________________
        
       Go-msquic: A new QUIC/HTTP3 library for Go
        
       Author : noboruma
       Score  : 75 points
       Date   : 2025-02-19 04:48 UTC (18 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | noboruma wrote:
       | msquic is one of the most performant QUIC protocol library out
       | there. go-msquic is a wrapper around msquic so you can use it
       | inside your Go project.
       | 
       | https://github.com/noboruma/go-msquic
       | 
       | The project is quite new, but we have seen good performance
       | results with it so far. PRs are welcome!
        
         | Veserv wrote:
         | Their dashboard [1] shows the library only gets ~7 Gbps on what
         | is presumably a single core (given that it is single connection
         | benchmark). Is that considered fast?
         | 
         | The memory bus on that system probably pushes at least ~400
         | Gbps, and even a fairly simple memcpy() implementation could
         | probably push ~100 Gbps even at standard MTU (i.e. small)
         | sizes. So that would be ~14 copies worth of execution cost per
         | bit. That seems extremely high especially given how much people
         | complain about the number of copies which, by this metric,
         | would only cost ~7% per extra full copy.
         | 
         | [1] https://microsoft.github.io/msquic/
        
           | ayanamist wrote:
           | Network throughput and memory throughput are quite different.
        
             | Veserv wrote:
             | I assume their network protocol benchmark meant to show how
             | fast their protocol implementation is relative to others is
             | not being bottlenecked on their network bandwidth because
             | that would be positively idiotic.
             | 
             | Given the machine the benchmarks are running on has a 50
             | Gbps NIC, that would be double stupid since their
             | bottleneck would then need to be the production side not
             | producing enough data to show how fast their implementation
             | is or bad network configuration doing the same.
             | 
             | And that all assumes they are not bypassing the NIC
             | entirely since they are benchmarking the _protocol
             | implementation_ so the source of packets is largely
             | irrelevant except for making sure they are not still in the
             | cache after the producer synthesizes them.
             | 
             | Beyond that we look to memory bandwidth as a fundamental
             | limiting factor on data shuffling from packets to the
             | protocol client to attempt to bound the theoretical maximum
             | throughput so we can see how far off a protocol
             | implementation is from the theoretical maximum.
        
           | klabb3 wrote:
           | > Is [~7 Gbps] considered fast?
           | 
           | With Quic, yes. I don't have hands on experience with this
           | lib but throughput is not the strength of quic. In fact,
           | that's true for untuned UDP in general. Oftentimes CPU will
           | bottleneck without bespoke platform-specific hacks to avoid
           | the one syscall per 1260 bytes default/portable status quo.
           | 
           | I don't know _that_ bench but throughput varies wildly
           | between environments, cross traffic and a number of mystical
           | parameters.
        
             | Veserv wrote:
             | Do we know if that is true for whatever Google is using
             | internally on their servers? Are they also only getting ~7
             | Gbps per core or are they going much faster either due to
             | software or hardware?
             | 
             | What are the actual exemplary implementations because ~7
             | Gbps per core seems really slow for an actual quality
             | production implementation based on my read of the QUIC
             | standard.
        
               | vitus wrote:
               | > ~7 Gbps per core seems really slow for an actual
               | quality production implementation
               | 
               | Not really? With a 128-core _machine_ , that's in the
               | ballpark of 900 Gbps; you're hitting other bottlenecks
               | far earlier than that. And in practice, we're talking
               | about 256 hardware threads for a dual-socket Epyc Milan
               | server, which has been the machine-of-the-day at Google
               | for years now. AMD server processors are so big these
               | days that you could spend a quarter of your compute on
               | QUIC without blinking an eye, be able to serve 450 Gbps
               | on paper per machine, and ultimately hit bottlenecks
               | because disk I/O isn't able to feed the NIC that fast for
               | YouTube serving.
               | 
               | One of the biggest things holding QUIC performance back
               | is a chicken-and-egg problem: vendors don't want to
               | implement NIC offload because there aren't enough
               | companies that want it, and companies don't want to use
               | QUIC because it represents such a big performance drop
               | relative to TCP's decades of tuning with the Linux kernel
               | (in part because of the lack of NIC offload).
        
               | Veserv wrote:
               | You are arguing: "Why should Google care about wasting
               | 25% of their compute costs?" I do not know how much that
               | is, but presumably it is in the billions per year. A 1%
               | saving would be tens of millions per year and that would
               | only require a 4% implementation improvement.
               | 
               | Having done the majority of a QUIC implementation myself,
               | achieving (on the non-encryption portion) 10 Gbps (1.5x
               | faster) seems trivial, 30 Gbps per core (4x faster) seems
               | straightforward, and 100 Gbps per core (15x faster) looks
               | possible.
               | 
               | I was looking for benchmarks of professional
               | implementations to see the limits of the protocol, but
               | all I see are rates in the single digit Gbps which I
               | assumed were toy re-implementations based on my analysis
               | of what should be possible. But apparently these are
               | state of the art implementations so now I am trying to
               | figure out if anybody knows the specific reasons for the
               | performance disparity.
        
               | jsnell wrote:
               | > You are arguing: "Why should Google care about wasting
               | 25% of their compute costs?"
               | 
               | So your estimate is that 25% of Google's compute costs
               | are spent on terminating QUIC connections? I'd be very
               | curious to hear how you arrived at that estimate.
               | 
               | > Having done the majority of a QUIC implementation
               | myself, achieving (on the non-encryption portion) 10 Gbps
               | (1.5x faster) seems trivial, 30 Gbps per core (4x faster)
               | seems straightforward, and 100 Gbps per core (15x faster)
               | looks possible.
               | 
               | 100Gbps goodput with typical internet MTU sizes will mean
               | about 10M ingress packets per second on the receiving
               | side. That gives you a time budget of about 100
               | nanoseconds per packet, i.e. a single cache miss takes up
               | the entire budget. Just computing a hash for the 5-tuple
               | to look up the connection in the socket table will be
               | like 10ns.
               | 
               | > But apparently these are state of the art
               | implementations so now I am trying to figure out if
               | anybody knows the specific reasons for the performance
               | disparity.
               | 
               | It would be a performance disparity if you had a working
               | implementation that was as fast as you claim, but as far
               | as I can tell you don't have one yet?
        
           | noboruma wrote:
           | Most of the benchmarks comparing msquic with other libraries
           | are showing it on top.
           | 
           | That's the reason we decided to go ahead and see how it
           | performs within our Go lang code base.
           | 
           | On our setup we are seeing a 50% latency reduction compared
           | with other implementations. Definitely worth a try if you are
           | looking for performance.
        
             | infogulch wrote:
             | Are these benchmarks published anywhere?
        
           | bufferoverflow wrote:
           | Why would you assume QUIC is equivalent to copying memory?
        
           | zamadatix wrote:
           | QUIC involves a lot more than copying packet data under a
           | specific header so the bounds provided by memcpy() end up
           | saying very little. E.g. QUIC mandates TLS 1.3, you'll have
           | congestion and loss control (not every packet you send is
           | guaranteed to make it), the tests are measuring goodput not
           | network bandwidth, latencies for switching between/waiting
           | for tasks to complete on a single core may be limiting.
           | 
           | Whether it's "considered fast" is better answered by simply
           | comparing the practical numbers, like in that dashboard,
           | rather than supposition. This kind of question is more aimed
           | at trying to find out "how fast could it possibly be".
        
           | musjleman wrote:
           | > what is presumably a single core
           | 
           | I would guess that it's not a single core benchmark and
           | that's the speed of the overall multi-threaded system.
           | 
           | > Is that considered fast?
           | 
           | You can squeeze out around 5GB/s/core with current fastest
           | standard tls1.3 algorithm (AES128GCM). 10+GB/s is possible
           | with aegis variants that are somewhat popular as an extension
           | to TLS libs.
        
             | Veserv wrote:
             | 5 GB/s per core would still be 40 Gbps per core, so only
             | ~15% of their time would be spent in encryption. They spend
             | 5x longer doing the non-encryption stuff.
             | 
             | Also, it would be silly to bottleneck your protocol
             | implementation benchmark on encryption that would be shared
             | amongst implementations because that does not highlight
             | your overhead advantages. In addition, the benchmarking RFC
             | explicitly allows for the null encryption case in
             | benchmarking for exactly that reason.
        
               | musjleman wrote:
               | > Also, it would be silly to bottleneck your protocol
               | implementation benchmark on encryption that would be
               | shared amongst implementations because that does not
               | highlight your overhead advantages
               | 
               | It would be great if benchmarks with no encryption were a
               | thing.
               | 
               | There's massive overheads, and I explicitly avoided
               | saying whether it's "fast" or not because to a lot of
               | people serving 1000req/s seems "fast" and TLS is
               | basically the main algorithmic complexity you'd expect
               | from a data transfer protocol.
        
       | predictionfutu wrote:
       | > CGO_ENABLED=1
       | 
       | It's not Go then
        
         | bheadmaster wrote:
         | To be fair, the first line in the README.md says
         | go-msquic is a Go wrapper for the Microsoft's QUIC library
         | 
         | So it's only the HN headline that is (technically) wrong.
        
           | kitd wrote:
           | And tbf it says _for_ Go, not _in_ Go
        
         | noboruma wrote:
         | Never claimed the library to be full Go implementation, it is a
         | library _for_ Go. If you want a pure Go implementation, it
         | already exists: quic-go.
         | 
         | It is mentioned & advised to use that one in the README.
         | However if you need more perf, you might want to give a try at
         | go-msquic.
        
       ___________________________________________________________________
       (page generated 2025-02-19 23:01 UTC)