Why calling python from rust is faster than python

using PyO3 give power to python and make it faster, but I do not understand why, should not it be same as calling python file!

Appreciate to get this explained, why calling script code from compiled code make it faster?

I just tried this code:

#![feature(proc_macro_hygiene)]
use inline_python::python;

fn main() {
    println!("Hello, Rust!");

    python! {
        import cv2
        
        print("Hello, Python")
        print(cv2.__version__)
    }
}

And could not understand why it is faster than this one:

python cv.py
import cv2

print("Hello, Python")
print(cv2.__version__)

image

Are you sure it is faster, and that it is not just measurement noise?

1 Like

Actually I'm not, I read it should be faster, tried to check, not sure about the results and about the reason.

You should put that test into a loop a thousand of times and take the average. Than you'd have a more precise result.

Assuming it is faster, one reason could be that the macro can do something like embedding the corresponding pyc file instead of a py file. I don't know how it actually works, but this is a possibility.

2 Likes

Thanks, my concern now is to get general understanding of calling script code from compiled code

Well, it looks it is not that deal, with running a loop 100_000_000 times, python alone is faster!

#![feature(proc_macro_hygiene)]
use inline_python::python;

fn main() {
    println!("Hello, Rust!");

    python! {
        import cv2

        print("Hello, Python")
        print(cv2.__version__)
        for x in range(1, 100000000, 1):
            print(x)
    }
}

image

I don't think that's what @alice meant.

To make sure your original measurements of Rust taking 187ms and Python taking 203ms are accurate and not just noise, you should run the same Measure-Command test several thousand times and look at the statistics.

I don't know whether Measure-Command will run the command several times and take an average for you, but if not I've heard great things about using hyperfine to measure performance for command-line programs.

5 Likes

Thanks, I used hyperfine for loops of 1_000, 10_000, 100_000 and 1_000_000 and looks calling Python from Rust is slightly faster than Python directly, but whay?

It's impossible to say for certain without profiling both, but it's possible that the python interpreter has to spend more time on things like filesystem calls and file I/O.

2 Likes

Maybe it's the difference of having to read the cv.py file, especially when stuff like virus scanners get involved, versus having that source embedded in the rust executable.

5 Likes

My two cents is that the Python interpreter needs to compile the high-level Python code to bytecode each time it runs (which takes time).

But that Rust already compiles the included Python script to bytecode when it is build, so when actually running the Rust script you're saving time by not needing to compile your Python script to bytecode anymore.

Not sure though.

Maybe @kngwyu knows more about this (contributer of Pyo3).

Looks inline-python precompiles Python string to byte codes in their proc-macro code.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.