Three functions in PixiJS’s rendering and text subsystems sit in the ‘fire’ quadrant — meaning they are both structurally complex and actively changing, making them live regression risks rather than backlog cleanup items. The top-ranked function, wordWrapTaggedLines, carries an activity risk of 18.57 with a recent commit activity of 17.46, pairing a cyclomatic complexity of 36 with nesting depth of 7. Across 4,035 total functions, 131 are rated critical-band — a concentration that signals the rendering core deserves focused attention now.
The table below ranks functions by activity-weighted risk — a score that multiplies structural complexity by recent commit frequency. A function that is both hard to understand (high cyclomatic complexity) and actively changing is a higher priority than one that is complex but untouched. CC = cyclomatic complexity (independent execution paths); ND = max nesting depth; FO = fan-out (distinct callees).
Top 5 Hotspots
| Function | File | Risk | CC | ND | FO |
|---|---|---|---|---|---|
wordWrapTaggedLines | src/scene/text/canvas/utils/measureTaggedText.ts | 18.6 | 36 | 7 | 16 |
renderChildren | src/scene/graphics/shared/svg/SVGParser.ts | 18.0 | 59 | 6 | 26 |
recursive | src/scene/graphics/shared/buildCommands/buildAdaptiveBezier.ts | 17.1 | 30 | 7 | 4 |
emscriptenWebGLGet | transcoders/ktx/libktx.js | 17.1 | 94 | 6 | 5 |
execute | src/scene/graphics/canvas/CanvasGraphicsAdaptor.ts | 16.3 | 33 | 5 | 25 |
Large Repo Analysis
pixijs is a large repository. To stay within memory constraints, this analysis used hybrid touch mode: structural complexity — CC, ND, FO — is measured precisely for every function. Git activity is tracked at the function level (via git log -L) only for files with 5 or more commits in the last 30 days; other files use a file-level approximation. Rankings therefore surface functions that are both structurally complex and in the most actively-changing parts of the codebase. Dormant code with high structural complexity will rank lower than it would under a full per-function analysis — to surface it, run hotspots analyze . --per-function-touches on a machine with sufficient memory.
Codemod / Tooling Files in Results
emscriptenWebGLGet in transcoders/ktx/libktx.js is a vendored, Emscripten-compiled C library used for KTX texture transcoding — it is not authored PixiJS code. Its cyclomatic complexity of 94 is a product of the compiled output, not a refactoring target. Exclude it from future runs with: { "exclude": ["transcoders/"] } in your .hotspotsrc.json.
Hotspot Analysis
wordWrapTaggedLines — src/scene/text/canvas/utils/measureTaggedText.ts
Based on its name and path, this function almost certainly handles word-wrap layout for tagged (rich) text, breaking styled runs of text into lines — a task that requires tracking style boundaries, measuring token widths, and managing line breaks simultaneously. A cyclomatic complexity of 36 means there are 36 independent execution paths, each a potential bug surface and a required test case; a nesting depth of 7 compounds that by making the control flow hard to reason about locally. Its recent commit activity of 17.46 puts it firmly in the ‘fire’ quadrant — this complexity is being exercised by active commits right now, making every change a live regression risk across text rendering.
Recommendation: Before any refactoring, add characterization tests that cover edge cases (empty tags, mixed-direction text, overflow conditions) to lock in current behavior. Then extract the line-measurement logic and the tag-boundary tracking into separate, single-responsibility helpers to bring cyclomatic complexity below 15.
renderChildren — src/scene/graphics/shared/svg/SVGParser.ts
From its name and location in the SVG parser, this function likely dispatches rendering logic across the full set of SVG child node types — a dispatch pattern that naturally accumulates one branch per supported element type. At cyclomatic complexity 59 and fan-out 26, it is both extremely branchy and broadly coupled: 26 distinct callees means a change here can ripple into a wide surface of downstream rendering code. Its recent commit activity of 17.76 is the highest among the top hotspots, and its ‘fire’ quadrant status means that SVG parsing is being actively changed against this structural backdrop.
Recommendation: Introduce a dispatch table or visitor pattern to replace the branching per SVG element type, reducing cyclomatic complexity and decoupling individual element handlers so they can be tested and changed in isolation. Review the 26 fan-out callees to identify which can be encapsulated behind a narrower interface.
recursive — src/scene/graphics/shared/buildCommands/buildAdaptiveBezier.ts
The name recursive in a file dedicated to adaptive bezier construction strongly suggests this is the subdivision routine that recursively splits bezier curves until a flatness threshold is met — a geometry-intensive algorithm where branch conditions govern subdivision depth, collinearity tests, and tolerance checks. A cyclomatic complexity of 30 and nesting depth of 7 reflect the multi-condition termination logic inherent to adaptive subdivision, but also make the function difficult to audit for correctness. With a recent commit activity of 16.15 in the ‘fire’ quadrant, this algorithm is under active development, heightening the risk that a subtle tolerance or boundary-case change introduces visual artifacts.
Recommendation: Extract the individual termination and subdivision conditions into named predicate functions to reduce nesting depth and make each branch’s intent explicit. Add property-based tests that verify geometric invariants (e.g., output points lie on the original curve) before touching the logic.
Patterns Found
Antipatterns detected across the top functions in this snapshot:
| Pattern | Occurrences |
|---|---|
complex_branching | 5 |
deeply_nested | 5 |
exit_heavy | 5 |
long_function | 4 |
god_function | 3 |
These labels belong to two tiers — Tier 1 (structural): complex_branching, deeply_nested, exit_heavy, long_function, god_function. Tier 2 (relational/temporal): hub_function, cyclic_hub, middle_man, neighbor_risk, stale_complex, churn_magnet, shotgun_target, volatile_god.
Key Takeaways
renderChildrenin SVGParser.ts has a fan-out of 26 and cyclomatic complexity of 59 — map its 26 callees before making any changes to understand the full blast radius, then introduce a visitor or dispatch-table pattern to make individual element handlers independently testable.wordWrapTaggedLineshas 36 independent execution paths and a nesting depth of 7: add characterization tests covering tag-boundary and overflow edge cases immediately, since its recent commit activity of 17.46 means it is being changed right now.- All three real-code hotspots share the god_function or long_function pattern alongside complex branching — the highest-leverage refactoring move across all three is extract-method: split each into smaller, named, single-responsibility helpers rather than attempting in-place simplification.
Reproduce This Analysis
git clone https://github.com/pixijs/pixijs
cd pixijs
git checkout 8f42bb760872ed6652775d00a4de448ac277e783
hotspots analyze . --mode snapshot --explain-patterns --force --hybrid-touches 5
To run the same analysis on your own codebase, run hotspots analyze . --mode snapshot in any local git repo — no configuration required.
Hotspots highlights structural and activity risk — not “bad code.” Findings are a prioritization aid, not a bug predictor. Editorial policy →