- Currently @ SentinelOne (we are hiring)
- A nerd since 1968, a computer geek since 1978
- GNU/Linux, KDE, GNU/Emacs, Python … Rust
- Rust resources
- Rust for Pythonistas / Robert Collinse Kiwi Pycon 2016
- Extending Python with rust / Samuel Cormier-Iijima Pycon Canada 2016
A system programming C’s like: speed + control Python’s like: safety + expressive power
- Minimal Runtime (no G/C)
- Low level control over H/W
- Suitable for writing O/S and web browsers:
An operating system for learning
Redox is a Unix-like Operating System written in Rust, aiming to bring the innovations of Rust to a modern microkernel and full set of applications
Servo is a modern, high-performance browser engine designed for both application and embedded use.
Fast + Safe + Concurrent
- Zero const abstractions* (@ compile time)
- Static dispatching
- Stack allocation
- Get us to a C/C++ speed
- No garbage collection
#!/usr/bin/env python3.4
def fib(n: int) -> int:
if n < 3:
return 1
else:
return fib(n-1) + fib(n-2)
if __name__ == '__main__':
print("%s" % fib(38))
fn fib(n: u64) -> u64 {
if n < 3 {
1
} else {
fib(n-1) + fib(n-2)
}
}
fn main() {
println!("{}", fib(38));
}
➜ time ./fib_py.py
39088169
./fib_py.py 12.02s user 0.01s system 98% cpu 12.229 total
➜ time ./fib_rs
39088169
./fib_rs 0.35s user 0.00s system 99% cpu 0.355 total
Fixing Python Performance with Rust / Armin Ronacher
Sentry processes over a billion errors every month. We’ve been able to scale most of our systems, but in the last few months, one component has stood out as a computational chokepoint: Python’s source map processing.
…
As of yesterday, we have dramatically cut down that processing time (and CPU utilization on our machines) by replacing our source map handling with a Rust module that we interface with from Python.
Automatic memory management
- but no G/C
Formally defied
- lifetime
- ownership,
- mutability,
No data races
{
let v = vec![1, 2, 3];
} // lifetime ends
let v = vec![1, 2, 3]; // v owns the Vec<i32>
let u = v; // ownership *moved* to u
let t = v; // ERROR: used moved value: `v`
let v = vec![1, 2, 3]; // v owns the Vec<i32>
let w = &v; // w borrow from v
let t = &v; // OK
fn print(v: Vec<i32>) {
println!("{:?}", v);
}
fn main() {
let v = vec![1, 2, 3];
print(v);
print(v); // ERROR: used moved value: `v`
}
fn print(v: &Vec<i32>) {
println!("{:?}", v);
}
fn main() {
let v = vec![1, 2, 3];
print(&v);
print(&v); // OK
}
#[derive(Copy, Clone)]
struct Rectangle {
height: f64,
width: f64,
}
fn main() {
let r1 = Rectangle {
height: 42.0,
width: 3.14,
};
let r2 = r1; // Copy
}
let v = vec![1, 2, 3];
v.push(4); // ERROR
let mut v = vec![1, 2, 3];
v.push(4); // OK
fn mutate(v: &Vec<i32>) {
v.push(4); // ERROR: cannot borrow immutable borrowed content `v` as mutable
}
fn main() {
let v = vec![1, 2, 3];
mutate(&v);
}
fn mutate(v: &mut Vec<i32>) {
v.push(4);
}
fn main() {
let mut v = vec![1, 2, 3];
mutate(&mut v);
}
let mut v = vec![1, 2 ,3];
let u = &v;
let t = &v;
let mut s = &v; // ERROR: cannot borrow `v` as mutable because it is also borrowed as immutable
fn main() {
let mut u: &Vec<i32>;
{
let mut v = vec![1, 2, 3];
u = &v; // ERROR: `v` does not live long enough
}
}
import string
def is_pangram(text):
alphabet = set(iter(string.lowercase))
return alphabet.issubset(set(c.lower() for c in text))
use std::collections::HashSet;
pub fn is_pangram(sentence: &str) -> bool {
let alphabet = "abcdefghijklmnopqrstuvwxyz".chars().collect::<HashSet<_>>();
alphabet.is_subset(&sentence.to_lowercase().chars().collect::<HashSet<_>>())
}
import string
def is_pangram(text):
alphabet = set(string.lowercase)
return alphabet.issubset(set(text.lower()))
use std::collections::HashSet;
pub fn is_pangram(sentence: &str) -> bool {
let alphabet = "abcdefghijklmnopqrstuvwxyz".chars().collect::<HashSet<_>>();
alphabet.is_subset(&sentence.to_lowercase().chars().collect::<HashSet<_>>())
}
- The type system: struct + enum
- Pattern matching: match
- Static duck typing: traits + Generics
- Concurrency: std::sync, Rayon, Tokio, …
- Tooling: cargo, rustdoc, rustup, …
- Ecosystem: Community + https://craits.io
- Rust progress: 1.0 2015/05→ 1.14 2016/12
- Rust ❤ Python: FFI, rust-cpython
Content left out of the presentation:
fn main() {
println!("Hello, world!");
}
➜ rust cargo new –bin hello Created binary (application) `hello` project ➜ rust cd hello
➜ hello git:(master) ✗ tree . ├── Cargo.toml └── src └── main.rs
1 directory, 2 files
➜ hello git:(master) ✗ cat Cargo.toml
[package]
name = "hello"
version = "0.1.0"
authors = ["Chen Rotem Levy <[email protected]>"]
[dependencies]
➜ hello git:(master) ✗ cat src/main.rs
fn main() {
println!("Hello, world!");
}
➜ hello git:(master) ✗ cargo run Compiling hello v0.1.0 (file:///home/chen/src/rust/hello) Finished debug [unoptimized + debuginfo] target(s) in 2.76 secs Running `target/debug/hello` Hello, world!
#[derive(Debug)]
struct X;
fn main() {
let x = X;
let y = x;
let z = x; // error[E0382]: use of moved value: `x`
}
error[E0382]: use of moved value: `x`
--> main.rs:7:9
|
6 | let y = x;
| - value moved here
7 | let z = x;
| ^ value used here after move
|
= note: move occurs because `x` has type `X`,
which does not implement the `Copy` trait
$ rustc --explain E0382 | wc
61 287 1695
zv* So
fn print_x(x: X) -> X {
println!("x: is {:?}", X);
x
}
fn main() {
let x = X;
x = print_x(x);
let y = x;
}
fn print_x(x: &X) {
println!("x: {:?}", x);
}
fn main() {
let x = X;
foo(x);
let y = x;
}
- Well defined sharing semantics
- Future library
- bool
- char
- i8/i16/i32/i64/isize
- u8/u16/u32/u64/usize
- f32/f64
- Tuples: (A, B, C, …)
- Arrays: [T; usize]
- Slice: &[T]
- String slice: &str
- Function: fn(A, B, …) -> X
struct Person {
String: name,
}
impl Person {
fn greet(&self) {
println!("Hello, {}", self.name);
}
}
`
enum Option {
Some(i32),
None,
}
fn check_option(op: &Option) {
match(*op) {
Some(n) => println!("We got a value {}", n),
None => println!("Sorry, no value here"),
}
}
struct Rectangle {
widnth: f64;
length: f64;
}
impl Rectangle {
fn new(w: f64, l: f64) -> Rectangle {
Rectangle { widnth: w, length: l }
}
fn area(&self) -> f64 {
self.length * self.height
}
}
use std::fmt::{Display, Formatter, Result}
impl Display for Rectangle {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "{} x {}", self.length, self.height)
}
}
Python | Rust |
---|---|
dynamic typed | static typed |
dynamic dispatch | static dispatch |
big runtime | small runtime |
Python | Rust |
---|---|
pip/setup-tools | cargo |
pypi | crates.io |
- self
- string formatting
- Unicode strings
- 1_000_000