DEV Community

arn-the-long-beard
arn-the-long-beard

Posted on

How to only Rust for web front_end - test & bench

4 - Let's try test & benchmark

Let's test that thing

Let's add the following in Cargo.toml

Cargo.toml

[dev-dependencies]
wasm-bindgen-test = "0.3"

Let's make a test file

./tests/web.rs


//! Test suite for the Web and headless browsers.

#![cfg(target_arch = "wasm32")]

extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;

extern crate seeded_game_of_life;
use seeded_game_of_life::universe::Universe;
wasm_bindgen_test_configure!(run_in_browser);

#[wasm_bindgen_test]
fn pass() {
    assert_eq!(1 + 1, 2);
}

#[cfg(test)]
pub fn input_spaceship() -> Universe {
    let mut universe = Universe::new();
    universe.set_width(6);
    universe.set_height(6);
    universe.set_cells(&[(1, 2), (2, 3), (3, 1), (3, 2), (3, 3)]);
    universe
}

#[cfg(test)]
pub fn expected_spaceship() -> Universe {
    let mut universe = Universe::new();
    universe.set_width(6);
    universe.set_height(6);
    universe.set_cells(&[(2, 1), (2, 3), (3, 2), (3, 3), (4, 2)]);
    universe
}

#[wasm_bindgen_test]
pub fn test_tick() {
    // Let's create a smaller Universe with a small spaceship to test!
    let mut input_universe = input_spaceship();

    // This is what our spaceship should look like
    // after one tick in our universe.
    let expected_universe = expected_spaceship();

    // Call `tick` and then see if the cells in the `Universe`s are the same.
    input_universe.tick();
    assert_eq!(&input_universe.get_cells(), &expected_universe.get_cells());
}


wasm-pack test --firefox and then click on the address and you should see the test in firefox

You can do the same if you have Chrome on your computer of course :)

At the moment, since today 29/07/2020

wasm-pack test --firefox --headless seems to fail. I made an issue about it there https://github.com/rustwasm/wasm-bindgen/issues/2261

Anyway testing is easy and we can also make standard tests as well

tests/universe.rs

#[cfg(test)]
mod tests {
    use seeded_game_of_life::universe::Universe;

    #[test]
    fn big_bang_works() {
       let universe = Universe::new();


        assert_eq!(universe.width(),64);
        assert_eq!(universe.height(),64);
    }
}

Let's bench it !

rustup default nightly

We need the Darkside if we want to use some features for benchmarking.

./benches/bench.rs

#![feature(test)]
extern crate seeded_game_of_life;
extern crate test;

use seeded_game_of_life::universe::Universe;

#[bench]
fn universe_ticks(b: &mut test::Bencher) {
    let mut universe = Universe::new();

    b.iter(|| {
        universe.tick();
    });
}

You should have something like this

Finished bench [optimized] target(s) in 5.83s
     Running target/release/deps/seeded_game_of_life-e5bb887774c98fd8

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/release/deps/bench-a3412253977e35f0

running 1 test
test universe_ticks ... bench:      38,410 ns/iter (+/- 29,201)

test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured; 0 filtered out

NB : There are few differences here compare to the original tutorial :

We also have to comment out all the #[wasm_bindgen] annotations, and the "cdylib" bits from Cargo.toml or else building native code will fail and have link errors.

  • No need to care about #[wasm_bindgen]
  • No need to remove "cdylib"

Probably because of the Seed magic, our rust code does not need the tag, so it is easier :D

Now if we compare to a javascript version of the code base :

  • No need to find a library like jest/mocha or other to make test because rust has everything we need :D
  • Tags and tools are there to target which kind of test we do
  • Benchmark code as native gives us easy overview of performance ( I never had such opportunity in js/ts) , can use perf on Linux

To resume, test & benchmark were already easy because of Rust, now it is even more easier since there is only Rust <3 . Thank you Seed !

5 - How to improve performances

Of course, there are many ways to improve the performances.

  • Take care more of what we are doing in the code:

    • correct type ?
    • conversion ?
    • call to DOM ?
    • follow the doc :D
  • Making a specific build for release:

    • small compiled code strategy
    • faster runtime strategy

Now in the code we have, we could actually remove every code like document() or canvas() and use Ref and access their state in the M̀odel

We can also use options for building as mentioned in the original tutorial. Let's try it!

Cargo.toml

[profile.release]
lto = true
opt-level = 'z'
codegen-units = 1

[package.metadata.wasm-pack.profile.release]
wasm-opt = ['-O3']

You can now run cargo make build_release

After refreshing your web browser, you will see that you are at 60 fps always with this size of grid and max ticks.
For me going from 40fps --ish to 60 is a nice improvement :D

You can try to compare the different generated packages if you want with the help of the tutorial

6 - Conclusion

There is much to say :D and I already talked/wrote sooo much :P

We just have shown together with this post that we can use Rust only ( with still html +css of course ) to code web front_end work.

From a personal point of view, I think of Rust as a language like Latin or Icelandic:

  • It can be very short and effective and sometimes very long because of the possibilities to add much context and details that enhance the sens of it.
  • Gives more control and nuances on what we need to say, write and communicate.

Rust is rich and powerful with a compiler who moves so many errors and bugs from run_time to compile_time.

  • It asks us to be better programmers & produce better code
  • It secures the code we produce
  • It really does indicate/encourage good practice and consistency ( Consistency in Javscript/Typescript even inside the same dev team is very hard to accomplish)
  • It makes you love and hate the compiler at the same time De l'amour à la haine, il n'y a qu'un pas :D

From a 5 years experience web-programmer that I am :

I really did enjoy my time with React/Redux. Especially redux, because it gives so much control and predictability over pure javascript. Same about Ngrx on Angular.
So I got a good time on React & Angular, but I also know all the pains, the endless maintenance and flood of dependencies to take care of in daily work.
They are part of my experience and I do not have any regret about them.
But now I have some friends who want to start Web stuff and the layer of complexity in Js/Ts/React/Angular∕vue environment are a huge gap to fight.

All the safety and paradigm ( & soo much more ) made by the front-end frameworks like React or Angular to make web development possible are now more accessible with Rust with much lighter abstraction.

Here are few of the many benefits I see by using Rust/Seed

  • One language for all logic
  • Less dependencies
  • Code robust and easy to predict & trust
  • We have state_management included
  • Visually more organized & structured code
  • Higher productivity
  • Compiler that helps us to build Robust/Solid Code
  • Less time to debug stuff
  • Much more predictability
  • Easy to maintain
  • One language for front_end & back_end
  • More control on performances
  • Probably better performances in the future also as well

We also have some challenges of course

  • IDEs still do not support all the disruptive concepts from Rust
  • Seed is not ready for production
  • We have still some generated js
  • No extension to watch the state at runtime in your web browser like our lovely redux-dev-tools can do
  • Not sure we can debug the code at runtime neither , but do we need it ?
  • No libraries available for specific needs, you will need to do it by yourself ( no UI library for now like Google Material or Bootstrap I think)

Here is the source code for this post.

Some parts of the code are gonna be updated and improved as I explained. I will do a new branch for that and link it below.

Rust + Seed made me happy to code again. It really make me feel to be part of a great adventure, meet new people, get new skills and discover new opportunities ! There is such much to build :)

Please guys, try & have fun & comment !!!

Top comments (0)