Presented by Dorian Puła @ PyCon Canada 2019
Photo © 2010 Colin - https://www.flickr.com/photos/48625620@N00/4446021223/
Dorian Puła (@dorianpula)
Software Developer @ Points
Open Source
Photo © 2010 Colin - https://www.flickr.com/photos/48625620@N00/4446021223/
An innovative systems-level language that helps
with writing memory safe, fast and reliable code.
Photo © 2010 Colin - https://www.flickr.com/photos/48625620@N00/4446021223/
Rust
fn convert_to_fahrenheit(celsius: f32) -> f32 {
celsius * 1.8 + 32.0
}
#[cfg(test)]
mod tests {
use super::{convert_to_fahrenheit, Temperature};
#[test]
fn conversion_celsius_to_fahrenheit() {
assert_eq!(convert_to_fahrenheit(25.0), 77.0);
}
}
Python
import unit_converter
def test_using_unit_converter():
assert unit_converter.convert_to_fahrenheit(25.0) == 77.0
Rust
struct Temperature {
celsius: f32,
}
impl Temperature {
fn to_fahrenheit(&self) -> f32 {
self.celsius * 1.8 + 32.0
}
fn windchill(&self, wind_speed_kph: f32) -> f32 {
13.12 + (0.6215 * self.celsius) - (11.37 * wind_speed_kph.powf(0.16))
+ (0.3965 * self.celsius * wind_speed_kph.powf(0.16))
}
}
Python
import unit_converter
def test_using_unit_converter():
temperature = unit_converter.Temperature(25.0)
assert temperature.to_fahrenheit() == 77.0
def test_windchill():
temperature = unit_converter.Temperature(-20.0)
assert round(temperature.windchill(32.0), 1) == -32.9
Photo © 2010 Colin - https://www.flickr.com/photos/48625620@N00/4446021223/
Add pyo3 dependencies to Cargo.toml
pip install maturin
#![feature(specialization)]
#[macro_use] extern crate pyo3;
use pyo3::prelude::*;
#[pyfunction]
pub fn convert_celsius_to_fahrenheit(celsius: f32) -> f32 {
celsius * 1.8 + 32.0
}
#[pymodule]
fn unit_converter(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_pyfunction!(convert_celsius_to_fahrenheit))?;
Ok(())
}
// ... Test code below ...
#![feature(specialization)]
#[macro_use]
extern crate pyo3;
use pyo3::prelude::*;
#[pyclass(module = "unit_converter")]
struct Temperature { celsius: f32 }
#[pymethods]
impl Temperature {
#[new]
fn new(obj: &PyRawObject, temperature: f32) {
obj.init(
Temperature { celsius: temperature }
);
}
fn to_fahrenheit(&self) -> f32 { self.celsius * 1.8 + 32.0 }
// Windchill function truncated for clarity.
}
#[pymodule]
fn unit_converter(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_class::<Temperature>()?;
Ok(())
}
Embedded Unit Conversion Example:
Photo © 2010 Colin - https://www.flickr.com/photos/48625620@N00/4446021223/
Using pytest-benchmark to compare against a Python implementation...
What about batching the calculations?
PyO3 has a better example with parallel word count.
----------------------------------------------------------------------------------------------------
Name (time in us) Min Max Mean
----------------------------------------------------------------------------------------------------
test_pure_python_once_numba 292.0990 (1.0) 317.7590 (1.0) 296.7477 (1.0)
test_numpy_numba 326.2470 (1.12) 526.1350 (1.66) 338.1704 (1.14)
test_rust_bytes_once 336.0620 (1.15) 1,053.0090 (3.31) 342.5122 (1.15)
test_c_swig_bytes_once 375.6310 (1.29) 1,389.9070 (4.37) 388.9181 (1.31)
test_rust_once 986.0360 (3.38) 2,498.5850 (7.86) 1,006.5819 (3.39)
test_numpy 1,137.1750 (3.89) 2,000.5430 (6.30) 1,167.2551 (3.93)
test_rust 2,555.1400 (8.75) 3,645.3900 (11.47) 2,592.0419 (8.73)
test_regex 22,597.1750 (77.36) 25,027.2820 (78.76) 22,851.8456 (77.01)
test_pure_python_once 32,418.8830 (110.99) 34,818.0800 (109.57) 32,756.3244 (110.38)
test_pure_python 43,823.5140 (150.03) 45,961.8460 (144.64) 44,367.1028 (149.51)
test_python_comprehension 46,360.1640 (158.71) 50,578.1740 (159.17) 46,986.8058 (158.34)
test_itertools 49,080.8640 (168.03) 51,016.5230 (160.55) 49,405.2562 (166.49)
----------------------------------------------------------------------------------------------------
Counting double letter pairings example more thorough
Photo © 2010 Colin - https://www.flickr.com/photos/48625620@N00/4446021223/
Questions?