Closed
Description
Consider the following snippet:
#[inline(never)]
fn fail() {
fail!("assertion failed");
}
impl<'a, W: Writer> Writer for UnsafeWriter<'a, W> {
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
let dst = self.buf.mut_slice_from(self.pos);
if buf.len() > dst.len() {
fail();
}
unsafe {
copy_nonoverlapping_memory(dst.as_mut_ptr(), buf.as_ptr(), buf.len())
}
self.pos += buf.len();
Ok(())
}
fn flush(&mut self) -> IoResult<()> {
self.flush_buf().and_then(|()| self.inner.flush())
}
}
Inlining fail()
causes significant slowdown in the following program
https://gist.github.com/anonymous/48ba255d89c2f9bf636c
Inlined:
real 0m3.256s
user 0m3.237s
sys 0m0.020s
Non-inlined:
real 0m1.562s
user 0m1.537s
sys 0m0.023s
Compiled with -O
. The program is tested with time ./cat -v /tmp/blabla.txt > /dev/null
where the text file are 100MB of random data.
Note that core::slice::MutableVector::copy_memory
has the form
#[inline]
unsafe fn copy_memory(self, src: &[T]) {
let len_src = src.len();
assert!(self.len() >= len_src);
ptr::copy_nonoverlapping_memory(self.as_mut_ptr(), src.as_ptr(), len_src)
}
where assert! expands to something similar to the inlined fail!() version above. This function is used by some Writers.
cc @cmr