tera icon indicating copy to clipboard operation
tera copied to clipboard

Clone properties of `Tera`

Open zizhengtai opened this issue 5 years ago • 3 comments

I'm using Tera with actix-web, which creates a separate app state (including a Tera instance in my case) per thread. I was originally doing something like this:

// Compile the templates only once
let tera = Tera::new(...)?;

HttpServer::new(move || {
    App::new()
        .data(tera.clone())  // Cloning a `Tera` here
})

I looked into the struct Tera and realized that I'm actually cloning a bunch of stuff (such as HashMaps and Vecs), so I decided to do this instead:

let tera = Arc::new(Tera::new(...)?);

HttpServer::new(move || {
    App::new()
        .app_data(Data::from(Arc::clone(&tera)))  // Cloning an `Arc<Tera>` here
})

But then I noticed that there are already Arcs inside Tera, which I think is wasteful in this case. I could be totally wrong and maybe Tera is designed this way for a reason, but I think it'd be more flexible if we replace the Arcs inside Tera with Rcs. This will have several consequences:

  • The Test, Filter and Function traits will no longer need to be Send. This should be a backwards-compatible change.
  • The Tera struct will no longer be Send. We need to wrap it in an Arc if we want to send it between threads.

This change will bring the following benefits:

  • Less overhead when using Tera from multiple threads (which I suppose all server frameworks require) since we don't have double Arcs anymore.
  • Less overhead when using Tera from a single thread since we don't need Arc at all.

The only downside I can think of is that making Tera not Send is a breaking change. I'd like to hear your opinions.

zizhengtai avatar Jun 12 '20 18:06 zizhengtai

Another way to do this while keeping backwards compatibility is:

  • Replace the Arcs inside Tera with Rcs
  • Move whatever is inside Tera now to a TeraInner and Arc-wrap it inside Tera:
struct Tera {
    inner: Arc<TeraInner>,
}

struct TeraInner {
    /* a bunch of stuff */
}

However, I still think externalizing the Arc is the most flexible approach.

zizhengtai avatar Jun 12 '20 18:06 zizhengtai

I do want tests/filters/functions to be Send though. Would https://github.com/getzola/zola/blob/master/components/templates/src/global_fns/mod.rs (+ rayon) still work without too much overhead?

Keats avatar Jun 12 '20 20:06 Keats

Would https://github.com/getzola/zola/blob/master/components/templates/src/global_fns/mod.rs (+ rayon) still work without too much overhead?

I'm not sure I follow...?

zizhengtai avatar Jun 13 '20 03:06 zizhengtai