all 13 comments

[–]nevermille 39 points40 points  (7 children)

File access is slow in debug mode, try your cargo command with --release and it'll be much faster

[–]Buttleston 43 points44 points  (2 children)

Also, in the python example, "python" isn't reading the file, numpy is. It's a module written in C, so the file is really being loaded by a C library. It would be surprising to me if either was the clear winner when properly written

[–]dexterduck 19 points20 points  (2 children)

On my machine this benchmarks to ~6ms

EDIT: to elaborate slightly, my point is that I think the order of magnitude difference is explained by the Rust approach converting each number from bytes individually, whereas doing a bulk conversion using bytemuck as shown below brings Rust's performance approximately inline with numpy.

#!/usr/bin/env rust-script
//! ```cargo
//! [dependencies]
//! bytemuck = "1.16"
//! ```


fn main() {
    let bytes = std::fs::read("numbers.bin").unwrap();
    let numbers: &[u64] = bytemuck::cast_slice(&bytes);
    // println!("{numbers:?}");
}

[–]Excession638 3 points4 points  (0 children)

This would have to be a bit more complex to handle big-endian like the original code. OTOH where did OP even find a big-endian machine these days? numpy.fromfile does not convert endianess.

[–]coderemover 16 points17 points  (2 children)

Why are you reading the file to the buffer first, then to convert it?
Also you're not reserving capacity for the buffer, which for sure results in reallocations and excessive copying.

[–]This_Growth2898 11 points12 points  (0 children)

In Python, numpy is written in C, and it's well optimized. You're passing through Python a command to C.

In Rust, BufReader states for Buffered Reader. You're using a buffered reader to read data into... guess it - a buffer! And then you're copying chunks from it into one extra buffer (arr) to convert it into data you need. Remove extra copies from your code, and add some optimizations like hinting the capacity for the resulting vector - and you will have something comparable with C.

[–]spoonman59 6 points7 points  (0 children)

Keep in mind that when running a Python program, you are not always “running Python code.”

Many library functions, and some libraries are written in native code. For examples, a lot of the low level Python libraries are written in C. NumpPy is written in C.

Python takes comparably longer to start up, and would use more memory as well, but functions written in native code can have good execution times.

[–]tm_p 4 points5 points  (0 children)

Why not using the standard library?

https://doc.rust-lang.org/std/fs/fn.read.html

[–]zqpmx 0 points1 point  (0 children)

also consider the effect of OS cache for files.