Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make HEADERS frame payload non-indirect #428

Merged
merged 4 commits into from
Jul 17, 2024

Conversation

Lukasa
Copy link
Contributor

@Lukasa Lukasa commented Nov 16, 2023

Motivation:

In previous patches we shrank the size of HTTP2Frame by making various data types indirect in the frame payload. This included HEADERS, which is unfortunte as HEADERS frames are quite common.

This patch changes the layout of the HEADERS frame to remove the indirect case.

Modifications:

  • Move END_STREAM into an OptionSet.
  • Turn the two optional bits into flags in the aforementioned OptionSet
  • Replace the properties with computed properties.
  • Remove the indirect case

Result:

HEADERS frames are cheaper.

@Lukasa Lukasa added the 🔨 semver/patch No public API change. label Nov 16, 2023
@Lukasa Lukasa force-pushed the cb-non-indirect-headers branch from b438da2 to 34390e5 Compare November 16, 2023 13:09
@dnadoba
Copy link
Member

dnadoba commented Nov 16, 2023

Can we add a unit test that checks that the size of FramePayload/HTTP2Frame doesn't exceed the maximum size of the inline existential storage? IIRC that would be 3 words / 24 Bytes on 64-bit systems.

@Lukasa Lukasa force-pushed the cb-non-indirect-headers branch from 34390e5 to 002ec5e Compare November 16, 2023 13:30
@Lukasa
Copy link
Contributor Author

Lukasa commented Nov 16, 2023

Done.

Copy link
Member

@dnadoba dnadoba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great performance/allocation improvement!

Copy link
Contributor

@glbrntt glbrntt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! ⛳️

Comment on lines 34 to 38
internal init(exclusive: Bool, dependency: HTTP2StreamID, weight: UInt8) {
self.exclusive = exclusive
self.dependency = dependency
self.weight = weight
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was the init intentionally internal before?

It's a parameter in Headers.init but is defaulted to nil so it looks like it not being public was an oversight?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like an oversight to me as well

@dnadoba
Copy link
Member

dnadoba commented Nov 16, 2023

The CI failure is interesting:

13:31:41 /code/Sources/NIOHTTP2/HTTP2Frame.swift:257:17: error: stored property 'booleans' of 'Sendable'-conforming struct 'Headers' has non-sendable type 'HTTP2Frame.FramePayload.Headers.Booleans'
13:31:41             var booleans: Booleans
13:31:41                 ^
13:31:41 /code/Sources/NIOHTTP2/HTTP2Frame.swift:226:20: note: consider making struct 'Booleans' conform to the 'Sendable' protocol
13:31:41             struct Booleans: OptionSet {
13:31:41                    ^
13:31:41                                       , Sendable

Booleans is an internal struct which is just made up of a single stored property which is Sendable. The compiler should be able to automatically synthesise Sendable conformance for us. Something is wrong here. Maybe @usableFromInline or the nesting is screwing with the compiler inference.

Motivation:

In previous patches we shrank the size of HTTP2Frame by
making various data types indirect in the frame payload.
This included HEADERS, which is unfortunte as HEADERS frames
are quite common.

This patch changes the layout of the HEADERS frame to remove the
indirect case.

Modifications:

- Move END_STREAM into an OptionSet.
- Turn the two optional bits into flags in the aforementioned
    OptionSet
- Replace the properties with computed properties.
- Remove the indirect case

Result:

HEADERS frames are cheaper.
@Lukasa Lukasa force-pushed the cb-non-indirect-headers branch from 002ec5e to b42fbe5 Compare November 17, 2023 15:37
@Lukasa Lukasa added 🆕 semver/minor Adds new public API. and removed 🔨 semver/patch No public API change. labels Nov 17, 2023
@Lukasa
Copy link
Contributor Author

Lukasa commented Nov 17, 2023

Updated.

@dnadoba
Copy link
Member

dnadoba commented Nov 17, 2023

Now we are hitting depreciation warnings because of the new NIO release:

15:38:56 /code/Tests/NIOHTTP2Tests/ConfiguringPipelineAsyncMultiplexerTests.swift:174:25: error: 'init(synchronouslyWrapping:configuration:)' is deprecated: This method has been deprecated since it defaults to deinit based resource teardown
15:38:56                     try NIOAsyncChannel(
15:38:56                         ^
15:38:56 /code/Tests/NIOHTTP2Tests/ConfiguringPipelineAsyncMultiplexerTests.swift:174:25: note: use 'init(wrappingChannelSynchronously:configuration:)' instead
15:38:56                     try NIOAsyncChannel(
15:38:56                         ^
15:38:56 /code/Tests/NIOHTTP2Tests/ConfiguringPipelineAsyncMultiplexerTests.swift:192:66: error: 'inbound' is deprecated: Use the executeThenClose scoped method instead.
15:38:56                     for try await receivedFrame in streamChannel.inbound {
15:38:56                                                                  ^
15:38:56 /code/Tests/NIOHTTP2Tests/ConfiguringPipelineAsyncMultiplexerTests.swift:195:49: error: 'outbound' is deprecated: Use the executeThenClose scoped method instead.
15:38:56                         try await streamChannel.outbound.write(ConfiguringPipelineAsyncMultiplexerTests.responseFramePayload)

@dnadoba
Copy link
Member

dnadoba commented Nov 24, 2023

I have reported the Sendable issue: swiftlang/swift#70019

@gjcairo gjcairo enabled auto-merge (squash) July 17, 2024 15:55
@gjcairo gjcairo merged commit a2b4d28 into apple:main Jul 17, 2024
6 of 7 checks passed
@Lukasa Lukasa deleted the cb-non-indirect-headers branch July 18, 2024 13:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🆕 semver/minor Adds new public API.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants