BeastCoding
By Tobias Kriebisch
on

Since PHP is morphing more and more into a static typed language, even if it is optional. I wanted to try out something that embraces types and performance as a first class citizen. Rust also has a pretty good reputation, so I went with it.

To get started, I wanted to write a simple, a few lines long program that can calculate the Fibonacci number in a certain position in the Fibonacci sequence.

So I came up with:z

fn fibonacci_u64(number: u64) -> u64 {
    let mut last: u64 = 1;
    let mut current: u64 = 0;
    let mut buffer: u64;
    let mut position: u64 = 1;

    return loop {
        if position == number {
            break current;
        }

        buffer = last;
        last = current;
        current = buffer + current; 
        position += 1;
    };
}

Being able to return something directly from a loop is a nice feature. It is pretty easy to read too.

Testing

For a PHP/Laravel developer, testing is almost a requirement to trust what you wrote, so I naturally wanted to write a test. Conveniently, rust has built in support for testing.

In the same file, you can add a module dedicated to testing:

#[cfg(test)]
mod tests {
    use super::*; // load also functions from the actuall code

    #[test]
    fn u64() {
       assert_eq!(fibonacci_u64(1), 0); 
       assert_eq!(fibonacci_u64(2), 1); 
       assert_eq!(fibonacci_u64(12), 89); 
       assert_eq!(fibonacci_u64(30), 514229); 
    }
}

With cargo test this will be compiled with extra safety checks like overflow tests and complain or give you green. It is a really seamless experience

Benchmarking

For fun I also tested an experimental feature of rust the cargo bench command that will benchmark your application. It is almost the same as writing tests.

As of writing you have to enable rust nightly features for this

#[cfg(test)]
mod tests {
    use super::*;
    use test::{Bencher,black_box};

    #[bench]
    fn bench_u64(b: &mut Bencher) {
        b.iter(|| {
            for i in 1..20 {
                black_box(fibonacci_u64(i));
            }
        });
    }

    #[bench]
    fn bench_u128(b: &mut Bencher) {
        b.iter(|| {
            for i in 1..20 {
                black_box(fibonacci_u128(i));
            }
        });
    }
}

This will output something like:

test tests::bench_u128 ... bench:           8 ns/iter (+/- 0)
test tests::bench_u64  ... bench:           4 ns/iter (+/- 0)

It looks like u128 takes double the time that u64 does on my machine. Seems correct, but it might be totally wrong and I missed something.

Conclusion

Rust looks nice and extremely thought through, for this little program. The cargo features are so far amazing. I am looking forward to a little bigger project.