-
Notifications
You must be signed in to change notification settings - Fork 125
cache NIOSSLContext (saves 27k allocs per conn) #362
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
Conversation
c6bfa23
to
c946b23
Compare
c946b23
to
15b2e3b
Compare
@@ -148,7 +153,7 @@ final class ConnectionPool { | |||
var host: String | |||
var port: Int | |||
var unixPath: String | |||
var tlsConfiguration: BestEffortHashableTLSConfiguration? | |||
private var tlsConfiguration: BestEffortHashableTLSConfiguration? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: make this private because nobody accesses it from the outside and if not private, then there are places where we have both a key.tlsConfiguration
and a configuration.tlsConfiguration
which aren't necessarily the same (eg. when doing https://
over a http://
proxy).
65ff26c
to
e6f5270
Compare
e184939
to
ae9c9ac
Compare
ae9c9ac
to
539671d
Compare
var isNIOTS: Bool { | ||
#if canImport(Network) | ||
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) { | ||
return self.underlyingBootstrap is NIOTSConnectionBootstrap | ||
} else { | ||
return false | ||
} | ||
#else | ||
return false | ||
#endif | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason, why we don't use this pattern?
var isNIOTS: Bool { | |
#if canImport(Network) | |
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) { | |
return self.underlyingBootstrap is NIOTSConnectionBootstrap | |
} else { | |
return false | |
} | |
#else | |
return false | |
#endif | |
} | |
var isNIOTS: Bool { | |
#if canImport(Network) | |
if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, *) { | |
return self.underlyingBootstrap is NIOTSConnectionBootstrap | |
} | |
#endif | |
return false | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reduced the amount of code we need here but happy to add another } else { return false }
Sources/AsyncHTTPClient/Utils.swift
Outdated
port: key.port, | ||
requiresTLS: requiresTLS, | ||
configuration: configuration, | ||
sslContextCache: sslContextCache, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we pass the SSLContextCache
down here? We already have a sslContext
(a Future
) created before. IMHO it would make more sense to pass that down.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is an excellent question, I have no idea. I'll look into this, maybe we can just inject the SSLContext into that method.
sslContext.map { sslContext -> (Channel, NIOSSLContext?) in | ||
(channel, sslContext) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because we now need the actual context. We're kicking off the connection creation and an SSLContext creation in parallel and this is the point where we need both.
Sources/AsyncHTTPClient/Utils.swift
Outdated
bootstrap = sslContextCache.sslContext(tlsConfiguration: configuration.tlsConfiguration ?? .forClient(), | ||
eventLoop: eventLoop, | ||
logger: logger) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is hit with in a test that doesn't require https
: testUploadStreamingBackpressure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
great catch! Thanks you
539671d
to
e9c243b
Compare
2d23f5a
to
064060e
Compare
5fa35bd
to
a7a30a8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, this LGTM.
a7a30a8
to
89336a0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. 🎉
89336a0
to
b2092fc
Compare
Motivation: At the moment, AHC assumes that creating a `NIOSSLContext` is both cheap and doesn't block. Neither of these two assumptions are true. To create a `NIOSSLContext`, BoringSSL will have to read a lot of certificates in the trust store (on disk) which require a lot of ASN1 parsing and much much more. On my Ubuntu test machine, creating one `NIOSSLContext` is about 27,000 allocations!!! To make it worse, AHC allocates a fresh `NIOSSLContext` for _every single connection_, whether HTTP or HTTPS. Yes, correct. Modification: - Cache NIOSSLContexts per TLSConfiguration in a LRU cache - Don't get an NIOSSLContext for HTTP (plain text) connections Result: New connections should be _much_ faster in general assuming that you're not using a different TLSConfiguration for every connection.
b2092fc
to
97b4896
Compare
Motivation:
At the moment, AHC assumes that creating a
NIOSSLContext
is both cheapand doesn't block.
Neither of these two assumptions are true.
To create a
NIOSSLContext
, BoringSSL will have to read a lot ofcertificates in the trust store (on disk) which require a lot of ASN1
parsing and much much more.
On my Ubuntu test machine, creating one
NIOSSLContext
is about 27,000allocations!!! To make it worse, AHC allocates a fresh
NIOSSLContext
for every single connection, whether HTTP or HTTPS. Yes, correct.
Modification:
Result:
New connections should be much faster in general assuming that you're
not using a different TLSConfiguration for every connection.