This skill should be used when the user asks to "review performance", "optimize Elm", "Elm performance", "performance audit", "find bottlenecks", "improve efficiency", or wants analysis of Elm code performance focusing on virtual DOM efficiency, rendering patterns, and data structure choices.
Install
npx skillscat add bromanko/llm-agents/elm-performance-review Install via the SkillsCat registry.
SKILL.md
Elm Performance Review
Action required: Run /review elm performance to start an interactive performance review. Do not perform the review manually.
Analyze Elm code for performance issues, focusing on virtual DOM rendering, lazy evaluation, efficient data handling, and avoiding unnecessary re-renders.
Scope Determination
First, determine what code to review:
- If the user specifies files/directories: Review those paths
- If no scope specified: Review working changes
- Check for
.jjdirectory first, usejj diffif present - Otherwise use
git diffto identify changed.elmfiles - If no changes, ask the user what to review
- Check for
Review Process
- Identify hot paths: Find frequently re-rendered views, large update cycles, expensive computations
- Analyze data flow: Track how data moves through Model/update/view
- Check rendering patterns below
- Review data structure choices
- Output findings in the standard format
Performance Checklist
Virtual DOM & Rendering
Html.Lazy.lazyused for expensive view functions that don't change oftenHtml.Lazy.lazy2/lazy3used with stable reference argumentsHtml.Keyed.nodeused for lists where items are reordered, added, or removed- Avoid recreating view structures unnecessarily (e.g., inline anonymous functions in event handlers)
- Large lists use keyed nodes to avoid full re-render
- View functions that depend on a small subset of Model receive only what they need
Model Design
- Model is not a single deeply nested record (causes full equality checks)
- Frequently changing data separated from stable data in Model
- Avoid storing derived/computed data in Model (compute in view instead, or use
Html.Lazy) - Consider breaking large Model into focused sub-models for
Html.Lazyeffectiveness - Avoid
Dictwith thousands of entries if only a few are displayed at a time
Update Function
updatereturns same Model reference when nothing changed (enablesHtml.Lazyskipping)- Avoid unnecessary record updates (
{ model | field = model.field }) - Batch related state changes in a single
updatebranch Cmd.batchused to combine commands, not chained updates- Avoid cascading messages (Msg triggers another Msg triggers another) — flatten when possible
Data Structures
Dictused for key-based lookups instead ofList.filter/List.findSetused for membership tests instead ofList.memberArrayused when index-based access is needed- Avoid
List.lengthin conditionals (O(n)) — track count in Model if needed - Avoid
List.reverseafterList.foldlwhenList.foldrwould suffice (or vice versa) - Avoid rebuilding large data structures on every update
JSON Decoding
- Decoders are not doing unnecessary work
- Large JSON payloads decoded into efficient structures (Dict, not List of pairs)
Decode.lazyused for recursive decoders- Avoid re-decoding data that hasn't changed
Subscriptions
- Subscriptions are stable references (avoid recreating on every call)
- High-frequency subscriptions (animation frames, mouse moves) do minimal work
Sub.batchused efficiently- Inactive subscriptions return
Sub.nonerather than filtering events in update
String & List Operations
- String concatenation uses
++sparingly in loops — considerString.joinorString.concat List.map/List.filterchains consolidated where possible- Avoid multiple passes over the same list — use
List.foldlfor single-pass operations String.fromInt/String.fromFloatnot called repeatedly for the same value
HTTP & Commands
- Requests are not duplicated (debouncing for user input, deduplication for data fetching)
- Large responses handled appropriately (pagination, streaming if possible via ports)
- Loading states prevent redundant requests
- Failed requests don't trigger infinite retry loops
Ports & JavaScript Interop
- Port messages are as small as necessary
- Avoid sending entire Model through ports
- High-frequency port communication batched where possible
- Large data transfers through ports use efficient serialization
Output Format
Present findings as:
## Findings
### [SEVERITY] Issue Title
**File:** `path/to/Module.elm:LINE`
**Category:** performance
**Issue:** Description of the performance concern and its impact.
**Suggestion:** How to optimize, with code example if helpful.
**Effort:** trivial|small|medium|large
---Use severity indicators:
- HIGH: Significant bottleneck, unbounded growth, rendering performance issues
- MEDIUM: Suboptimal patterns, unnecessary overhead
- LOW: Minor optimizations, micro-improvements
Summary
After all findings, provide:
- Total count by severity
- Top bottlenecks to address
- Hot paths identified
- Architecture recommendations (if applicable)
- Overall performance assessment (1-2 sentences)