- Notifications
You must be signed in to change notification settings - Fork 136
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
Uh oh!
There was an error while loading. Please reload this page.
Conversation
c6bfa23 to c946b23Compareweissi commented May 8, 2021
| varport:Int | ||
| varunixPath:String | ||
| vartlsConfiguration:BestEffortHashableTLSConfiguration? | ||
| privatevartlsConfiguration: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 e6f5270Comparee184939 to ae9c9acCompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| varisNIOTS:Bool{ | ||
| #if canImport(Network) | ||
| if #available(OSX 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0,*){ | ||
| returnself.underlyingBootstrap is NIOTSConnectionBootstrap | ||
| }else{ | ||
| returnfalse | ||
| } | ||
| #else | ||
| returnfalse | ||
| #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?
| varisNIOTS: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 | |
| } | |
| varisNIOTS: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 }
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Sources/AsyncHTTPClient/Utils.swift Outdated
| port: key.port, | ||
| requiresTLS: requiresTLS, | ||
| configuration: configuration, | ||
| sslContextCache: sslContextCache, |
fabianfettMay 12, 2021 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
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.
Uh oh!
There was an error while loading. Please reload this page.
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
Uh oh!
There was an error while loading. Please reload this page.
2d23f5a to 064060eCompare5fa35bd to a7a30a8Compare
Lukasa left a comment
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.
fabianfett left a comment
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. 🎉
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.


Motivation:
At the moment, AHC assumes that creating a
NIOSSLContextis 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
NIOSSLContextis about 27,000allocations!!! To make it worse, AHC allocates a fresh
NIOSSLContextfor 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.