Skip to content

Array copy const fn is surprisingly slow #92511

Open
@nico-abram

Description

@nico-abram

The following program is surprisingly slow, taking over 10 seconds to compile on my machine, even with -Zmir-opt-level=3

#![feature(const_eval_limit)]
#![const_eval_limit = "10000000"]
fn main() {
    const MB: usize = 1024 * 1024;
    const L: usize = MB;
    const DATA: [u8; L] = [3; L];
    const TEST: [u8; L] = test(&DATA);

    const fn test(data: &[u8]) -> [u8; L] {
        let mut ret = [0u8; L];
        let mut i = 0;
        loop {
            if i >= data.len() {
                break;
            }
            ret[i] = data[i];
            i = i + 1;
        }
        ret
    }
    println!("{}", TEST[1024]);
}

I wrote a const fn bmp parser and when I tried using it on a 6mb 1080x1920 image it made cargo check take 10+ minutes, and it is mostly copying an array element by element. I wrote this small sample for which I think the problem is basically the same. The full thing is here if anyone wants to look at it https://gist.github.com/nico-abram/21087e54d21883fd2d72eeee55675d6a

The following version using ptr::copy_nonoverlapping is much faster, taking under 2 seconds on my machine for a 7 MiB array.

#![feature(const_mut_refs)]
#![feature(const_intrinsic_copy)]
fn main() {
    const MB: usize = 1024 * 1024;
    const L: usize = 7 * MB;
    const DATA: [u8; L] = [3; L];
    const TEST: [u8; L] = test(&DATA);

    const fn test(data: &[u8]) -> [u8; L] {
        let mut ret = [0u8; L];
        unsafe { std::ptr::copy_nonoverlapping(data.as_ptr(), &mut ret as *mut _, data.len()) };
        ret
    }
    println!("{}", TEST[1024]);
}

nightly version used: rustc 1.59.0-nightly (f8abed9 2021-12-26)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-arrayArea: `[T; N]`

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions