Skip to content

Do not create an encoder stream if dynamic table is not used - #12

Merged
glbrntt merged 2 commits into
apple:mainfrom
agnosticdev:noEncoderStream
Jul 14, 2026
Merged

Do not create an encoder stream if dynamic table is not used#12
glbrntt merged 2 commits into
apple:mainfrom
agnosticdev:noEncoderStream

Conversation

@agnosticdev

Copy link
Copy Markdown
Contributor

Motivation

When the connection is started a client is offering a Dynamic Table with the size of 4096:

Hypertext Transfer Protocol Version 3
    UNI STREAM: Control Stream off=0
        Uni Stream Type: Control Stream (0x0000000000000000)
        SETTINGS len=15
            [Stream ID: 2]
            Type: SETTINGS (0x0000000000000004)
            Length: 15
            Frame Payload: 06ffffffffffffffff015000074064
            Settings - Max Field Section Size: 4611686018427387903
            Settings - Max Table Capacity: 4096
            Settings - Blocked Streams: 100
Hypertext Transfer Protocol Version 3
    UNI STREAM: QPACK Decoder Stream off=0
        Uni Stream Type: QPACK Decoder Stream (0x0000000000000003)
Hypertext Transfer Protocol Version 3
    UNI STREAM: QPACK Encoder Stream off=0
        Uni Stream Type: QPACK Encoder Stream (0x0000000000000002)

And so the HTTP server opens encoder streams even though it doesnt look like the Dynamic table is supported:

if settings.qpackMaximumTableCapacity > 0 {
    // These settings would enable the peer to use the dynamic table
    // We must not allow that, see the DynamicTable doc for explanation.
    fatalError("Dynamic table is not supported yet")
}

So each packet from the peer contains a client QPACK decoder frame:

(Each packet has a QPACK Decoder frame in it)
19 0.983563 HTTP3 1486 QPACK DEC[1], STREAM(12), HEADERS: GET https://192.168.xxx.xxx:8080/responsiveness/download/1000, PADDING
23 0.984147 HTTP3 1486 QPACK DEC[1], STREAM(20), HEADERS: GET https://192.168.xxx.xxx:8080/responsiveness/download/1000, PADDING

And this causes QUIC and HTTP3 to use a lot of CPU processing the decoder frame.

Modifications

Setup a effectiveDynamicTableSize to be based on the local and remote table size, if one is zero then the encoder stream will not be opened.

Result

Nice reduction in CPU.
Top of tree without this change:

14.83 G  100.0% -  http3-swift-quic (16387)

With this change:

12.89 G  100.0% -  http3-swift-quic (43069)

Comment thread Sources/HTTP3/HTTP3ConnectionStateMachine.swift Outdated
Comment thread Sources/HTTP3/HTTP3ConnectionStateMachine.swift Outdated
@josephnoir josephnoir added the 🔨 semver/patch No public API change. label Jul 10, 2026
@glbrntt
glbrntt merged commit 8119053 into apple:main Jul 14, 2026
29 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 semver/patch No public API change.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants