Add warning about slow .to_string() method

This commit is contained in:
René Kijewski 2024-09-16 17:11:44 +02:00
parent 4d1bf69a57
commit 92e3bf88b5
4 changed files with 55 additions and 0 deletions

View File

@ -1,5 +1,29 @@
# Performance
## Rendering Performance
When rendering a rinja template, you should prefer the methods
* [`.render()`] (to render the content into a new string),
* [`.render_into()`] (to render the content into an [`fmt::Write`] object, e.g. [`String`]) or
* [`.write_into()`] (to render the content into an [`io::Write`] object, e.g. [`Vec<u8>`])
over [`.to_string()`] or [`format!()`].
While `.to_string()` and `format!()` give you the same result, they generally perform much worse
than rinja's own methods, because [`fmt::Write`] uses [dynamic methods calls] instead of
monomorphised code. On average, expect `.to_string()` to be 100% to 200% slower than `.render()`.
[dynamic methods calls]: <https://doc.rust-lang.org/stable/std/keyword.dyn.html>
[`.render()`]: <https://docs.rs/rinja/latest/rinja/trait.Template.html#method.render>
[`.render_into()`]: <https://docs.rs/rinja/latest/rinja/trait.Template.html#tymethod.render_into>
[`.write_into()`]: <https://docs.rs/rinja/latest/rinja/trait.Template.html#method.write_into>
[`fmt::Write`]: <https://doc.rust-lang.org/stable/std/fmt/trait.Write.html>
[`String`]: <https://doc.rust-lang.org/stable/std/string/struct.String.html>
[`io::Write`]: <https://doc.rust-lang.org/stable/std/io/trait.Write.html>
[`Vec<u8>`]: <https://doc.rust-lang.org/stable/std/vec/struct.Vec.html>
[`.to_string()`]: <https://doc.rust-lang.org/stable/std/string/trait.ToString.html#tymethod.to_string>
[`format!()`]: <https://doc.rust-lang.org/stable/std/fmt/fn.format.html>
## Slow Debug Recompilations
If you experience slow compile times when iterating with lots of templates,

View File

@ -75,6 +75,24 @@ pub use crate::error::{Error, Result};
/// Main `Template` trait; implementations are generally derived
///
/// If you need an object-safe template, use [`DynTemplate`].
///
/// ## Rendering performance
///
/// When rendering a rinja template, you should prefer the methods
///
/// * [`.render()`][Template::render] (to render the content into a new string),
/// * [`.render_into()`][Template::render_into] (to render the content into an [`fmt::Write`]
/// object, e.g. [`String`]) or
/// * [`.write_into()`][Template::write_into] (to render the content into an [`io::Write`] object,
/// e.g. [`Vec<u8>`])
///
/// over [`.to_string()`][std::string::ToString::to_string] or [`format!()`].
/// While `.to_string()` and `format!()` give you the same result, they generally perform much worse
/// than rinja's own methods, because [`fmt::Write`] uses [dynamic methods calls] instead of
/// monomorphised code. On average, expect `.to_string()` to be 100% to 200% slower than
/// `.render()`.
///
/// [dynamic methods calls]: <https://doc.rust-lang.org/stable/std/keyword.dyn.html>
pub trait Template: fmt::Display {
/// Helper method which allocates a new `String` and renders into it
fn render(&self) -> Result<String> {

View File

@ -174,6 +174,16 @@ impl<'a> Generator<'a> {
// Implement `Display` for the given context struct.
fn impl_display(&mut self, buf: &mut Buffer) {
let ident = &self.input.ast.ident;
buf.write(format_args!(
"\
/// Implement the [`format!()`][::std::format] trait for [`{}`]\n\
///\n\
/// Please be aware of the rendering performance notice in the \
[`Template`][{CRATE}::Template] trait.\n\
",
quote!(#ident),
));
self.write_header(buf, "::core::fmt::Display", None);
buf.write(format_args!(
"\

View File

@ -55,6 +55,9 @@ struct Foo {{ {} }}"##,
const SIZE_HINT: ::core::primitive::usize = #size_hint;
const MIME_TYPE: &'static ::core::primitive::str = "text/plain; charset=utf-8";
}
/// Implement the [`format!()`][::std::format] trait for [`Foo`]
///
/// Please be aware of the rendering performance notice in the [`Template`][::rinja::Template] trait.
impl ::core::fmt::Display for Foo {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {