home / skills / levnikolaevich / claude-code-skills / ln-653-runtime-performance-auditor

ln-653-runtime-performance-auditor skill

/ln-653-runtime-performance-auditor

This skill analyzes code for runtime performance anti-patterns and returns structured findings with severity and recommendations.

npx playbooks add skill levnikolaevich/claude-code-skills --skill ln-653-runtime-performance-auditor

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
7.7 KB
---
name: ln-653-runtime-performance-auditor
description: "Runtime performance audit worker (L3). Checks blocking IO in async, unnecessary allocations, sync sleep in async, string concat in loops, missing to_thread for CPU-bound, redundant data copies. Returns findings with severity, location, effort, recommendations."
allowed-tools: Read, Grep, Glob, Bash
---

> **Paths:** File paths (`shared/`, `references/`, `../ln-*`) are relative to skills repo root. If not found at CWD, locate this SKILL.md directory and go up one level for repo root.

# Runtime Performance Auditor (L3 Worker)

Specialized worker auditing runtime performance anti-patterns in async and general code.

## Purpose & Scope

- **Worker in ln-650 coordinator pipeline** - invoked by ln-650-persistence-performance-auditor
- Audit **runtime performance** (Priority: MEDIUM)
- Check async anti-patterns, unnecessary allocations, blocking operations
- Return structured findings with severity, location, effort, recommendations
- Calculate compliance score (X/10) for Runtime Performance category

## Inputs (from Coordinator)

**MANDATORY READ:** Load `shared/references/task_delegation_pattern.md#audit-coordinator--worker-contract` for contextStore structure.

Receives `contextStore` with: `tech_stack`, `best_practices`, `codebase_root`.

**Domain-aware:** Supports `domain_mode` + `current_domain`.

## Workflow

1) **Parse context from contextStore**
   - Extract tech_stack, best_practices
   - Determine scan_path
   - Detect async framework: asyncio (Python), Node.js async, Tokio (Rust)

2) **Scan codebase for violations**
   - Grep patterns scoped to `scan_path`
   - For Rules 1, 3, 5: detect `async def` blocks first, then check for violations inside them

3) **Collect findings with severity, location, effort, recommendation**

4) **Calculate score using penalty algorithm**

5) **Return JSON result to coordinator**

## Audit Rules (Priority: MEDIUM)

### 1. Blocking IO in Async
**What:** Synchronous file/network operations inside async functions, blocking event loop

**Detection (Python):**
- Find `async def` functions
- Inside them, grep for blocking calls:
  - File: `open(`, `.read_bytes()`, `.read_text()`, `.write_bytes()`, `.write_text()`, `Path(...).(read|write)`
  - Network: `requests.get`, `requests.post`, `urllib.request`
  - Subprocess: `subprocess.run(`, `subprocess.call(`
- Exclude: calls wrapped in `await asyncio.to_thread(...)` or `await loop.run_in_executor(...)`

**Detection (Node.js):**
- Inside `async function` or arrow async, grep for `fs.readFileSync`, `fs.writeFileSync`, `child_process.execSync`

**Severity:**
- **HIGH:** Blocking IO in API request handler (blocks entire event loop)
- **MEDIUM:** Blocking IO in background task/worker

**Recommendation:** Use `aiofiles`, `asyncio.to_thread()`, or `loop.run_in_executor()` for file operations; use `httpx.AsyncClient` instead of `requests`

**Effort:** S (wrap in to_thread or switch to async library)

### 2. Unnecessary List Allocation
**What:** List comprehension where generator expression suffices

**Detection:**
- `len([x for x in ...])` - allocates list just to count; use `sum(1 for ...)`
- `any([x for x in ...])` - allocates list for short-circuit check; use `any(x for ...)`
- `all([x for x in ...])` - same pattern; use `all(x for ...)`
- `set([x for x in ...])` - use set comprehension `{x for x in ...}`
- `"".join([x for x in ...])` - use generator directly `"".join(x for x in ...)`

**Severity:**
- **MEDIUM:** Unnecessary allocation in hot path (API handler, loop)
- **LOW:** Unnecessary allocation in infrequent code

**Recommendation:** Replace `[...]` with generator `(...)` or set comprehension `{...}`

**Effort:** S (syntax change only)

### 3. Sync Sleep in Async
**What:** `time.sleep()` inside async function blocks event loop

**Detection:**
- Grep for `time\.sleep` inside `async def` blocks
- Pattern: `await some_async_call()` ... `time.sleep(N)` ... `await another_call()`

**Severity:**
- **HIGH:** `time.sleep()` in async API handler (freezes all concurrent requests)
- **MEDIUM:** `time.sleep()` in async background task

**Recommendation:** Replace with `await asyncio.sleep(N)`

**Effort:** S (one-line change)

### 4. String Concatenation in Loop
**What:** Building string via `+=` inside loop (O(n^2) for large strings)

**Detection:**
- Pattern: variable `result`, `output`, `html`, `text` with `+=` inside `for`/`while` loop
- Grep for: variable followed by `+=` containing string operand inside loop body

**Severity:**
- **MEDIUM:** String concat in loop processing large data (>100 iterations)
- **LOW:** String concat in loop with small iterations (<100)

**Recommendation:** Use `list.append()` + `"".join()`, or `io.StringIO`, or f-string with `"".join(generator)`

**Effort:** S (refactor to list + join)

