Skip to content

Miri is slow on what should be a straightforward program #4616

@folkertdev

Description

@folkertdev

This issue came up when chatting with @oli-obk. I fully understand that miri is not meant to be a fast interpreter, but small changes have delivered big performance wins in the past, so perhaps this example just hits some particular edge case that has a simple fix. The slow runtime (much worse on CI machines) limits how much we can use miri in practice.

git clone git@github.com:trifectatechfoundation/zlib-rs.git
cd zlib-rs
cargo +nightly miri nextest run --run-ignored=ignored-only deflate_init_uninitialized

the test in question only initializes the decompression state, and then disposes of it again. No data is actually compressed. The state is a bit over 3000 bytes on the stack. The initialization also allocates and zeroes a bunch of memory (on the order of 128kb). Otherwise it doesn't do anything particularly weird or computationally expensive:

#[test]
#[cfg_attr(miri, ignore = "slow")]
fn deflate_init_uninitialized() {
    use libz_rs_sys::*;

    unsafe {
        let mut strm = MaybeUninit::<z_stream>::uninit();

        core::ptr::write(
            core::ptr::addr_of_mut!((*strm.as_mut_ptr()).zalloc).cast(),
            zlib_rs::allocate::C.zalloc,
        );

        core::ptr::write(
            core::ptr::addr_of_mut!((*strm.as_mut_ptr()).zfree).cast(),
            zlib_rs::allocate::C.zfree,
        );

        core::ptr::write(
            core::ptr::addr_of_mut!((*strm.as_mut_ptr()).opaque),
            core::ptr::null_mut(),
        );

        let err = deflateInit_(
            strm.as_mut_ptr(),
            6,
            zlibVersion(),
            core::mem::size_of::<z_stream>() as _,
        );
        assert_eq!(err, Z_OK);

        let err = deflateEnd(strm.as_mut_ptr());
        assert_eq!(err, Z_OK);
    }
}

This test takes about 10s to run in isolation on my dev machine (running it alongside other tests slows it down further):

> cargo +nightly miri nextest run --run-ignored=ignored-only deflate_init_uninitialized
    Finished `test` profile [optimized + debuginfo] target(s) in 0.02s
info: for the target platform, using target runner `/home/folkert/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner` defined by `target.cfg(all()).runner` specified by `--config`
info: for the host platform, using target runner `/home/folkert/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner` defined by `target.cfg(all()).runner` specified by `--config`
    Starting 1 test across 4 binaries (291 skipped)
        PASS [  10.928s] test-libz-rs-sys null::deflate_init_uninitialized

Actually compressing the string "Ferris" adds 5 seconds to the runtime:

> cargo +nightly miri nextest run --run-ignored=ignored-only ferris_bytes
    Finished `test` profile [optimized + debuginfo] target(s) in 0.02s
info: for the target platform, using target runner `/home/folkert/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner` defined by `target.cfg(all()).runner` specified by `--config`
info: for the host platform, using target runner `/home/folkert/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/cargo-miri runner` defined by `target.cfg(all()).runner` specified by `--config`
    Starting 1 test across 4 binaries (291 skipped)
        PASS [  15.003s] test-libz-rs-sys null::ferris_bytes
------------
     Summary [  15.004s] 1 test run: 1 passed, 291 skipped

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-interpreterArea: affects the core interpreterI-slowImpact: Makes Miri even slower than it already is

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions