Skip to content

Eager load templates - #57

Open
etiennebarrie wants to merge 4 commits into
mainfrom
actionview-eager-load-templates
Open

Eager load templates#57
etiennebarrie wants to merge 4 commits into
mainfrom
actionview-eager-load-templates

Conversation

@etiennebarrie

Copy link
Copy Markdown
Member

This gives a way to load all templates at boot time, and make them shareable.
For now only strict locals templates are supported, since they allow folding the UnboundTemplate.@templates cache into a single Template object.

super
end

def eager_load_templates

@gmcgibbon gmcgibbon Aug 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are we planning on calling this? I assume ractorize!, right?

Add FileSystemResolver#eager_load_templates, which globs the view path
once and populates the unbound-template cache up front instead of lazily
on first lookup. The cache stays mutable, so binding new locals at render
time keeps working exactly as before; this only warms the cache. Given a
view, it also compiles each template into the view's compiled-method
container, so templates can be compiled up front on the main Ractor:
worker Ractors only call the compiled methods.

Also extract the lookup out of #_find_all into #unbound_templates_for and
drop the throwaway Concurrent::Map that was allocated on every uncached
lookup, computing directly instead.
Give Template, UnboundTemplate, the file source, and the resolver's
PathParser a #freeze that turns them into deeply-frozen, Ractor-shareable
objects, and add FileSystemResolver#freeze to freeze the whole eager-built
cache. Combined with #eager_load_templates, a resolver can be built and
then frozen so its templates can be shared across Ractors.

Template#freeze memoizes the method name, strict-locals declaration and
compiled source, then drops the compile mutex. UnboundTemplate collapses to
a single @strict_locals_template once it discovers the template is strict,
rather than a defaulting Hash, which makes freezing straightforward.

Freezing requires a compiled template: freeze drops the compile mutex and
frozen ivars reject writes, so a template frozen before compilation could
never render. Template#freeze raises for uncompiled templates, pointing
the error at the boot step that froze too early rather than at the first
render. Compiling first also warms @type, which render populates with the
template's Mime::Type; full shareability therefore depends on the Mime
registry being frozen at boot.

Freezing requires strict locals: a non-strict template compiles a distinct
method per set of locals, so it can't be reduced to one shareable template.
UnboundTemplate#freeze therefore raises for any template that hasn't
declared its locals. Support for freezing non-strict templates and partials
is left to a follow-up.
Rails::Application#ractorize! now warms every file system resolver:
eager_load_templates globs each view path and compiles every template
into the shared view context class on the main Ractor, since worker
Ractors only call the compiled methods. Freezing the resolvers is left
to the follow-up that supports non-strict templates.
A template compiles its render method into a single module, the
compiled_method_container of the view it was first rendered with, and
@compiled is a single bit: rendering the same template with a view
whose container differs finds @compiled set, skips compilation, and
fails with an unexplained NoMethodError when the view dispatches the
method. Remember the container at compilation and raise an explicit
error instead. With templates now compiled up front in ractorize!,
mixing containers is easier to hit and harder to diagnose.
@etiennebarrie
etiennebarrie force-pushed the actionview-eager-load-templates branch from b262f80 to 93519a3 Compare August 6, 2026 10:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants