Skip to content

net/http{,/internal/http2}: reduce memory usage #80735

Open

Description

@bradfitz

I'm trying to get http2 memory usage down.

Looks like there are a few easy-ish wins.

Notably, this goroutine (with x/net/http2 stacks still) can go away:

359664 @ 0x48dd6e 0x46a0c5 0xaa6888 0xaa5bb8 0x495a21
#	0xaa6887	golang.org/x/net/http2.(*clientStream).writeRequest+0xc87	golang.org/x/net@v0.56.0/http2/transport.go:1199
#	0xaa5bb7	golang.org/x/net/http2.(*clientStream).doRequest+0x17		golang.org/x/net@v0.56.0/http2/transport.go:1060

And there are some buffers that can be released/pooled earlier too, not held fo the life of the stream.

Tracking bug for http2 memory overall, for other CLs to use.

/cc @neild @nicholashusin

Activity

  1. gopherbot commented on Aug 5, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/810780 mentions this issue: net/http/internal/http2: let Transport's request-write goroutine exit early

  2. gopherbot commented on Aug 6, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/811680 mentions this issue: net/http/internal/http2: release handler write buffers when idle

  3. added
    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.
    on Aug 17, 2026
  4. cagedmantis commented on Aug 17, 2026

    @cagedmantis
    Contributor
  5. gopherbot commented on Sep 5, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/828206 mentions this issue: net/http/internal/http2: don't pin frame-sized write buffers on idle conns

  6. gopherbot commented on Sep 5, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/828205 mentions this issue: net/http/internal/http2: don't pin frame-sized read buffers on idle conns

  7. gopherbot commented on Sep 5, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/828204 mentions this issue: net/http/internal/http2: turn Framer.getReadBuf func field into a method

  8. changed the title [-]net/http/internal/http2: reduce memory usage[/-] [+]net/http{,/internal/http2}: reduce memory usage[/+] on Sep 6, 2026
  9. gopherbot commented on Sep 6, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/828504 mentions this issue: net/http: don't pin bufio buffers on idle HTTP/1 keep-alive connections

  10. 7 remaining items

  11. gopherbot commented on Sep 9, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/830364 mentions this issue: net/http: don't require timeout errors to wrap os.ErrDeadlineExceeded

  12. gopherbot commented on Sep 9, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/830365 mentions this issue: net/http: don't require timeout errors to wrap os.ErrDeadlineExceeded

  13. gopherbot commented on Sep 9, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/830384 mentions this issue: net/http: release HTTP/1 empty buffers immediately for keep-alive connections

  14. added this to the Go1.28 milestone on Sep 10, 2026
  15. gopherbot commented on Sep 11, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/831084 mentions this issue: net/http/internal/http2: let the server's serve goroutine exit when idle

  16. gopherbot commented on Sep 14, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/832504 mentions this issue: net/http/internal/http2: do some follow-ups to serve parking change

  17. gopherbot commented on Sep 15, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/833344 mentions this issue: net/http: don't pin bufio buffers on conns handed off to HTTP/2

  18. gopherbot commented on Sep 17, 2026

    @gopherbot
    Contributor

    Change https://go.dev/cl/834084 mentions this issue: net/http/internal/http2: replace parkMu with a single atomic word

  19. Medium1992 commented on Sep 30, 2026

    @Medium1992

    Related: memory pinned by HTTP/2 receive windows on slow streams. The windows are fixed (1 MiB per stream on the server, 4 MiB on the Transport), so every long-lived body whose reader lags behind the link holds a full window of unread data.

    Have you considered receive-window autotuning, as in kernel TCP, gRPC-Go's BDP estimator or quic-go? For example: start at 64 KiB, grow to 2× what the body reader consumed per RTT (RTT from PING), shrink gradually when the reader slows down, and never exceed the current fixed values.

    A prototype of this, done as a frame-level shim under net/http in a proxy. The code and the measurements below were produced by an AI assistant (Claude) on a local test bench (100 Mbit/s, 50 ms RTT, 30 sessions):

    scenario fixed windows autotuned
    client, slow body reader 146 MB 31–65 MB
    server, slow request-body consumer 70 MB 20 MB
    fast-then-slow stream, unread per stream 4.2 MB 0.17 MB

    Steady-state throughput is unchanged. The cost is a slower ramp for new streams: 5-second transfers were 3% slower at 30 ms RTT, 13% at 80 ms and 30% at 150 ms. Code: https://github.com/Medium1992/Xray-core-fork/blob/feat/xhttp-mux-cool/transport/internet/splithttp/h2flow.go

    Inside net/http this would be both simpler and architecturally cleaner: the body reader knows exactly when data is consumed, while a shim has to infer it from WINDOW_UPDATE frames.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Performance

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions