-
Notifications
You must be signed in to change notification settings - Fork 299
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
Merge #428 and #499 #540
Merge #428 and #499 #540
Conversation
The use of MaybeUninit to replace the depreciated mem::uninitialized() is supported because the minimum supported version of Rust is 1.39. This change moves most of the uninitialized memory related use of unsafe into the parse_hdr() function.
The general pattern follows the "Initilizing an array element-by-element" example in the documentation of MaybeUninit. This change removes some unnecessary use of unsafe.
This introduces a dev-dependency on the criterion crate. The new benchmark for HeaderName uses different standard header names of increasing lengths.
A previous commit had extracted the comparison of a presumed-initialized MaybeUninit<u8> and a static u8 to its own function. While clearer, this lead to a performance regression so this commit manually inlines this method again. This restores most (but not yet all) of the performance that regressed.
Move the eq! macro into the parsh_hdr() function which locallized all of the unsafe code related to MaybeUninit.
The comments describe the pre-condition and post-conditions on the various different parts of the two parse_hdr() implementations that combine to make the use of MaybeUninit in that function sound. The process of assessing the soundness of the use of MaybeUninit also included manually checking that the number of parameters to each all eq!() invocation matches the number of bytes initilized by the immediatly preceeding invocation of to_lower!() (which is necessary to avoid undefined behavior). To avoid being overly repetative the general pattern that assures soundness is documented in the comments but not each instance of that pattern. Each instance, though, was checked.
The comments document the invariant, preconditions, and post-conditions that together ensure that the use of unsafe related to UTF-8 assumptions (in calls to ByteStr::from_utf8_unchecked()) are sound.
f399df0
to
a146c3b
Compare
Hi @jeddenlea I think due to the nature of those two PRs I think it probably makes sense to review them individually and have separate commits. So we should try to revive those again even though there will be some conflicts. |
... plus some clean-up. It was only after I came up with the scheme using `const fn from_bytes(&[u8]) -> Option<StandardHeader>` that I noticed the debug+wasm32-wasi version of `parse_hdr`, which had something very similar. While cleaning up that function, I realized it still would still panic if an attempted name was too long, which had been fixed for all other targets and profiles in hyperium#433. Then, I thought it would be worth seeing if the use of `eq!` in the primary version of `parse_hdr` still made any difference. And, it would not appear so. At least not on x86_64, nor wasm32-wasi run via wasmtime. I've run the benchmarks a number of times now, and it seems the only significant performance change anywhere is actually that of `HeaderName::from_static` itself, which now seems to run in about 2/3 the time on average. Unfortunately, `const fn` still cannot `panic!`, but I've followed the lead from `HeaderValue::from_static`. While that version required 1.46, this new function requires 1.49. That is almost 8 months old, so hopefully this isn't too controversial!
…o constname_merge Merges hyperium#428 into hyperium#499
a146c3b
to
9bede3a
Compare
@LucioFranco certainly! I won't be upset if this PR is abandoned, I just wanted to work out what a merge would look like because it would be great for both to be included in the next release, and there are lots of conflicts. This can be used as a reference if that's helpful. I did update it to include the small tweak I had to make on #499 for final approval. |
src/header/name.rs
Outdated
pub const fn from_static(src: &'static str) -> HeaderName { | ||
let name_bytes = src.as_bytes(); | ||
if let Some(standard) = StandardHeader::from_bytes(name_bytes) { | ||
return HeaderName{ |
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'd think rustfmt would catch the missing space... Not that I care, but makes me wonder 🤔
Looks like we got conflicts from merging first your other PR. I've read through the code and changes, everything is super clear, thank you! Want to try to rebase and we'll get a release out with this? |
Merged in #555. |
For your consideration. I'm not sure what the ideal way to collapse these commits together would be to match the clean, ordered scheme this repo is otherwise doing. But, if we were to apply #428 atop #499, I think it would look like this.