Improve Performance of HTTP Request and Response inits - #145
Improve Performance of HTTP Request and Response inits#145nerdsupremacist wants to merge 5 commits into
Conversation
| func fields(for name: HTTPField.Name) -> some Sequence<HTTPField> { | ||
| HTTPFieldSequence(fields: self, name: name) |
There was a problem hiding this comment.
this should still return the HTTPFieldSequence. HTTPFieldSequence should become internal though.
| init(reservingCapacity capacity: Int) { | ||
| fields.reserveCapacity(capacity) | ||
| } |
There was a problem hiding this comment.
let's remove this and instead just call reserveCapacity on the HTTPFields.
| } | ||
|
|
||
| init(parsed: [HTTPFields.Element]) throws { | ||
| let nonPseudoCount = parsed.count { !$0.name.isPseudo } |
There was a problem hiding this comment.
This is O(n). Let's just over reserve.
There was a problem hiding this comment.
Can do. FYI I tested it and it didn't yield any difference in the benchmarks but that could also just be the benchmarks
|
|
||
| init(parsed: [HTTPFields.Element]) throws { | ||
| let nonPseudoCount = parsed.count { !$0.name.isPseudo } | ||
| self.fields = HTTPFields(reservingCapacity: nonPseudoCount) |
There was a problem hiding this comment.
| self.fields = HTTPFields(reservingCapacity: nonPseudoCount) | |
| self.fields = HTTPFields() | |
| self.fields.reserveCapacity(parsed.count) |
| guard self.fields.fields(for: .contentLength).allValuesSame else { | ||
| throw ParsingError.multipleContentLength | ||
| } | ||
| guard self.fields[values: .contentDisposition].allElementsSame else { | ||
| guard self.fields.fields(for: .contentDisposition).allValuesSame else { | ||
| throw ParsingError.multipleContentDisposition | ||
| } | ||
| guard self.fields[values: .location].allElementsSame else { | ||
| guard self.fields.fields(for: .location).allValuesSame else { | ||
| throw ParsingError.multipleLocation |
There was a problem hiding this comment.
Urgh we walk the full field list three times here. can we just do it once?
There was a problem hiding this comment.
Good callout. I have added the validation to happen while we're appending the values rather than after the fact. Given there was a lot of duplicate code I wrapped the validation in a property wrapper (might be overkill let me know and I can remove it)
| for field in parsed { | ||
| try self.add(field: field) | ||
| } |
There was a problem hiding this comment.
We should do the pseudo headers first. for all remaining headers, we likely can use: append(contentsOf: parsed[pseudoHeaders...])
Motivation
Currently constructing a request or response from parsed http fields requires multiple unnecessary allocations.
Mainly due to:
Modifications
Result
Reduction in allocations and instructions in benchmarks
Before
After