Kida compiles templates into Python functions at load time. This article covers the optimization passes and configuration options available to framework authors and performance-conscious users.
F-String Coalescing
The compiler's primary optimization is f-string coalescing — merging consecutive output nodes into single f-string appends instead of multiplebuf.append()calls.
Before (5 function calls)
_append('<div id="')
_append(_e(item["id"]))
_append('">')
_append(_e(item["name"]))
_append('</div>')
After (1 function call)
_append(f'<div id="{_e(item["id"])}">{_e(item["name"])}</div>')
This reduces function call overhead by ~37% in output-heavy templates.
How It Works
The compiler scans template bodies for consecutive coalesceable nodes:
| Node Type | Coalesceable? | Notes |
|---|---|---|
Static text (Data) |
Yes | Literal HTML |
| Simple variable output | Yes | {{ name }}, {{ item.title }} |
| Pure filter output | Yes | {{ name \| upper }}, {{ text \| trim }} |
| Item access | Yes | {{ items[0] }}, {{ data["key"] }} |
| Function calls | No | May have side effects |
| Ternary expressions | No | Complex control flow |
Control flow ({% if %}, {% for %}) |
No | Breaks the coalescing run |
When 2 or more consecutive coalesceable nodes are found, they are merged into a singleast.JoinedStr(Python f-string AST node). Brace escaping is handled automatically by the AST compiler.
Configuration
F-string coalescing is enabled by default:
env = Environment(
fstring_coalescing=True, # Default — recommended
)
Disable it when debugging compiled template output:
env = Environment(
fstring_coalescing=False, # Each output is a separate append
)
Pure Filters
The compiler only coalesces filter expressions that are known to be pure (no side effects, deterministic). Kida includes a built-in set of pure filters:
upper, lower, title, capitalize, swapcase, trim, strip, lstrip, rstrip,
escape, e, forceescape, default, d, int, float, string, str, bool,
length, count, first, last, join, center, ljust, rjust, truncate,
wordwrap, indent, urlencode
Register your own pure filters so the compiler can coalesce them:
env = Environment(
pure_filters={"markdown", "highlight", "currency"},
)
These are combined with the built-in set at compilation time.
Backslash Limitation
Python f-strings cannot contain backslashes in expression parts. The compiler detects backslashes in string constants and falls back to separate appends for those expressions.
AST Preservation
Kida can preserve the optimized AST after compilation, enabling runtime introspection via the static analysis API.
env = Environment(
preserve_ast=True, # Default — enables analysis API
)
Memory Trade-Off
Preserving the AST uses ~2x memory per template. Disable it in memory-constrained environments where you don't need introspection:
env = Environment(
preserve_ast=False, # Saves memory, disables analysis
)
With preserve_ast=False, the following methods return empty/None results:
template.block_metadata()returns{}template.template_metadata()returnsNonetemplate.depends_on()returnsfrozenset()template.required_context()returnsfrozenset()template.is_cacheable()returnsFalsetemplate.validate_context()returns[]
Render Modes
The compiler generates code for three render modes in a single compilation pass:
| Mode | Method | Output |
|---|---|---|
| StringBuilder | render() |
Full string in memory (fastest) |
| Streaming | render_stream() |
Generator yielding chunks |
| Async streaming | render_stream_async() |
Async generator yielding chunks |
The compiler emits_append(...) calls for StringBuilder mode and yield ...statements for streaming mode. Both share the same expression compilation logic.
Line Tracking
The compiler emits line-number updates usingContextVar-based RenderContext. This enables accurate error messages without polluting the user's context dictionary:
# Compiler emits this before each statement:
_ctx.line = 42 # Current template line
On error, the line number is read from RenderContextto produce messages like:
TemplateRuntimeError: 'page' is undefined
File "page.html", line 42, in template
See Also
- Static Analysis — Using analysis results from preserved ASTs
- Configuration —
fstring_coalescing,pure_filters,preserve_ast - Performance — Benchmark results