Rust lang series episode #17 — dispatching (#rust-series)

in rust-series •  8 years ago  (edited)

Hello everyone, new episode of rust series is here, today we will discuss dispatching. Dispatching in Rust is a mechanism to determine which polymorph code to run. This can sound strange mysteriously but after few examples it will be clear. It basically means when you have something "hidden" behind trait, it resolves which and how implementation method will be called.

Rust supports two ways of dispatching:

  • static (monomorphization)
    • pros: supports function inlining, optimization and compilation-time checks, resolved at compile-time
    • cons: can bloat instruction cache
  • dynamic (trait objects)
    • pros: less bloated code
    • cons: slower virtual function calls, resolved during runtime

Implementing Loggable trait

Let's assume that we have some types we wish to "enhance" with Loggable trait which will provide log method. One of those will be Article, our well-known struct from other episodes. Others will be built-in types.

struct Article {
    id: i32,
    upvotes: i32
}

trait Loggable {
    fn log(&self);
}

impl Loggable for u8 {
    fn log(&self) {
        println!("u8: {}", *self)
    }
}

impl Loggable for String {
    fn log(&self) {
        println!("String: {}", *self);
    }
}

impl Loggable for Article {
    fn log(&self) {
        println!("Article id: {}, upvotes: {}", (*self).id, (*self).upvotes);
    }
}

Now we want to provide some generic method that will accept these types and call log method on them.

Static dispatch approach

For static dispatch we need to implement generic method that will accept generic type implementing Loggable as a function parameter.

fn static_dispatch_log<T:Loggable>(loggable: T) {
    loggable.log();
}

fn main() {
    let int_var = 123u8;
    let string_var = "Steemit".to_string();
    let article_var = Article{id:1, upvotes: 150};

    static_dispatch_log(int_var);
    static_dispatch_log(string_var);
    static_dispatch_log(article_var);
}

# output
u8: 123
String: Steemit
Article id: 1, upvotes: 150

Like this, static dispatching is used and everything needed is "pre-generated" during compilation.

Dynamic dispatch approach

For dynamic dispatch we need to create method that will accept trait object (reference-like trait) as a parameter.

fn dynamic_dispatch_log(loggable: &Loggable) {
    loggable.log();
}


fn main() {
    let int_var = 123u8;
    let string_var = "Steemit".to_string();
    let article_var = Article{id:1, upvotes: 150};

    dynamic_dispatch_log(&int_var);
    dynamic_dispatch_log(&string_var);
    dynamic_dispatch_log(&article_var);
}

# output
u8: 123
String: Steemit
Article id: 1, upvotes: 150

Like this, dynamic dispatching is used and calling is decided at runtime.

If you are interested in performance, static dispatch should be faster, but for this example execution times were equal and even dynamic dispatch was often slightly faster. And so you don't need to worry about performance much until it's critical issue for you.

Digging deeper

Static dispatch creates virtual methods for each type. On the other hand dynamic dispatch uses trait object which has this form.

pub struct TraitObject {
    pub data: *mut (),      // data pointer
    pub vtable: *mut (),   // virtual method table pointer
}
  • data pointer points to data pointer
  • vtable points to virtual data table for corresponding implementation

For more details you can check https://doc.rust-lang.org/book/trait-objects.html#representation , we might touch this deeper topic later.

Postfix

That's all for today, thank you for your appreciations, feel free to comment and point out possible mistakes (first 24 hours works the best but any time is fine). May Jesus bless your programming skills, use them wisely and see you next time.

Meanwhile you can also check the official documentation to find more about discussed dispatching and trait objects.

#rust-series
#rust-lang
#rust

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!