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

Do not allocate String to check if HTTP message is keep alive #402

Merged
merged 1 commit into from May 16, 2018

Conversation

Projects
None yet
3 participants
@normanmaurer
Copy link
Member

normanmaurer commented May 14, 2018

Motivation:

We can check if a HTTP message is using keep alive without any allocation.

Modifications:

Directly act on the internal storage of HTTPHeaders to find out if keep alive is used or not.

Result:

Less allocations

@normanmaurer normanmaurer requested review from Lukasa and weissi May 14, 2018

@weissi
Copy link
Contributor

weissi left a comment

like it because the .lowercased was always annoying and a waste.


if connection == "close" {
return false
if !self.headers.isEmpty {

This comment has been minimized.

@weissi

weissi May 14, 2018

Contributor

this seems superfluous as you iterate self.headers just after that. If this is empty, the loop won't do anything either.

This comment has been minimized.

@normanmaurer

normanmaurer May 14, 2018

Author Member

ok :)

}
return connection == "keep-alive"
// HTTP 1.1 use keep-alive by default if not otherwise told.
return version.major == 1 && version.minor == 1

This comment has been minimized.

@weissi

weissi May 14, 2018

Contributor

this should be version.minor >= 1 as RFC says to treat 1.x where x>=1 like 1.1

@@ -18,6 +18,8 @@ let crlf: StaticString = "\r\n"
let headerSeparator: StaticString = ": "

private let connectionUtf8 = "connection".utf8
private let closeUtf8 = "close".utf8

This comment has been minimized.

@weissi

weissi May 14, 2018

Contributor

I think these global variables do nothing (in the good case) and cause a slowdown if the compiler isn't able to optimise it. Just put them where you use them

This comment has been minimized.

@normanmaurer

normanmaurer May 14, 2018

Author Member

@weissi hmm I would have thought its actually better as .utf8 should only be called once ? Maybe I should make these static ?

This comment has been minimized.

@weissi

weissi May 14, 2018

Contributor

@normanmaurer .utf8 is a function that needs to be inlined. If you want to cache the bytes straight, you'll need to do Array("close".utf8)

This comment has been minimized.

@normanmaurer

normanmaurer May 14, 2018

Author Member

ah ok... then let me just do what you said first.

This comment has been minimized.

@weissi

weissi May 14, 2018

Contributor

that should be pretty fast in 4.1 and really fast in 4.2

This comment has been minimized.

@weissi

weissi May 14, 2018

Contributor

only using StaticStrings would be faster but we unfortunately don't support them yet for headers (which we should fix)

This comment has been minimized.

@normanmaurer

normanmaurer May 14, 2018

Author Member

@weissi on my to do list for this week ;)

if !self.headers.isEmpty {
for header in self.headers {
if self.buffer.equalCaseInsensitiveASCII(view: connectionUtf8, at: header.name) {
if self.buffer.equalCaseInsensitiveASCII(view: closeUtf8, at: header.value) {

This comment has been minimized.

@weissi

weissi May 14, 2018

Contributor

technically this isn't a correct implementation, right? could be connection: keep-alive, foobar no?

I know, it's not worse than the previous implementation either but the fast path is anyway that there is no connection header

This comment has been minimized.

@normanmaurer

normanmaurer May 14, 2018

Author Member

@weissi I just preserved the old behaviour. @Lukasa thoughts ?

@@ -18,6 +18,8 @@ let crlf: StaticString = "\r\n"
let headerSeparator: StaticString = ": "

This comment has been minimized.

@weissi

weissi May 14, 2018

Contributor

please change the allocation counter test limits and reduce according to the number of allocs saved

This comment has been minimized.

@normanmaurer

normanmaurer May 15, 2018

Author Member

@weissi let me see if it changes anything (as it will only if we actual have a connection header).

This comment has been minimized.

@normanmaurer

normanmaurer May 15, 2018

Author Member

@weissi @Lukasa ok no changes as we never have such a header.

return false
for header in self.headers {
if self.buffer.equalCaseInsensitiveASCII(view: "connection".utf8, at: header.name) {
if self.buffer.equalCaseInsensitiveASCII(view: "close".utf8, at: header.value) {

This comment has been minimized.

@Lukasa

Lukasa May 15, 2018

Contributor

I don't think this is quite right, though to be fair this has never been quite right. Strictly speaking I think this will fail if the header is Connection: close, some-other-header-name, when it should not. Additionally, neither close nor keep-alive strictly have to be first.

Do we want to add some tolerance for that, or set it as a contributor friendly issue and let the community tackle it?

This comment has been minimized.

@normanmaurer

normanmaurer May 15, 2018

Author Member

@Lukasa @weissi I can fix this as part of this PR or do a followup ... Whatever you prefer. let me know.

This comment has been minimized.

@weissi

weissi May 15, 2018

Contributor

@Lukasa yes, commented on that one too but I'd be happy with a follow-up.

This comment has been minimized.

@normanmaurer

normanmaurer May 15, 2018

Author Member

will do a followup

@weissi

weissi approved these changes May 15, 2018

Copy link
Contributor

weissi left a comment

🙌

@normanmaurer

This comment has been minimized.

Copy link
Member Author

normanmaurer commented May 15, 2018

@Lukasa cool with me merging ?

Do not allocate String to check if HTTP message is keep alive
Motivation:

We can check if a HTTP message is using keep alive without any allocation.

Modifications:

Directly act on the internal storage of HTTPHeaders to find out if keep alive is used or not.

Result:

Less allocations

@normanmaurer normanmaurer force-pushed the normanmaurer:keepalive_not_alloc branch from 152d300 to 0210df4 May 15, 2018

@Lukasa

Lukasa approved these changes May 16, 2018

@Lukasa Lukasa merged commit e029ede into apple:master May 16, 2018

2 checks passed

pull request validation (4.0.3) Build finished.
Details
pull request validation (4.1) Build finished.
Details

@Lukasa Lukasa added this to the 1.7.0 milestone May 18, 2018

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