If you mainly use hyper (or a framework on top, like iron, nickel, rustless, etc), then this really shouldn’t affect you at all. It’s just the parsing logic for the HTTP/1.1 spec in a standalone crate.
First, some buzz words. It’s stateless. It’s zero-copy. It performs zero allocations. It’s design piggybacks on the design of picohttpparser, which does the same.
- Stateless: Keeping state means branches. Branches slow down individual parsing attempts. Instead, state of a socket can and should be handled outside of the parser itself. As the socket receives more data, you can try to parse again
- Zero allocations
To be fast, and yet safe, an
Iterator is used to prevent unnecessary bounds checks. That implementation is encapsulated in an inner private module, so the safety is easier to audit, and a safe API is exposed from the module, so the main API must use the iterator safely.2
Coming 1.1 and 1.2
There’s two lower hanging fruit that could provide noticeable speed improvements: branch predictions, and SIMD. There’s an accepted Rust RFC for adding a
likely intrinsic that gives us branch prediction, but its implementation needs an extra push to get in.
There’s the simd crate, with only 2 things preventing it from speeding up httparse: its using an unstable feature or three, and SSE4 support is needed to get
_mm_cmpestri, which would provide the biggest boost.
Or maybe both of these will be available at the same time, and they both can be added in httparse 1.1.
Building your own HTTP library? Get out of here! <3 ↩︎
Don’t look at the
next_8 API. It’s wonky. I wanted a safe way to get 8 bytes at a time, and also be able to safely tell the
Iterator how far into those 8 bytes I actually got. It’d probably be better to make that a closure instead, like
bytes.with_8(|eight| check!(eight)). ↩︎