### 5. Missing `to_thread` for CPU-Bound
**What:** CPU-intensive synchronous code in async handler without offloading to thread

**Detection:**
- Inside `async def`, find CPU-intensive operations:
  - JSON parsing large files: `json.loads(large_data)`, `json.load(file)`
  - Image processing: `PIL.Image.open`, `cv2.imread`
  - Crypto: `hashlib`, `bcrypt.hashpw`
  - XML/HTML parsing: `lxml.etree.parse`, `BeautifulSoup(`
  - Large data transformation without await points
- Exclude: operations already wrapped in `asyncio.to_thread()` or executor

**Severity:**
- **MEDIUM:** CPU-bound operation in async handler (blocks event loop proportionally to data size)

**Recommendation:** Wrap in `await asyncio.to_thread(func, *args)` (Python 3.9+) or `loop.run_in_executor(None, func, *args)`

**Effort:** S (wrap in to_thread)

### 6. Redundant Data Copies
**What:** Unnecessary `.copy()`, `list()`, `dict()` when data is only read, not mutated

**Detection:**
- `data = list(items)` where `data` is only iterated (never modified)
- `config = config_dict.copy()` where `config` is only read
- `result = dict(original)` where `result` is returned without modification

**Severity:**
- **LOW:** Redundant copy in most contexts (minor memory overhead)
- **MEDIUM:** Redundant copy of large data in hot path

**Recommendation:** Remove unnecessary copy; pass original if not mutated

**Effort:** S (remove copy call)

## Scoring Algorithm

**MANDATORY READ:** Load `shared/references/audit_scoring.md` for unified scoring formula.

## Output Format

Return JSON to coordinator:

```json
{
  "category": "Runtime Performance",
  "score": 7,
  "total_issues": 5,
  "critical": 0,
  "high": 2,
  "medium": 2,
  "low": 1,
  "findings": [
    {
      "severity": "HIGH",
      "location": "app/infrastructure/messaging/job_processor.py:444",
      "issue": "Blocking IO: input_path.read_bytes() inside async function blocks event loop",
      "principle": "Async Best Practices / Non-Blocking IO",
      "recommendation": "Use aiofiles or await asyncio.to_thread(input_path.read_bytes)",
      "effort": "S"
    }
  ]
}
```

## Critical Rules

- **Do not auto-fix:** Report only
- **Async context required:** Rules 1, 3, 5 apply ONLY inside async functions
- **Exclude wrappers:** Do not flag calls already wrapped in `to_thread`/`run_in_executor`
- **Context-aware:** Small files (<1KB) read synchronously may be acceptable
- **Exclude tests:** Do not flag test utilities or test fixtures

## Definition of Done

- contextStore parsed (tech_stack, async framework)
- scan_path determined
- Async framework detected (asyncio/Node.js async/Tokio)
- All 6 checks completed:
  - blocking IO, unnecessary allocations, sync sleep, string concat, CPU-bound, redundant copies
- Findings collected with severity, location, effort, recommendation
- Score calculated
- JSON returned to coordinator

## Reference Files

- **Audit scoring formula:** `shared/references/audit_scoring.md`
- **Audit output schema:** `shared/references/audit_output_schema.md`

---
**Version:** 1.0.0
**Last Updated:** 2026-02-04

Overview

This skill audits runtime performance anti-patterns in application code, focused on async contexts and hot paths. It detects blocking I/O in async functions, sync sleep in async code, unnecessary allocations and copies, string concatenation in loops, and CPU-bound work not offloaded to threads. Findings include severity, file location, estimated effort, and concrete recommendations. The worker also computes a compliance score for the Runtime Performance category.

How this skill works

The auditor reads contextStore to determine tech stack, best practices, scan path, and async framework (asyncio, Node.js async, or Tokio). It scans files under the scan path, locating async functions first for rules that apply only in async context, then applies pattern-based detections for each rule. It collects structured findings (severity, location, issue, principle, recommendation, effort), applies a penalty-based scoring algorithm, and returns a JSON result to the coordinator.

When to use it

  • CI pipeline step before merge to catch runtime regressions
  • Periodic codebase audits focused on performance and scalability
  • Pre-release checks for services handling concurrent requests
  • During refactors that touch async handlers or hot loops
  • When diagnosing high-latency or CPU-bound production incidents

Best practices

  • Only flag blocking calls inside async functions; exclude wrappers like asyncio.to_thread or run_in_executor
  • Prefer async libraries (aiofiles, httpx.AsyncClient) for I/O in async handlers
  • Replace repeated string += in loops with list.append() + ''.join() or io.StringIO
  • Use generator expressions and set comprehensions to avoid unnecessary list allocation
  • Offload CPU-bound synchronous work in async handlers with await asyncio.to_thread(...)

Example use cases

  • Find requests.get or open() calls inside async API handlers and recommend aio alternatives or to_thread
  • Detect len([x for ...]) and suggest sum(1 for ...) to avoid list allocation
  • Spot time.sleep() used inside async functions and recommend await asyncio.sleep()
  • Identify large data copies like list(items) in hot loops and recommend removing the copy
  • Flag += string building inside loops processing many items and recommend join-based patterns

FAQ

Does the auditor auto-fix issues?

No. The skill reports findings with recommendations but does not modify source code.

Will it flag small synchronous reads like tiny config files?

Small file reads under a context-aware size threshold are treated as acceptable; the auditor focuses on hot paths and large or blocking operations.