Comments (7)
Thanks for filing this: I think the debug builds are vastly overestimating the cost of the StreamMap
. CircularBuffer
is an abstraction over Array
, and so it provides extra layers of performance cost that are not optimised out in debug builds. In release builds, however, it vanishes.
I think the fact that stream IDs start at zero, and increment from there
Incidentally, this is why CircularBuffer
is used: it allows the storage to be totally ordered, without needing to be frequently "compacted".
from swift-nio-http2.
One note: we could replace CircularBuffer
with Deque
from Swift collections.
from swift-nio-http2.
Just reading the header comment in StreamMap
(which I should have done before posting this issue, sorry) - it notes that a tradeoff was made resulting in slower lookups, but it assumes number of streams is low. I think if you're totally blasting a server with many gigs/s in uploads over a fast connection, which is our use case, stream IDs per connection could actually wind up being quite substantial. - I think I may have misunderstood how HTTP/2 streams work here.
It also dismisses dictionaries, due to the computational load of computing hashes. But couldn't we just make HTTP2StreamID
Hashable
- and simply provide the underlying Int32
as the hashValue
from swift-nio-http2.
Thanks for filing this: I think the debug builds are vastly overestimating the cost of the
StreamMap
.CircularBuffer
is an abstraction overArray
, and so it provides extra layers of performance cost that are not optimised out in debug builds. In release builds, however, it vanishes.
I've noticed release builds being way faster too, so maybe all of this is a non-issue. I'll check when I have time 👍
from swift-nio-http2.
It also dismisses dictionaries, due to the computational load of computing hashes. But couldn't we just make HTTP2StreamID Hashable - and simply provide the underlying Int32 as the hashValue
This totally works, but the tradeoff isn't straightforward. For small dictionaries (in this case, fewer than 100 elements), it's cheaper to do a linear array scan to find the element than it is to hash the key and do a jump. This is fairly non-intuitive but comes down to the way branch predictors and cache preloaders work: the memory subsystem can observe and optimise this access pattern, meaning that we're never waiting for memory, in a way that it cannot do with hashing. The data structure is therefore optimised for small size. For larger sizes, we do binary search instead, which is still extremely cheap.
from swift-nio-http2.
Thanks for the technical explanation! I'm glad a lot of thought went into this.
Diving a bit deeper, I'm seeing a lot of the work is actually coming from debugOnly
calls - so yeah seems like a false alarm. Notably, setting _backingCheck
. Now I'm wondering why _UInt24
is used, but that's a rabbit hole I should probably avoid for today!
from swift-nio-http2.
Thanks for the technical explanation! I'm glad a lot of thought went into this.
Diving a bit deeper, I'm seeing a lot of the work is actually coming from
debugOnly
calls - so yeah seems like a false alarm. Notably, setting_backingCheck
. Now I'm wondering why_UInt24
is used, but that's a rabbit hole I should probably avoid for today!
The _backingCheck
is just doing some (as you noticed) debug-build-only checking that may help to catch bugs early. It uses _UInt24
because we happened to have 24 spare bits in the data structure. So I thought why not (in debug builds) make use of those bits and store some extra information that we can then verify all the time. If I had used a normal UInt32
then the data structure would've grown (in debug & release builds) and if I had used UInt16
then we'd still have wasted 8 bits.
Concretely, those 24 bits store the length of the buffer such that we can detect if some code illegally stores and reuses buffer offsets across resizes. That's illegal because (like other many other data structures) the actual indexes get invalidates if you add/remove elements.
from swift-nio-http2.
Related Issues (20)
- HPACKHeaders.peekPseudoHeader allocates awkward temporary array
- HTTP2ChannelHandler.wroteFrame is never returned to false
- Consider returning [Substring] from HPACKHeaders.subscript(canonicalForm:)
- Provide API for adding pseudo headers to HPACKHeaders
- OutboundFlowControlBuffer probably allocates unnecessarily
- Suport HTTP Protocol Upgrade Mechanism HOT 7
- Improve performance of `Substring._trimWhitespace()` HOT 1
- Suppress writes triggered by EOF reads
- Remote pushes with invalid headers leave a stream dangling
- Push latest versions to CocoaPods? HOT 1
- `NIOHTTP2Handler` should handle `ChannelShouldQuiesceEvent` HOT 2
- Reconsider implementation of Equatable and Hashable for HPACKHeaders HOT 2
- Remove @unchecked Sendable when NIOCore adopts Sendable
- Produce a better error when sending HEADERS on a quiesced connection
- Failed assertion in change from 1.24.1 to 1.25.0 HOT 5
- The new HPACK header test for RemoveAll() fails on Android HOT 2
- Race condition causes header frame to be fired on HTTP2StreamChannel AFTER first data frame(s) HOT 3
- Content-Length in responses on HEAD method produce error HOT 3
- Support close mode when closing HTTP2StreamChannel HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from swift-nio-http2.