skills/accelint-ts-performance/SKILL.md
Systematic JavaScript/TypeScript performance audit and optimization using V8 profiling and runtime patterns. Use when (1) Users say 'optimize performance', 'audit performance', 'this is slow', 'reduce allocations', 'improve speed', 'check performance', (2) Analyzing code for performance anti-patterns (O(n²) complexity, excessive allocations, I/O blocking, template literal waste), (3) Optimizing functions regardless of current usage context - utilities, formatters, parsers are often called in hot paths even when they appear simple, (4) Fixing V8 deoptimization (monomorphic/polymorphic issues, inline caching). Audits ALL code for anti-patterns and reports findings with expected gains. Covers loops, caching, batching, memory locality, algorithmic complexity fixes with ❌/✅ patterns.
npx skillsauth add gohypergiant/agent-skills accelint-ts-performanceInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Systematic performance optimization for JavaScript/TypeScript codebases. Combines audit workflow with expert-level optimization patterns for runtime performance.
Note: For general best practices (type safety with any/enum, avoiding null, not mutating parameters), use the accelint-ts-best-practices skill instead. This section focuses exclusively on performance-specific anti-patterns.
NEVER assume code is cold path - Utility functions, formatters, parsers, and validators appear simple but are frequently called in loops, rendering pipelines, or real-time systems. Always audit ALL code for performance anti-patterns. Do not make assumptions about usage frequency or skip auditing based on perceived simplicity.
NEVER apply all optimizations blindly - Performance patterns have trade-offs. Balance optimization gains against code complexity. When conducting audits, identify ALL anti-patterns through systematic analysis and report them with expected gains. Let users decide which optimizations to apply based on their specific context.
NEVER ignore algorithmic complexity - Optimizing O(n²) code with micro-optimizations is futile. For n=1000, algorithmic fix (O(n² → O(n)) yields 1000x speedup; micro-optimizations yield 1.1-2x at best. Fix algorithm first: use Maps/Sets for O(1) lookups, eliminate nested iterations, choose appropriate data structures.
NEVER sacrifice correctness for speed - Performance bugs are still bugs. Optimizations frequently break edge cases: off-by-one errors in manual loops, wrong behavior for empty arrays, null handling issues. Verify behavior matches before and after. Add comprehensive tests covering edge cases before optimizing—catching bugs in production costs far more than any performance gain.
NEVER optimize code you don't own - Shared utilities, library internals, or code actively developed by others creates merge conflicts, duplicates effort, and confuses ownership. Performance changes affect all callers; coordinate with owners or defer optimization until code stabilizes.
NEVER ignore memory vs CPU trade-offs - Caching trades memory for speed. Unbounded memoization causes memory leaks in long-running applications. A 2x CPU speedup that increases memory 10x can trigger OOM crashes or frequent GC pauses (worse than original slowness). Profile memory usage alongside CPU; set cache size limits; use WeakMap for lifecycle-bound caches.
NEVER assume performance across environments - V8 optimizations differ between Node.js versions (v18 vs v20), browsers (Chrome vs Safari), and architectures (x64 vs ARM). An optimization yielding 3x speedup in Chrome may regress 1.5x in Safari. Profile in ALL target environments before shipping; maintain fallback implementations for environment-specific optimizations.
NEVER chain array methods (.filter().map().reduce()) - Each method creates intermediate arrays and iterates separately. For arrays with 10k items, .filter().map() allocates 10k + 5k items (if 50% pass filter) and iterates twice. Use single reduce pass to iterate once with zero intermediate allocations, yielding 2-5x speedup in hot paths.
NEVER use Array.includes() for repeated lookups - Array.includes() is O(n) linear search. Checking 1000 items against array of 100 is O(n×m) = 100k operations. Use Set.has() instead: O(1) lookup via hash table, reducing 100k operations to 1000 for ~100x speedup. Build Set once upfront; amortized cost is negligible.
NEVER await before checking if you need the result - await suspends execution immediately, even if the value isn't needed. Move await into conditional branches that actually use the result. Example: const data = await fetch(url); if (condition) { use(data); } wastes I/O time when condition is false. Better: if (condition) { const data = await fetch(url); use(data); } skips fetch entirely when unneeded.
NEVER recompute constants inside loops - Recomputing invariants wastes CPU in every iteration. For 10k iterations, array.length lookup (even if cached by engine) or Math.max(a, b) runs 10k times unnecessarily. Hoist invariants outside loops: const len = array.length; for (let i = 0; i < len; i++) or curry functions to precompute constant parameters once.
NEVER create unbounded loops or queues - Prevents runaway resource consumption from bugs or malicious input. Set explicit limits (for (let i = 0; i < Math.min(items.length, 10000); i++)) or timeouts. Unbounded loops can freeze UI threads; unbounded queues cause OOM crashes. Fail fast with clear limits rather than degrading gracefully into unusability.
NEVER place try/catch in hot paths - V8 cannot inline functions containing try-catch blocks and marks entire function as non-optimizable. Single try-catch in hot loop causes 3-5x slowdown by preventing inlining, escape analysis, and other optimizations. Validate inputs before hot paths using type guards; move try-catch outside loops to wrap entire operation; use Result types for expected errors.
Apply these tests to focus optimization efforts effectively:
.map(). Balance performance with team velocity.This skill uses progressive disclosure to minimize context usage:
Follow the 4-phase audit workflow below for systematic performance analysis.
Load AGENTS.md to scan compressed rule summaries organized by category.
When you identify specific performance issues, load corresponding reference files for detailed ❌/✅ examples.
When users explicitly request a performance audit, load the template for consistent reporting:
Two modes of operation:
Audit Mode - Skill invoked directly (/accelint-ts-performance <path>) or user explicitly requests performance audit
Implementation Mode - Skill triggers automatically during feature work
Copy this checklist to track progress:
- [ ] Phase 1: Profile - Identify actual bottlenecks using profiling tools
- [ ] Phase 2: Analyze - Categorize issues by impact and optimization category
- [ ] Phase 3: Optimize - Apply performance patterns from references/
- [ ] Phase 4: Verify - Measure improvements and validate correctness
CRITICAL: Audit ALL code for performance anti-patterns. Do not skip code based on assumptions about usage frequency. Utility functions, formatters, parsers, validators, and data transformations are frequently called in loops, rendering pipelines, or real-time systems even if their implementation appears simple.
When profiling tools are available, use them to establish baseline measurements:
node --prof script.js && node --prof-process isolate-*.logWhether profiling data is available or not: Perform systematic static code analysis to identify ALL performance anti-patterns:
Output: Complete list of ALL identified anti-patterns with their locations and expected performance impact. Do not filter based on "severity" or "priority" - report everything found.
When generating audit reports (when skill is invoked directly via /accelint-ts-performance <path> or user explicitly requests performance audit), use the structured template:
For EVERY issue identified in Phase 1, categorize by optimization type:
Categorize ALL issues by optimization type:
| Issue Type | Category | Expected Gain | |------------|----------|---------------| | Nested loops, O(n²) complexity | Algorithmic optimization | 10-1000x | | Repeated expensive computations | Caching & memoization | 2-100x | | Allocation-heavy code | Allocation reduction | 1.5-5x | | Sequential access violations | Memory locality | 1.5-3x | | Excessive I/O operations | I/O optimization | 5-50x | | Blocking async operations | I/O optimization | 2-10x | | Property access in loops | Caching & memoization | 1.2-2x |
Quick reference for mapping issues:
Load references/quick-reference.md for detailed issue-to-category mapping and anti-pattern detection.
Output: Categorized list of ALL issues with their optimization categories. Do not filter or prioritize - list everything found in Phase 1.
Step 1: Identify your bottleneck category from Phase 2 analysis.
Step 2: Load MANDATORY references for your category. Read each file completely with no range limits.
| Category | MANDATORY Files | Optional | Do NOT Load | |----------|----------------|----------|-------------| | Algorithmic (O(n²), nested loops, repeated lookups) | reduce-looping.md<br>reduce-branching.md | — | memoization, caching, I/O, allocation | | Caching (property access in loops, repeated calculations) | memoization.md<br>cache-property-access.md | cache-storage-api.md (for Storage APIs) | I/O, allocation | | I/O (blocking async, excessive I/O operations) | batching.md<br>defer-await.md | — | algorithmic, memory | | Memory (allocation-heavy, GC pressure) | object-operations.md<br>avoid-allocations.md | — | I/O, caching | | Locality (sequential access violations, cache misses) | predictable-execution.md | — | all others | | Safety (unbounded loops, runaway queues) | bounded-iteration.md | — | all others | | Micro-opt (hot path fine-tuning, 1.1-2x improvements) | currying.md<br>performance-misc.md | — | all others (apply only after algorithmic fixes) |
Notes:
Step 3: Scan for quick reference during optimization
Load AGENTS.md to see compressed rule summaries organized by category. Use as a quick lookup while implementing patterns from the detailed reference files above.
Apply patterns systematically:
Example optimization:
// ❌ Before: O(n²) - nested iteration
for (const user of users) {
const items = allItems.filter(item => item.userId === user.id);
process(items);
}
// ✅ After: O(n) - single pass with Map lookup
// Performance: reduce-looping.md - build lookup once pattern
const itemsByUser = new Map<string, Item[]>();
for (const item of allItems) {
if (!itemsByUser.has(item.userId)) {
itemsByUser.set(item.userId, []);
}
itemsByUser.get(item.userId)!.push(item);
}
for (const user of users) {
const items = itemsByUser.get(user.id) ?? [];
process(items);
}
Measure performance gain:
Verify correctness:
Document optimization:
// Performance optimization applied: 2026-01-28
// Issue: Nested iteration causing O(n²) complexity with 10k items
// Pattern: reduce-looping.md - Map-based lookup
// Speedup: 145x faster (5200ms → 36ms)
// Verified: All tests pass, manual QA complete
Deciding whether to keep the optimization:
Real-time systems (60fps rendering, live data visualization): Even 1.05x improvements matter in critical hot paths. Use frame timing profiler to verify impact on frame budget (16.67ms for 60fps).
If tests fail: Fix the optimization or revert. Performance bugs are still bugs.
Calibrate guidance specificity to optimization impact:
| Optimization Type | Freedom Level | Guidance Format | Example |
|------------------|---------------|-----------------|---------|
| Algorithmic (10x+ gain) | Medium freedom | Multiple valid approaches, pick based on constraints | "Use Map for O(1) lookup or Set for deduplication" |
| Caching (2-10x gain) | Medium freedom | Pattern with examples, cache invalidation strategy | "Memoize with WeakMap if lifecycle matches source objects" |
| Micro-optimization (1.1-2x) | Low freedom | Exact pattern from reference, measure first | "Cache array.length in loop: for (let i = 0, len = arr.length; ...)" |
The test: "What's the speedup and maintenance cost?"
Use this table to rapidly identify which optimization category applies.
Audit everything: Identify ALL performance anti-patterns in the code regardless of current usage context. Report all findings with expected gains.
| If You See... | Root Cause | Optimization Category | Expected Gain |
|---------------|------------|----------------------|---------------|
| Nested for loops over same data | O(n²) complexity | Algorithmic (reduce-looping) | 10-1000x |
| .filter() followed by .find() or .map() | Multiple passes over data | Algorithmic (reduce-looping) | 2-10x |
| Repeated array.find() or .includes() | O(n) linear search | Algorithmic (reduce-looping, use Set/Map) | 10-100x |
| Many if/else chains on same variable | Branch-heavy code | Algorithmic (reduce-branching) | 1.5-3x |
| Same function called with same inputs repeatedly | Redundant computation | Caching (memoization) | 2-100x |
| obj.prop.nested.deep accessed multiple times in loop | Property access overhead | Caching (cache-property-access) | 1.2-2x |
| localStorage.getItem() or sessionStorage in loop | Expensive I/O in loop | Caching (cache-storage-api) | 5-20x |
| Multiple await fetch() in sequence | Sequential I/O blocking | I/O (batching, defer-await) | 2-10x |
| await before conditional that might not need result | Premature async suspension | I/O (defer-await) | 1.5-3x |
| Many object spreads {...obj} or [...arr] | Allocation overhead | Memory (avoid-allocations) | 1.5-5x |
| Creating objects/arrays inside hot loops | GC pressure from allocations | Memory (avoid-allocations) | 2-5x |
| Object.assign() or spread when mutation is safe | Unnecessary immutability cost | Memory (object-operations) | 1.5-3x |
| Accessing array elements non-sequentially | Cache locality issues | Memory Locality (predictable-execution) | 1.5-3x |
| while(true) or unbounded queue growth | Runaway resource usage | Safety (bounded-iteration) | Prevents crashes |
| Function called with mostly same first N params | Repeated parameter passing | Micro-opt (currying) | 1.1-1.5x |
| try/catch inside hot loop | V8 deoptimization | Micro-opt (performance-misc) | 3-5x |
| String concatenation in loop with + | Quadratic string copying | Micro-opt (performance-misc) | 2-10x |
How to use this table:
tools
Implement QRSPI-planned OpenSpec changes with intelligent parallelization. Use when the user wants to apply a QRSPI change, implement tasks with parallelization, or says "apply this QRSPI change", "implement with parallelization", "run the parallel slices". This skill is specifically designed for changes created via accelint-qrspi that include "Parallelization Strategy" sections in tasks.md. It orchestrates parallel sub-agent execution for independent task slices using OpenSpec CLI workflows. Make sure to use this skill when the user mentions applying QRSPI changes, running parallel implementation, or working on changes with vertical slices.
development
Generate or update an ARCHITECTURE.md living document for any codebase. Use this skill whenever a user mentions "architecture.md", "ARCHITECTURE.md", "document my architecture", "architecture overview", "system architecture", "generate architecture doc", "create architecture file", "update architecture", "architecture diagram", or wants a technical overview of how their project is structured. Make sure to use this skill whenever users want to document how their system works — even if they phrase it as "write up the system", "document the tech stack", "create a technical overview", or "help me describe the architecture". Always prefer this skill over ad-hoc architecture documentation.
development
Automate the QRSPI + OpenSpec planning workflow (Questions → Research → Design → Structure) for spec-driven development. Use this skill when the user wants to plan a ticket, start a QRSPI workflow, create a change with QRSPI, or says "plan this with QRSPI", "use QRSPI to plan", "start QRSPI workflow", "create spec-driven change", or asks about planning a feature/change before implementation. This skill handles ONLY the planning phase — it does NOT implement code. After completion, the user continues with /opsx:apply for implementation.
development
Comprehensive TypeScript/JavaScript coding standards focusing on type safety, defensive programming, and code correctness. Use when (1) Writing or reviewing TS/JS code, (2) Fixing type errors or avoiding any/enum/null, (3) Implementing control flow, state management, or error handling, (4) Applying zero-value pattern or immutability, (5) Code review for TypeScript anti-patterns. Covers naming conventions, function design, return values, bounded iteration, input validation. For performance optimization, use accelint-ts-performance skill. For documentation, use accelint-ts-documentation skill.