This unfortunately won’t do much good as a PR because the project seems to be abandoned but you can get really big speedups in pystache by caching templates and (particularly) parsed templates. Especially if you are using a lot of partials.
It looks something like this:
# Subclass pystache.Renderer to provide our custom caching versions of pystache classes for performance reasons. class CachedRenderer(pystache.Renderer): def _make_loader(self) -> pystache.loader.Loader: return CachedLoader(file_encoding=self.file_encoding, extension=self.file_extension, to_unicode=self.str, search_dirs=self.search_dirs) def _make_render_engine(self) -> pystache.renderengine.RenderEngine: resolve_context = self._make_resolve_context() resolve_partial = self._make_resolve_partial() engine = CachedRenderEngine(literal=self._to_unicode_hard, escape=self._escape_to_unicode, resolve_context=resolve_context, resolve_partial=resolve_partial, to_str=self.str_coerce) return engine # A custom loader that acts exactly as the default loader but only loads a given file once to speed up repeated use of partials. # This will stop us loading record.mustache from disk 16,000 times on /cards/ for example. class CachedLoader(pystache.loader.Loader): def __init__(self, file_encoding: Optional[str] = None, extension: Optional[Union[str, bool]] = None, to_unicode: Optional[StringConverterFunction] = None, search_dirs: Optional[List[str]] = None) -> None: super().__init__(file_encoding, extension, to_unicode, search_dirs) self.templates: Dict[str, str] = {} def read(self, path: str, encoding: Optional[str] = None) -> str: if self.templates.get(path) is None: # look in redis using modified date on filesystem of path self.templates[path] = super().read(path, encoding) # write to redis return self.templates[path] # If you have already parsed a template, don't parse it again. class CachedRenderEngine(pystache.renderengine.RenderEngine): # pylint: disable=too-many-arguments def __init__(self, literal: StringConverterFunction = None, escape: StringConverterFunction = None, resolve_context: Optional[Callable[[ContextStack, str], str]] = None, resolve_partial: Optional[StringConverterFunction] = None, to_str: Optional[Callable[[object], str]] = None) -> None: super().__init__(literal, escape, resolve_context, resolve_partial, to_str) self.parsed_templates: Dict[str, pystache.parsed.ParsedTemplate] = {} def render(self, template: str, context_stack: ContextStack, delimiters: Optional[Tuple[str, str]] = None) -> str: if self.parsed_templates.get(template) is None: # look in redis self.parsed_templates[template] = pystache.parser.parse(template, delimiters) # store in redis return self.parsed_templates[template].render(self, context_stack)