Skip to content

Inline fail! causes significant slowdown in write() #14485

Closed
@mahkoh

Description

@mahkoh

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    I-compiletimeIssue: Problems and improvements with respect to compile times.I-slowIssue: Problems and improvements with respect to performance of generated code.P-lowLow priority

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions