Skip to content
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

Closed
wants to merge 11 commits into from
Closed

Conversation

jeddenlea
Copy link
Contributor

@jeddenlea jeddenlea commented Apr 1, 2022

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.

sbosnick added 8 commits May 9, 2020 17:38
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.
@LucioFranco
Copy link
Member

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!
@jeddenlea
Copy link
Contributor Author

@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.

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{
Copy link
Member

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 🤔

@seanmonstar
Copy link
Member

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?

@seanmonstar
Copy link
Member

Well I tried resolving the conflicts with GitHub's help, and it failed in one tiny way. So I've now fixed it up locally, and ended up squashing it into a single commit since the diff was quite small now that #499 was merged before. The new PR is in #555.

@seanmonstar
Copy link
Member

Merged in #555.

@seanmonstar seanmonstar closed this Jun 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants