diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-05-09 18:34:56 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-05-09 18:34:56 +0200 |
| commit | 671dd0992faf936478f17dc79dcee25ea432fb53 (patch) | |
| tree | 205077cd626afb80f6afc08c131ef02b28e26685 /src/libstd | |
| parent | 26a7544aa306d1c22b57798ade4662bd51c3e306 (diff) | |
| parent | b9c430129d5971df4410b6c829b100ce8191328e (diff) | |
| download | rust-671dd0992faf936478f17dc79dcee25ea432fb53.tar.gz rust-671dd0992faf936478f17dc79dcee25ea432fb53.zip | |
Rollup merge of #60656 - petertodd:2019-inline-cursor-over-slice, r=sfackler
Inline some Cursor calls for slices
(Partially) brings back https://github.com/rust-lang/rust/pull/33921
I've noticed in some serialization code I was writing that writes to slices produce much, much, worse code than you'd expect even with optimizations turned on. For example, you'd expect something like this to be zero cost:
```
use std::io::{self, Cursor, Write};
pub fn serialize((a, b): (u64, u64)) -> [u8;8+8] {
let mut r = [0u8;16];
{
let mut w = Cursor::new(&mut r[..]);
w.write(&a.to_le_bytes()).unwrap();
w.write(&b.to_le_bytes()).unwrap();
}
r
}
```
...but it compiles down to [dozens of instructions](https://rust.godbolt.org/z/bdwDzb) because the `slice_write()` calls aren't inlined, which in turn means `unwrap()` can't be optimized away, and so on.
To be clear, this pull-req isn't sufficient by itself: if we want to go down that path we also need to add `#[inline]`'s to the default implementations for functions like `write_all()` in the `Write` trait and so on, or implement them separately in the `Cursor` impls. But I figured I'd start a conversation about what tradeoffs we're expecting here.
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/cursor.rs | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 64f8659b8f8..f627fb0f562 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -265,6 +265,7 @@ impl<T> BufRead for Cursor<T> where T: AsRef<[u8]> { } // Non-resizing write implementation +#[inline] fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<usize> { let pos = cmp::min(*pos_mut, slice.len() as u64); let amt = (&mut slice[(pos as usize)..]).write(buf)?; @@ -272,6 +273,7 @@ fn slice_write(pos_mut: &mut u64, slice: &mut [u8], buf: &[u8]) -> io::Result<us Ok(amt) } +#[inline] fn slice_write_vectored( pos_mut: &mut u64, slice: &mut [u8], @@ -341,6 +343,7 @@ impl Write for Cursor<&mut [u8]> { slice_write_vectored(&mut self.pos, self.inner, bufs) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -354,6 +357,7 @@ impl Write for Cursor<&mut Vec<u8>> { vec_write_vectored(&mut self.pos, self.inner, bufs) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -367,6 +371,7 @@ impl Write for Cursor<Vec<u8>> { vec_write_vectored(&mut self.pos, &mut self.inner, bufs) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } @@ -382,6 +387,7 @@ impl Write for Cursor<Box<[u8]>> { slice_write_vectored(&mut self.pos, &mut self.inner, bufs) } + #[inline] fn flush(&mut self) -> io::Result<()> { Ok(()) } } |
