As reported in the OP, the issue was filed long ago https://github.com/golang/go/issues/47840 <https://github.com/golang/go/issues/47840>
My CL https://go-review.googlesource.com/c/net/+/362834 <https://go-review.googlesource.com/c/net/+/362834> is a viable fix (and should of been supported originally). > On Nov 10, 2021, at 12:59 PM, Andrey T. <xnow4fippy...@sneakemail.com> wrote: > > Fellas, > I would say the 5x throughput difference is a serious problem.Would you be > kind and open an issue on github about it? > Also, the PR that you have might benefit from explanation about what you are > trying to solve (and probably link to an issue on github), so it would get > more attention. > > Thanks! > > Andrey > > > On Tuesday, November 9, 2021 at 4:50:34 PM UTC-7 ren...@ix.netcom.com > <http://ix.netcom.com/> wrote: > Well, I figured out a way to do it simply. The CL is here > https://go-review.googlesource.com/c/net/+/362834 > <https://go-review.googlesource.com/c/net/+/362834> > > The frame size will be used for all connections using that transport, so it > is probably better to create a transport specifically for the high-throughput > transfers. > > You can also create perform single shot requests like: > > if useH2C { > rt = &http2.Transport{ > AllowHTTP: true, > DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { > return dialer.Dial(network, addr) > }, > MaxFrameSize: 1024*256, > } > } > > var body io.ReadCloser = http.NoBody > > req, err := http.NewRequestWithContext(ctx, "GET", url, body) > if err != nil { > return err > } > > resp, err := rt.RoundTrip(req) > > >> On Nov 9, 2021, at 3:31 PM, Robert Engels <ren...@ix.netcom.com >> <applewebdata://D74CB65E-BF16-44B6-8916-B6DB733E8726>> wrote: >> >> To be clear, I have no plans to submit a Cl to improve this at this time. >> >> It would require some api changes to implement properly. >> >>> On Nov 9, 2021, at 12:19 PM, Kirth Gersen <kirth...@gmail.com >>> <applewebdata://D74CB65E-BF16-44B6-8916-B6DB733E8726>> wrote: >>> >>> Great ! >>> >>> > I made some local mods to the net library, increasing the frame size to >>> > 256k, and the http2 performance went from 8Gbps to 38Gbps. >>> That is already enormous for us. thx for finding this. >>> >>> 4 -> Indeed a lot of WINDOW_UPDATE messages are visible when using >>> GODEBUG=http2debug=1 >>> >>> >>> On Tuesday, November 9, 2021 at 6:28:16 PM UTC+1 ren...@ix.netcom.com >>> <http://ix.netcom.com/> wrote: >>> I did a review of the codebase. >>> >>> Http2 is a multiplexed protocol with independent streams. The Go >>> implementation uses a common reader thread/routine to read all of the >>> connection content, and then demuxes the streams and passes the data via >>> pipes to the stream readers. This multithreaded nature requires the use of >>> locks to coordinate. By managing the window size, the connection reader >>> should never block writing to a steam buffer - but a stream reader may >>> stall waiting for data to arrive - get descheduled - only to be quickly >>> rescheduled when reader places more data in the buffer - which is >>> inefficient. >>> >>> Out of the box on my machine, http1 is about 37 Gbps, and http2 is about 7 >>> Gbps on my system. >>> >>> Some things that jump out: >>> >>> 1. The chunk size is too small. Using 1MB pushed http1 from 37 Gbs to 50 >>> Gbps, and http2 to 8 Gbps. >>> >>> 2. The default buffer in io.Copy() is too small. Use io.CopyBuffer() with a >>> larger buffer - I changed to 4MB. This pushed http1 to 55 Gbs, and http2 to >>> 8.2. Not a big difference but needed for later. >>> >>> 3. The http2 receiver frame size of 16k is way too small. There is overhead >>> on every frame - the most costly is updating the window. >>> >>> I made some local mods to the net library, increasing the frame size to >>> 256k, and the http2 performance went from 8Gbps to 38Gbps. >>> >>> 4. I haven’t tracked it down yet, but I don’t think the window size update >>> code is not working as intended - it seems to be sending window updates >>> (which are expensive due to locks) far too frequently. I think this is the >>> area that could use the most improvement - using some heuristics there is >>> the possibility to detect the sender rate, and adjust the refresh rate >>> (using high/low water marks). >>> >>> 5. The implementation might need improvements using lock-free structures, >>> atomic counters, and busy-waits in order to achieve maximum performance. >>> >>> So 38Gbps for http2 vs 55 Gbps for http1. Better but still not great. >>> Still, with some minor changes, the net package could allow setting of a >>> large frame size on a per stream basis - which would enable much higher >>> throughput. The gRPC library allows this. >>> >>> >>>> On Nov 8, 2021, at 10:58 AM, Kirth Gersen <kirth...@ <>gmail.com >>>> <http://gmail.com/>> wrote: >>>> >>> >>>> http/2 implementation seems ~5x slower in bytes per seconds (when transfer >>>> is cpu capped). >>>> >>>> POC: https://github.com/nspeed-app/http2issue >>>> <https://github.com/nspeed-app/http2issue> >>>> >>>> I submitted an issue about this 3 months ago in the Go Github ( >>>> https://github.com/golang/go/issues/47840 >>>> <https://github.com/golang/go/issues/47840> ) but first commenter >>>> misunderstood it and it got buried (they're probably just swamped with too >>>> many open issues (5k+...)). >>>> >>>> Everything using Golang net/http is impacted, the Caddy web server for >>>> instance. >>>> >>>> I know it probably doesn't matter for most use cases because it's only >>>> noticeable with high throughput transfers (>1 Gbps). >>>> Most http benchmarks focus on "requests per second" and not "bits per >>>> seconds" but this performance matters too sometimes. >>>> >>>> If anyone with expertise in profiling Go code and good knowledge of the >>>> net/http lib internal could take a look. It would be nice to optimize it >>>> or at least have an explanation. >>>> >>>> thx (sorry if wrong group to post this). >>>> >>> >>>> -- >>>> You received this message because you are subscribed to the Google Groups >>>> "golang-nuts" group. >>>> To unsubscribe from this group and stop receiving emails from it, send an >>>> email to golang-nuts...@ <>googlegroups.com <http://googlegroups.com/>. >>>> To view this discussion on the web visit >>>> https://groups.google.com/d/msgid/golang-nuts/89926c2f-ec73-43ad-be49-a8bc76a18345n%40googlegroups.com >>>> >>>> <https://groups.google.com/d/msgid/golang-nuts/89926c2f-ec73-43ad-be49-a8bc76a18345n%40googlegroups.com?utm_medium=email&utm_source=footer>. >>> >>> >>> -- >>> You received this message because you are subscribed to the Google Groups >>> "golang-nuts" group. >>> To unsubscribe from this group and stop receiving emails from it, send an >>> email to golang-nuts...@googlegroups.com >>> <applewebdata://D74CB65E-BF16-44B6-8916-B6DB733E8726>. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/golang-nuts/7332f727-6716-4c4d-85c5-a86cacd0c89fn%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/golang-nuts/7332f727-6716-4c4d-85c5-a86cacd0c89fn%40googlegroups.com?utm_medium=email&utm_source=footer>. > > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com > <mailto:golang-nuts+unsubscr...@googlegroups.com>. > To view this discussion on the web visit > https://groups.google.com/d/msgid/golang-nuts/1bfe6aec-abd2-4f63-bf77-bbfa6fd213ban%40googlegroups.com > > <https://groups.google.com/d/msgid/golang-nuts/1bfe6aec-abd2-4f63-bf77-bbfa6fd213ban%40googlegroups.com?utm_medium=email&utm_source=footer>. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/990B1C94-4E3E-4825-9A9E-B7DCEFCE5019%40ix.netcom.com.