-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Use simple io::Error for &[u8] Read and Write impl #42156
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
Conversation
This seems pretty reasonable to me I think. @rust-lang/libs Does anyone feel like the new errors will be too confusing? |
Nah this seems reasonable to me, especially because they're just an implementation on slices and not for the whole trait |
I’m not following the reasoning. You say:
AFAICT it only creates the … I guess what you describe does happen ONCE, when the actual failure case happens and the function returns the Error (the |
The sample code uses that to stop the loop. So yes, it happens at least once. Creating the common io::Error though involves a function call which the optimizer can't just remove (side effects, etc.) so stopping the loop is really expensive compared to the rest of the function. It's probably fair to accept this optimization as it's reading over the simplest readable type in the language. |
See, my point here is not about it being a bad optimisation to make, but about whether it is the right way to optimise this. Any This could also be fixed in general by fixing #24194 + a targeted #[inline] on a relevant constructor function. |
I confirmed that it could work if that issue is fixed [1]. We would need to mark the str/String Into<Box>> inline accordingly. Can we rely on that? [1] choose stable&release in http://play.integer32.com/?gist=dd721e339a507e560016b8baee698a60 doesn't work on nightly. |
@nagisa do you have an answer for @arthurprs's question here? |
To be clearer, can we rely on llvm to optimize out the error path allocations? Maybe it considers it might have side effects or something (like normal functions). |
I general you can’t rely on optimisations in any way at all. If you need some particular sequence of instructions, write them down in assembly. That being said, getting rid of the allocations here by constructing a different variant of the error enumeration and getting rid of the allocations here by a carefully placed inline hint are pretty much equivalent as far as reliability is concerned IMO. |
Fair enough. I suggesting using the simple io::Error then, it was created for this exact purpose. |
Ahh, maybe not... it's too specific. I'll probably close and we can revisit once #24194 is resolved. |
I'm not sure this change is gonna fly because of the worse error message (see end of post), but here's the case.
I was checking https://www.reddit.com/r/rust/comments/6cjs7u/analyzing_the_performance_of_a_hash/ and I pinpointed the cause of slowness to the io::read_exact implementation that byteorder read_u32 calls.
It turns out that the optimizer isn't smart enough to avoid the creation of the result altogether and creates a relatively costly io::Error just to discard it after (edit: reason being that creating an io::Error involves a function call and the optimizer can't blindly remove that side effect).
I played a bit with the code and if the code is simple enough (simple enum creation after the inlines) it optimizes out just as well as the version with the branch+unwrap().
Playground link for before: http://play.integer32.com/?gist=04569213693e4862ef1e13a19e408cd5
Playground link for after: http://play.integer32.com/?gist=3755fc64d339c81d8cb01ea41cc0862b
code
before
after
Error message changes: