Slow generation: HandlebarTemplateEngine rebuilds Handlebars and reparses templates on every render
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 45/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Tranquilo
- Stack tecnológico
- java
- Área
- performance, tooling
Línea de trabajo
Comienza en HandlebarTemplateEngine.getRendered(...) e inspecciona cómo se crean la instancia de Handlebars, los helpers, los templates y los partials para cada renderizado. Revisa el comportamiento propuesto de IndentAwareTemplateCache y verifica tanto la reutilización de templates compilados como la salida correcta de prettyPrint(true) con diferentes sangrías de include. Se considera completado cuando se conserva la salida sin cambios en la API pública ni en los templates, y se logra la aceleración de generación indicada.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
HandlebarTemplateEngine.getRendered(...) creates a new Handlebars instance and recompiles the template (and every partial it references) on every call. Profiling shows the jknack ANTLR-based lexer accounting for ~65% of CPU during code generation for a typical OpenAPI specification.
How to reproduce
Generate code with the handlebars engine (the default for v3) against any sufficiently large spec. The cost grows roughly with (templates_rendered) × (partials_per_template) because every render repeats the full Handlebars setup + parse.
Profile
Java Flight Recorder captured during a representative warm run shows:
- ~65% of in-method CPU under
org.antlr.v4.runtime.atn.LexerATNSimulator.closure(...)— jknack's parser. - Each
getRenderedallocates a newHandlebars, re-registers all helpers, and reparses the entry template, which in turn re-parses every{{> partial }}it transitively includes.
Why it matters
Generating a server-side stub project with ~75 controllers / ~180 output files takes ~50–60 s on the affected code path. Once compiled templates are cached for the lifetime of a single generation, the same workload completes in ~12 s — a ~4.5× speed-up with no API change and no spec-side change.
Precedent
#12313 / its accompanying fix established the same pattern in another hotspot (AbstractJavaCodegen.toModelName() was called millions of times and was cached for a 3× improvement). The fix proposed here applies the same idea to template parsing.
Caveat / why a naive cache breaks output
jknack's stock ConcurrentMapTemplateCache cannot be used as-is for handlebars partials in prettyPrint(true) mode. Partial.merge wraps the partial's TemplateSource in an anonymous class whose equals/hashCode delegate only to the underlying source (filename + lastModified), but whose content() returns the partial body re-indented by the include site's leading whitespace. The same partial included at two different indents therefore collides on lookup and the first-compiled indent wins for every subsequent include — observable as silently shifted whitespace in generated output. See related jknack issues #401 and #708.
The proposed fix carries a small replacement cache (~95 LOC) keyed on (filename, content), which preserves the speed-up while keeping per-indent renders correct.
Proposed fix
A PR will follow that:
- Holds a single
Handlebarsinstance perHandlebarTemplateEngine(and so per generation), registering helpers once. - Caches compiled top-level
Templates pertemplateFile. - Installs an
IndentAwareTemplateCacheto make handlebars' own partial cache safe underprettyPrint(true).
No public API changes. No template changes. No swagger-codegen-generators change required.
- Lenguaje dominante
- Mustache
- Estrellas
- 17.8k
- Forks
- 6k
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
- Incluye un Dockerfile o un archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de swagger-api/swagger-codegen
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
swagger-api/swagger-codegen#12755 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
swagger-api/swagger-codegen#12445 ·
-
security vulnerability
Dificultad 1/5 Menos de una hora Aptitud para principiantes 62/100
swagger-api/swagger-codegen#11942 ·
-
[JAVA] Non compilable enums generated with property errorOnUnknownEnum=truePosiblemente ocupada @HiagoW la tomó hace 1458 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
swagger-api/swagger-codegen#11812 · 1 reacción ·
-
security vulnerability
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
swagger-api/swagger-codegen#11594 ·
Todos los issues de swagger-api/swagger-codegen
Issues similares
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
vercel/streamdown#673 · 1 reacción ·
Los mantenedores suelen responder en 1 día
-
type/automation type/performance
Dificultad 1/5 Menos de una hora Aptitud para principiantes 68/100
Los mantenedores suelen responder en 1 día
-
collision drivers call wp.func upper_trid_index from python every step (15-24% cpu step time)Posiblemente ocupada @dundysm la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
google-deepmind/mujoco_warp#1787 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
vllm-project/guidellm#1307 ·
Los mantenedores suelen responder en 1 día
-
Whole-run Hits/sec, Misses/sec, MOVED/sec and ASK/sec wrap after 2^32 events: 32-bit counters in one_sec_cmd_stats are summed across the runPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
redis/memtier_benchmark#642 ·
Los mantenedores suelen responder en 1 día