mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 06:07:17 +00:00
Reduce template render overhead (#103343)
The contextmanager decorator creates a new context manager every time its run, but since we only have a single context var, we can use the same one every time. Creating the contextmanager was roughly 20% of the time time of the template render I was a bit suprised to find it creates a new context manager object every time https://stackoverflow.com/questions/34872535/why-contextmanager-is-slow
This commit is contained in:
parent
62067fc64c
commit
68471b6da5
@ -6,7 +6,7 @@ import asyncio
|
|||||||
import base64
|
import base64
|
||||||
import collections.abc
|
import collections.abc
|
||||||
from collections.abc import Callable, Collection, Generator, Iterable, MutableMapping
|
from collections.abc import Callable, Collection, Generator, Iterable, MutableMapping
|
||||||
from contextlib import contextmanager, suppress
|
from contextlib import AbstractContextManager, suppress
|
||||||
from contextvars import ContextVar
|
from contextvars import ContextVar
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from functools import cache, lru_cache, partial, wraps
|
from functools import cache, lru_cache, partial, wraps
|
||||||
@ -20,7 +20,7 @@ import re
|
|||||||
import statistics
|
import statistics
|
||||||
from struct import error as StructError, pack, unpack_from
|
from struct import error as StructError, pack, unpack_from
|
||||||
import sys
|
import sys
|
||||||
from types import CodeType
|
from types import CodeType, TracebackType
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
Concatenate,
|
Concatenate,
|
||||||
@ -504,7 +504,8 @@ class Template:
|
|||||||
|
|
||||||
def ensure_valid(self) -> None:
|
def ensure_valid(self) -> None:
|
||||||
"""Return if template is valid."""
|
"""Return if template is valid."""
|
||||||
with set_template(self.template, "compiling"):
|
with _template_context_manager as cm:
|
||||||
|
cm.set_template(self.template, "compiling")
|
||||||
if self.is_static or self._compiled_code is not None:
|
if self.is_static or self._compiled_code is not None:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -2213,21 +2214,32 @@ def iif(
|
|||||||
return if_false
|
return if_false
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
class TemplateContextManager(AbstractContextManager):
|
||||||
def set_template(template_str: str, action: str) -> Generator:
|
"""Context manager to store template being parsed or rendered in a ContextVar."""
|
||||||
"""Store template being parsed or rendered in a Contextvar to aid error handling."""
|
|
||||||
template_cv.set((template_str, action))
|
def set_template(self, template_str: str, action: str) -> None:
|
||||||
try:
|
"""Store template being parsed or rendered in a Contextvar to aid error handling."""
|
||||||
yield
|
template_cv.set((template_str, action))
|
||||||
finally:
|
|
||||||
|
def __exit__(
|
||||||
|
self,
|
||||||
|
exc_type: type[BaseException] | None,
|
||||||
|
exc_value: BaseException | None,
|
||||||
|
traceback: TracebackType | None,
|
||||||
|
) -> None:
|
||||||
|
"""Raise any exception triggered within the runtime context."""
|
||||||
template_cv.set(None)
|
template_cv.set(None)
|
||||||
|
|
||||||
|
|
||||||
|
_template_context_manager = TemplateContextManager()
|
||||||
|
|
||||||
|
|
||||||
def _render_with_context(
|
def _render_with_context(
|
||||||
template_str: str, template: jinja2.Template, **kwargs: Any
|
template_str: str, template: jinja2.Template, **kwargs: Any
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Store template being rendered in a ContextVar to aid error handling."""
|
"""Store template being rendered in a ContextVar to aid error handling."""
|
||||||
with set_template(template_str, "rendering"):
|
with _template_context_manager as cm:
|
||||||
|
cm.set_template(template_str, "rendering")
|
||||||
return template.render(**kwargs)
|
return template.render(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user