Rust-scales Python: Some examples (1)
Tags: rust, webassembly, python
Published: 2019-07-07 16:38:30

---
title: Rust-scales Python: Some examples (1)
published: true
description: a continuation of Rust-scales Python: Basic Experiment
tags: rust, Wasm, Python, WebAssembly
series: Rust-scales Python with Wasmer
---

Please read the [first part of this post](https://dev.to/tuned/rust-scales-python-basic-experiment-49h0) before going on with this one.

## Introduction

In the [first post of this series](https://dev.to/tuned/rust-scales-python-basic-experiment-49h0) I displayed the basic commands needed to leverage [python-ext-wasm](https://github.com/wasmerio/python-ext-wasm/tree/master). 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:```rust
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](https://github.com/eliovir/rust-examples/blob/master/fibonacci.rs)):```rust
#[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](https://en.wikipedia.org/wiki/Convex_hull) over a set of Cartesian points, as taken from Rust [geo](https://github.com/georust/geo)```rust
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](https://github.com/Mec-iS/rust-wasm-python-101/blob/master/timing/src_py/__init__.py):

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](https://pypi.org/project/Shapely/) (`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](https://github.com/Mec-iS/rust-wasm-python-101) 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:
```bash
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
```
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.