DEV Community

Lorenzo (Mec-iS)
Lorenzo (Mec-iS)

Posted on • Updated on

Rust-scales Python: Some examples (1)

Please read the first part of this post before going on with this one.

Introduction

In the first post of this series I displayed the basic commands needed to leverage python-ext-wasm. Wasmer.io is a project aiming to provide a streamlined solution to allow compilation and usage of "Universal Binaries" via WebAssembly; python-ext-wasm is a library that provides binding from Python to compiled binaries so that in future any Python developer can take advantage of all the incredible WebAssembly features by keeping writing Python code.

Environment and assumptions

As described in the previous post we work with a diverse setup without leaving behind ergonomics and ease-of-use. The basics components for starting experimenting are Rust (and cargo) and Python. I have spotted some functions that are going to be our targets for the sake of exercise with the workflow and also provide some basic measures of how useful the Wasmer.io approach is and will be. These functions are written in Rust:

  1. a simple addition function:

    pub extern fn simple_add(a: i32, b: i32) -> i32 { a + b}
    
  2. a Fibonacci series implementation, one of the many you may have used while trying to exercise your coding skills (credits here):

    #[no_mangle]
    pub extern fn fibo(n: i32) -> i32 {
    if n < 0 {
        panic!("{} is negative!", n);
    } else if n == 0 {
        panic!("zero is not a right argument to fibonacci()!");
    } else if n == 1 {
        return 1;
    }
    
    let mut sum = 0;
    let mut last = 0;
    let mut curr = 1;
    for _i in 1..n {
        sum = last + curr;
        last = curr;
        curr = sum;
    }
    sum
    }
    
  3. The function used to compute Convex Hull over a set of Cartesian points, as taken from Rust geo

    use geo::{Polygon, LineString};
    use geo::convexhull::ConvexHull;
    ///
    /// Constructive operations: Convex hull in Rust Geo
    ///
    #[no_mangle]
    pub extern fn rust_geo_convex_hull() -> () {
    // An L shape
    let coords = vec![
        (0.0, 0.0),
        (4.0, 0.0),
        (4.0, 1.0),
        (1.0, 1.0),
        (1.0, 4.0),
        (0.0, 4.0),
        (0.0, 0.0)];
    // conversions to geo types are provided from several kinds of coordinate sequences
    let poly = Polygon::new(coords.into(), vec![]);
    
    // uses the QuickHull algorithm to calculate the polygon's convex hull
    let hull = poly.convex_hull();
    

I picked these functions so that is possible to compare them with their own functionally equivalent counterparts in Python that you can find coded here:

  1. the most basic addition function in Python
  2. a Fibonacci implementation taken from SO that uses a while loop (as the Rust implementation above using a for-loop)
  3. the Convex Hull implementation as provided by shapely, one of the most popular Python geolibrary (pip install shapely[vectorized]). The same input has been passed as in its Rust counterpart.

Running the tests

If you have already your Python virtual environment up with the requirements installed, and you follow the simple instructions in the previous post, you may be able to clone the repo and try on your own:

  • in the root directory, do your cargo build --target wasm32-unknown-unknown to compile your universal binary with the Rust functions above;
  • in timing directory run python run_timing_collection.py. This is a series of timeit calls that time both implementations for each function

This is the outcome as printed by my machine listing the Python function timing and the Wasm function timing over some thousands of iterations:

Modules exported from Rust: 
["loop_str", "rust_geo_convex_hull", "fibo", "simple_add"]
py add 1.2614150420049555
t_wasm add 8.43558448299882
py fibo 44.35585713999899
t_wasm fibo 1.240821371000493
py shapely convex hull 47.863506109999435
t_wasm rust-geo convex hull 2.2532036840057117
Enter fullscreen mode Exit fullscreen mode

You should also find some data in timing/data/timing.csv

Disclaimer: I do not assume that this is a proper benchmark but more an exercise, so I do not expect the results to be accurate but only to give a general indication of trends.

Conclusion

I would be glad to receive more data from different setups. If you want you can just drop a comment with the results printed out by your machine; just copy/paste the last line in your timing.csv to help with some data.

Thanks to all the OpenSource maintainers that made this short experiment possible.

Top comments (3)

Collapse
 
moshemalawach profile image
Moshe Malawach

How do you handle strings?

Is there some helpers to easily pass strings both ways?

Thanks

Collapse
 
tuned profile image
Lorenzo (Mec-iS)

You can find some utils for string processing here

Collapse
 
tuned profile image
Lorenzo (Mec-iS)

thanks for asking. good subject for the next post.