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

Specialize BufList::copy_to_bytes #2413

Merged
merged 1 commit into from
Feb 3, 2021
Merged

Specialize BufList::copy_to_bytes #2413

merged 1 commit into from
Feb 3, 2021

Conversation

vorner
Copy link
Contributor

@vorner vorner commented Jan 31, 2021

Some implementations of the Buf trait have an optimized version (for
example Bytes) of copy_to_bytes, opportunistically use that one.

For some background, I was implementing a similar type and had a look there and noticed it is not implemented. Or is there some reason why it shouldn't be implemented?

@seanmonstar
Copy link
Member

Good idea! The implementation looks right to me (though trickier than I assumed before looking). What do you think of adding a few tests since it's tricky?

  • If only containing a single Bytes, the pointer should be the same before and after.
    • That it popped the buf if the length is the same.
  • That it handles a single buf that's longer.
  • That it handles multiple bufs.

@vorner
Copy link
Contributor Author

vorner commented Feb 2, 2021

OK, that makes sense. And yes, these things usually come with more corner cases than expected (this whole implementation doesn't even assume empty buffers are possible somewhere in the middle).

During the tests I've noticed this implementation doesn't panic if the request is longer than all the buffers put together. That is probably allowed, because the advance allows for non-panicking and copy_to_bytes doesn't have any note about panicking. But I think it would be better if it panicked. There are few possibilities:

  • Leave it as it is (+ add test for that it doesn't panic and takes the whole rest)
  • Add a trivial test at the top of the relevant block. But that one will call .remaining() which iterates through all the buffers one more time, which could be a bit slower.
  • Do the check after the copying is done, as the Bytes::remaining() is likely something much faster. The downside is, the data has already been consumed so we could either put it back (push_front), at the cost of added code complexity, or say that after a panic, the structure is in some unknown state anyway.
  • Port keeping pre-computed remaining length from the version I've written. The downside is added code complexity.
  • Use that ⬆️ as a dependency. But it's a 0.1 crate (though I don't expect breaking the API of this particular type), it's additional dependency, and your code has some actual benchmarks around this type.

So I'd like to know which option you'd prefer.

@seanmonstar
Copy link
Member

The default implementation does panic: https://docs.rs/bytes/1.0.1/src/bytes/buf/buf_impl.rs.html#816

It seems like we can just add the check to the _ => branch, since the other 2 would be delegating to another implementation that can do that same check.

Some implementations of the Buf trait have an optimized version (for
example Bytes) of copy_to_bytes, opportunistically use that one.
@vorner
Copy link
Contributor Author

vorner commented Feb 2, 2021

The default implementation does panic

I know. I was just saying that an implementation is probably not required to panic in that situation.

As for the check, I was probably stressing too much over the fact that remaining iterates over all the inner buffers while IMO remaining should be cheap… but then, the default implementation did it too.

Copy link
Member

@seanmonstar seanmonstar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work, thank you!

@seanmonstar seanmonstar merged commit 4d2125c into hyperium:master Feb 3, 2021
@vorner vorner deleted the buflist-copy-to-bytes branch February 4, 2021 19:30
BenxiangGe pushed a commit to BenxiangGe/hyper that referenced this pull request Jul 26, 2021
Some implementations of the Buf trait have an optimized version (for
example Bytes) of copy_to_bytes, opportunistically use that one.
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.

2 participants