Skip to content

Buffer channelReads in ResponseStreamState until the next channelReadComplete #388

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

Merged
merged 4 commits into from
Jul 7, 2021

Conversation

fabianfett
Copy link
Member

@fabianfett fabianfett commented Jul 6, 2021

Motivation

After a lengthy offline discussion @Lukasa, we concluded that it would be best, if the HTTPRequestStateMachine would buffer up all reads until the next channelReadComplete. The main reason is, we minimize potential cross thread communication, by passing collected byteBuffers onward.

Modifications

  • ConsumerControlState was replaced with ResponseStreamState
  • channelReads are buffered up to a channelReadComplete.
  • on channelReadComplete all buffered body parts are forwarded to the consumer

@fabianfett fabianfett requested a review from Lukasa July 6, 2021 14:14
@fabianfett fabianfett added the 🔨 semver/patch No public API change. label Jul 6, 2021
@fabianfett fabianfett added this to the HTTP/2 support milestone Jul 6, 2021
case waitingForRead(CircularBuffer<ByteBuffer>)
/// The state machines expects a call to `demandMoreResponseBodyParts`. The buffer is empty. It is
/// preserved for performance reasons.
case waitingForDemand(CircularBuffer<ByteBuffer>)
Copy link
Collaborator

Choose a reason for hiding this comment

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

By making this a mini-state-machine, I recommend going the whole way: pull this out to a file and give it a bunch of methods that correspond to the events that can occur to it (e.g. func read). Then, the bigger state machine can just call those.

@fabianfett fabianfett force-pushed the ff-buffer-in-channel branch from d76029f to 96fbbbd Compare July 6, 2021 16:08
@fabianfett fabianfett changed the title Buffer channelReads in the HTTPRequestStateMachine until the next channelReadComplete Buffer channelReads in ResponseStreamState until the next channelReadComplete Jul 6, 2021
private var state: State

init(expectingBody: Bool) {
self.state = .waitingForBytes(CircularBuffer(initialCapacity: expectingBody ? 16 : 0))
Copy link
Collaborator

Choose a reason for hiding this comment

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

Given that there is no such thing as an empty circular buffer (initialCapacity: 0 still allocates) we may as well skip the branch and just always set 16.

mutating func end() -> CircularBuffer<ByteBuffer> {
switch self.state {
case .waitingForBytes(let buffer):
// This should never happen. But we don't want to precondition this behavior. Let's just
Copy link
Collaborator

Choose a reason for hiding this comment

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

This comment is wrong.

expectingBody = true
}
} else if head.headers.contains(name: "transfer-encoding") {
expectingBody = true
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can delete this code per my above comment.

@fabianfett fabianfett force-pushed the ff-buffer-in-channel branch from 2c49141 to a4fba69 Compare July 7, 2021 10:52
@fabianfett fabianfett merged commit fcb0f21 into swift-server:main Jul 7, 2021
@fabianfett fabianfett deleted the ff-buffer-in-channel branch July 7, 2021 11:30
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.

2 participants