utkarshkukreti / markup.rs

A blazing fast, type-safe template engine for Rust.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question: define! vs new!

diegopy opened this issue · comments

Hi team,

First, thanks for this library. The impressive benchmark result is making me move from Maud to this, although I'm not very experienced with either.
Me question is regarding define! vs new! macro use, like in the fortunes.rs example. I tend to prefer new! here, and have functions wrapping the template, so my question is: Is there any disadvantage (in performance or otherwise) of new! vs define!? Any advice on which one will scale better once the number of templates (and the references between them) scales as the application grows?

Thanks

new! is ad-hoc, and suitable to be returned from a function (ie: fn doc<Head, Body>(h: Head, b: Body)), while define! creates a structure, suitable for repeated use in a small context.

Well, new for stuff you return, define for stuff you own, I guess.

Hi @diegopy,

Yes, there's a performance difference - new! uses closures to allow access to outer variables, and the way they're implemented in Rust + the fact that the Render trait uses a generic writer argument means that dynamic dispatch is used for all write operations, unlike define!, which uses static dispatch. The example you linked to was written mainly for benchmarking purpose. Here are its latest results: https://github.com/utkarshkukreti/markup.rs/runs/2213438391?check_suite_focus=true#step:7:58 tldr: define! is almost twice as fast as new!. In practice though, both are really really fast. Even new! renders at 500MB/s on GitHub Actions' server.

I personally use whichever makes more sense in the situation, without considering the performance difference. The primary reason to choose one over the other: new! lets you access variables in outer scope while render! makes it easy to have "named arguments" using structs. You should use whichever results in cleaner code in your situation.

@ZaneHannanAU I'm not sure I understand your example. You can accept generic template with define as well:

markup::define! {
    Doc<Head: markup::Render, Body: markup::Render>(h: Head, b: Body) {
        head { @h }
        body { @b }
    }
}

Did you mean something else?

Yes, there's a performance difference -

Thanks for your detailed reply, very clear.