home / skills / yelmuratoff / agent_sync / performance

performance skill

/.ai/src/skills/performance

This skill helps you diagnose performance issues in Flutter apps, then optimize rendering, lists, and heavy work off the UI thread.

npx playbooks add skill yelmuratoff/agent_sync --skill performance

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

Files (1)
SKILL.md
2.1 KB
---
name: performance
description: When diagnosing jank, reducing rebuild cost, optimizing lists/rendering, or moving work off the UI thread.
---

# Performance (Measure, Then Optimize)

## When to use

- Jank (missed frames) during scrolling, animations, or screen transitions.
- Slow startup, slow screen open, or large memory usage.
- Large lists/images causing stutters.
- Heavy parsing/formatting done in the UI layer.

## Steps

### 1) Measure first (don’t guess)

Use Flutter DevTools:

- frame chart (UI vs raster time)
- CPU profiler
- memory (leaks, churn)

Define a small “before/after” metric (e.g., 99th percentile frame time while scrolling).

### 2) Reduce rebuild cost

Common wins:

```dart
// Prefer const when possible
const SizedBox(height: 8);
```

```dart
// Keep BLoC states minimal; avoid putting large mutable objects in state.
```

Avoid passing large objects through widget constructors if a selector can read it from a scope/BLoC.

### 3) Make lists lazy and stable

Prefer lazy builders:

```dart
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) => ItemTile(item: items[index]),
)
```

If items can reorder, use stable keys on item widgets.

### 4) Avoid expensive painting

Avoid unnecessary `Opacity`, `Clip.*`, and patterns that trigger saveLayer unless needed.

### 4b) Isolate frequent repainters with RepaintBoundary

Wrap any widget driven by an `AnimationController`, `Ticker`, or high-frequency stream:

```dart
RepaintBoundary(
  child: AnimatedCounter(value: elapsed),
)
```

When to apply: DevTools "Highlight Repaints" shows the parent tree flashing on every animation frame.

Caution: Do not wrap everything—`RepaintBoundary` allocates an extra layer and increases GPU memory. Apply only where profiling identifies propagating repaints as the bottleneck.

### 5) Move heavy work off the UI thread

Use isolates/compute for:

- large JSON parsing
- heavy mapping/sorting
- complex formatting

```dart
final result = await Isolate.run(() => heavyWork(input));
```

### 6) Keep performance fixes testable

Refactor heavy logic into pure functions/classes so it can be unit tested and benchmarked in isolation.

Overview

This skill helps diagnose and fix Flutter performance problems by guiding measurement, reducing UI work, optimizing lists and painting, and moving heavy work off the UI thread. It focuses on practical steps you can apply quickly to eliminate jank, shrink rebuild cost, and stabilize rendering under load.

How this skill works

Start by measuring with Flutter DevTools (frame chart, CPU profiler, memory inspector) and define a simple before/after metric such as 99th percentile frame time while scrolling. Inspect rebuilds, paint/compose times, and memory churn. Apply targeted mitigations: minimize rebuild cost, convert lists to lazy builders, isolate frequent repainters with RepaintBoundary where justified, and run heavy computation in isolates or compute.

When to use it

  • You see dropped frames or jank during scrolling, animations, or transitions.
  • App startup or screen open times feel slow or memory usage is high.
  • Large lists or images cause stutters during interaction.
  • Heavy parsing, sorting, or formatting runs on the UI thread.
  • You need reliable before/after metrics to validate optimizations.

Best practices

  • Measure first—profile frame, CPU, and memory to find the real bottleneck.
  • Keep widget state minimal and prefer const widgets to reduce rebuild cost.
  • Use ListView.builder or other lazy builders; give item widgets stable keys when order changes.
  • Avoid patterns that force expensive compositing (unnecessary Opacity, Clip, saveLayer).
  • Wrap only hot repainting subtrees with RepaintBoundary after profiling.
  • Move heavy parsing or computation to isolates and keep logic testable and pure.

Example use cases

  • Reduce jank in a chat app that stutters while new messages stream in by profiling and isolating repainting widgets.
  • Speed up onboarding by moving large JSON parsing into an isolate and measuring startup frame times.
  • Optimize a product list by switching to ListView.builder with stable keys and trimming widget rebuilds.
  • Fix a CPU-bound animation by profiling, identifying repaint propagation, and applying RepaintBoundary selectively.
  • Refactor formatting logic into pure functions so you can unit test and benchmark performance changes.

FAQ

When should I use RepaintBoundary?

Use it when profiling shows a subtree repaints at high frequency and those repaints propagate to large parents; avoid wrapping everything because it increases GPU memory.

How do I know if work must move off the UI thread?

If CPU profiling shows long synchronous tasks (parsing, sorting, heavy mapping) on the UI isolate causing frame spikes, move that work to an isolate or compute.