Slow generation: HandlebarTemplateEngine rebuilds Handlebars and reparses templates on every render
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 45/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Tranquilla
- Stack tecnologico
- java
- Ambito
- performance, tooling
Direzione di ricerca
Inizia da HandlebarTemplateEngine.getRendered(...) e verifica come vengono creati l’istanza di Handlebars, gli helper, i template e i partial per ogni rendering. Esamina il comportamento proposto di IndentAwareTemplateCache e verifica sia il riutilizzo dei template compilati sia l’output corretto di prettyPrint(true) con diversi livelli di indentazione degli include. Il lavoro è completato quando l’output viene mantenuto senza modifiche all’API pubblica o ai template, ottenendo al contempo l’accelerazione di generazione indicata.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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.
- Lingua principale
- Mustache
- Stelle
- 17.8k
- Fork
- 6k
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
- Include un Dockerfile o un file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di swagger-api/swagger-codegen
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
swagger-api/swagger-codegen#12755 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
swagger-api/swagger-codegen#12445 ·
-
security vulnerability
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 62/100
swagger-api/swagger-codegen#11942 ·
-
[JAVA] Non compilable enums generated with property errorOnUnknownEnum=trueForse già presa @HiagoW l’ha presa 1459 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
swagger-api/swagger-codegen#11812 · 1 reazione ·
-
security vulnerability
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
swagger-api/swagger-codegen#11594 ·
Tutte le issue di swagger-api/swagger-codegen
Issue simili
-
from-review-extraction python severity:nit
Difficoltà 2/5 1-3 ore Idoneità per principianti 80/100
LearningCircuit/local-deep-research#7462 ·
I maintainer di solito rispondono entro 2 giorni
-
perf(translator): Claude→Responses stream re-validates the whole request body on every SSE chunkAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
router-for-me/CLIProxyAPI#6665 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
I maintainer di solito rispondono entro 1 giorno
-
Enable the existing compression middleware in server.jsForse già presa @ademolabiyi92-design l’ha presa oggi. Apertaenhancement Stellar Wave
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
Emmy123222/Stellar-MarketPay-#1776 · 2 commenti ·
I maintainer di solito rispondono entro 2 giorni
-
area-middleware
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
dotnet/aspnetcore#69849 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno