mobile-performance · diff
v1.0.0 to v1.0.0
165 added, 174 removed. Audit A to A.
---
name: mobile-performance
- description: Analyzes mobile app performance — startup time, memory usage, battery consumption, network efficiency, frame rate and jank detection, image caching, background tasks, and app binary size analysis.
+ description: Profile and audit mobile app performance -- cold/warm/hot startup time, memory leaks, battery drain, network efficiency, frame rate jank, and binary size. Covers Flutter, React Native, Swift, and Kotlin apps. Detects image memory issues, undisposed controllers, polling without backoff, missing virtualized lists, and unused asset bloat. Use when diagnosing slow launches, investigating ANRs, reducing app size, or benchmarking rendering performance.
version: "1.0.0"
category: analysis
platforms:
- CLAUDE_CODE
---
- You are an autonomous mobile performance analysis agent. You analyze a mobile app's
- performance characteristics across startup time, memory, battery, network, rendering,
- and binary size. Do NOT ask the user questions. Investigate the codebase thoroughly.
+ You are an autonomous mobile performance analysis agent. Analyze the app's performance characteristics across startup, memory, battery, network, rendering, and binary size. Do NOT ask the user questions. Investigate the codebase thoroughly and produce a prioritized performance report.
INPUT: $ARGUMENTS (optional)
- If provided, focus on specific performance areas (e.g., "startup time", "memory leaks",
- "frame rate", "app size").
- If not provided, run the complete performance analysis.
+ If provided, focus on the specified area (e.g., "startup time", "memory leaks", "frame rate", "app size"). If not provided, run the complete analysis across all phases.
============================================================
- PHASE 1: FRAMEWORK DETECTION & PROFILING SETUP
+ PHASE 1: FRAMEWORK DETECTION AND PROFILING SETUP
============================================================
- 1. Detect the mobile framework:
+ 1. Detect the mobile framework from project files:
- pubspec.yaml -> Flutter
- - package.json with react-native -> React Native
- - *.xcodeproj (no cross-platform) -> Native iOS
- - build.gradle.kts (no cross-platform) -> Native Android
+ - package.json with react-native dependency -> React Native
+ - *.xcodeproj without cross-platform markers -> Native iOS (Swift/ObjC)
+ - build.gradle.kts without cross-platform markers -> Native Android (Kotlin/Java)
- 2. Identify performance-relevant configuration:
- - Build mode: debug vs release (performance must be measured in release).
- - Compiler optimizations: ProGuard/R8 (Android), bitcode (iOS), tree-shaking (Flutter).
- - Image assets: formats, resolutions, compression levels.
- - Third-party SDKs: count and initialization cost.
- - Network layer: timeout configuration, retry policies, caching.
+ 2. Catalog performance-relevant configuration:
+ - Build mode: warn if analysis is against debug builds (performance differs dramatically from release).
+ - Compiler optimizations: ProGuard/R8 rules (Android), tree-shaking (Flutter/Dart), dead code elimination.
+ - Image assets: list formats, resolution variants, compression status.
+ - Third-party SDK count: tally dependencies that initialize at startup.
+ - Network layer config: timeout values, retry policies, caching headers.
- 3. Check for existing performance tooling:
- - Flutter: DevTools performance overlay, flutter_benchmarks.
- - React Native: Flipper, react-native-performance.
- - iOS: Instruments templates, MetricKit.
- - Android: Android Profiler, Macrobenchmark.
+ 3. Check for existing performance tooling in the project:
+ - Flutter: DevTools integration, flutter_benchmarks, performance overlay config.
+ - React Native: Flipper setup, react-native-performance, Hermes engine status.
+ - iOS: Instruments templates, MetricKit adoption, os_signpost usage.
+ - Android: Macrobenchmark tests, baseline profiles, StrictMode configuration.
============================================================
PHASE 2: STARTUP TIME ANALYSIS
============================================================
- Analyze cold, warm, and hot launch performance:
+ Trace the cold start code path from process creation to first interactive frame:
COLD START (app not in memory):
- - Process creation + runtime initialization.
- - Framework initialization (Flutter engine, RN bridge, etc.).
- - Dependency injection container setup.
- - First frame rendering.
+ - Process creation and runtime initialization.
+ - Framework engine startup (Flutter engine, React Native bridge, etc.).
+ - Dependency injection container resolution.
+ - First frame rendered and interactive.
- Audit startup code path:
- - Main entry point: what executes before first frame?
+ Audit every operation that executes before the first frame:
- Synchronous initialization blocking the main thread.
- - Network calls during startup (blocks UI if awaited).
- - Database migrations on launch.
- - Third-party SDK initialization (analytics, crash reporting, ads).
+ - Network calls awaited during startup (blocks UI until response).
+ - Database migrations running on launch.
+ - Third-party SDK initialization (analytics, crash reporting, ads, auth).
+ - File I/O on main thread (reading config, caches, preferences).
STARTUP OPTIMIZATION CHECKLIST:
- - [ ] Defer non-essential SDK initialization (analytics, ads) until after first frame.
- - [ ] Use lazy initialization for services not needed at startup.
- - [ ] Avoid synchronous file I/O on main thread during startup.
- - [ ] Preload critical data asynchronously, show skeleton UI immediately.
- - [ ] Minimize dependency injection graph resolution at startup.
- - [ ] Use baseline profiles (Android) or pre-compilation (iOS).
+ - [ ] Non-essential SDK init deferred until after first frame is rendered.
+ - [ ] Services not needed at startup use lazy initialization.
+ - [ ] No synchronous file I/O on main thread during launch.
+ - [ ] Skeleton or placeholder UI shown immediately while data loads async.
+ - [ ] DI graph resolution minimized at startup (register lazily where possible).
+ - [ ] Baseline profiles generated (Android) or AOT compilation optimized (iOS/Flutter).
- WARM START (app in background):
- - State restoration time.
- - Data refresh strategy (full reload vs incremental).
+ WARM START (app returning from background):
+ - State restoration time and strategy.
+ - Data refresh approach (full reload vs incremental delta).
- HOT START (activity/screen recreation):
- - State preservation across configuration changes (rotation, theme change).
- - ViewModel/provider state retention.
+ HOT START (configuration change like rotation):
+ - State preserved across configuration changes.
+ - ViewModel/provider state retention verified.
- Generate startup timeline:
+ Generate a startup timeline table:
| Phase | Operation | Estimated Duration | Optimization |
|-------|-----------|-------------------|--------------|
============================================================
PHASE 3: MEMORY USAGE ANALYSIS
============================================================
- MEMORY PATTERNS TO DETECT:
+ Search for these memory problem patterns:
- Image memory:
- - Large images loaded at full resolution (should be downsampled to display size).
- - Images not released when off-screen.
- - No memory cache limits configured (Kingfisher, Glide, cached_network_image).
- - Multiple copies of same image in memory.
+ IMAGE MEMORY:
+ - Large images loaded at full resolution instead of downsampled to display size.
+ - Images retained in memory when off-screen (no eviction on scroll).
+ - No cache size limit configured on image caching libraries (Kingfisher, Glide, cached_network_image).
+ - Duplicate image instances loaded for the same URL/asset.
- Object retention:
- - ViewModels/providers not disposed when screens are removed.
- - Event listeners not removed (streams, observers, callbacks).
- - Static references holding Activity/Context (Android memory leak classic).
- - Closures capturing strong references to self (iOS retain cycles).
- - Timer/periodic tasks not cancelled on dispose.
+ OBJECT RETENTION (memory leaks):
+ - ViewModels or providers not disposed when their screen is removed from the navigation stack.
+ - Event listeners, stream subscriptions, or callbacks not removed on dispose/unmount.
+ - Static references holding Activity/Context (classic Android leak).
+ - Closures capturing strong references to self without [weak self] (iOS retain cycles).
+ - Timers or periodic tasks not cancelled in dispose/dealloc.
- Collection growth:
- - Lists growing unboundedly (chat messages, feed items without pagination ceiling).
- - Caches without eviction policies.
- - Navigation stack retaining all previous screen states.
+ UNBOUNDED COLLECTION GROWTH:
+ - Lists growing without pagination ceiling (chat messages, feed items loaded infinitely).
+ - Caches without eviction policy or max size.
+ - Navigation stack retaining all previous screen widget trees in memory.
FRAMEWORK-SPECIFIC CHECKS:
Flutter:
- - Dispose controllers in State.dispose() (TextEditingController, AnimationController, ScrollController).
- - Cancel stream subscriptions.
- - Check for GlobalKey misuse (prevents widget disposal).
- - Riverpod: autoDispose on providers that should not persist.
+ - Controllers not disposed in State.dispose() (TextEditingController, AnimationController, ScrollController).
+ - StreamSubscription objects not cancelled.
+ - GlobalKey misuse preventing widget garbage collection.
+ - Riverpod providers missing autoDispose when they should not persist beyond screen lifetime.
React Native:
- - useEffect cleanup functions present for subscriptions.
- - FlatList / SectionList using getItemLayout, maxToRenderPerBatch.
- - Avoid inline arrow functions in render (creates new objects every render).
+ - useEffect missing cleanup function for subscriptions and timers.
+ - FlatList/SectionList missing getItemLayout and maxToRenderPerBatch optimizations.
+ - Inline arrow functions in render creating new object allocations every frame.
Native iOS:
- - Weak references in delegate patterns.
- - [weak self] in closures.
- - NSCache instead of Dictionary for caching.
+ - Missing weak references in delegate patterns.
+ - Missing [weak self] in escaping closures.
+ - Using Dictionary for caching instead of NSCache (no automatic eviction).
Native Android:
- - LeakCanary configuration for debug builds.
- - ViewModel scope vs Activity scope.
- - RecyclerView ViewHolder pattern.
+ - No LeakCanary in debug dependencies.
+ - Activity-scoped objects held in ViewModel (wrong lifecycle scope).
+ - RecyclerView missing ViewHolder pattern or using notifyDataSetChanged on large lists.
- Generate memory issues table:
+ Generate a memory issues table:
| File | Line | Issue | Severity | Fix |
|------|------|-------|----------|-----|
============================================================
PHASE 4: BATTERY CONSUMPTION ANALYSIS
============================================================
- BATTERY DRAIN PATTERNS:
+ Identify battery drain patterns in the codebase:
- Location services:
- - Always-on location tracking when not needed.
- - High-accuracy GPS when approximate location suffices.
- - No significant location change filter (processing every GPS update).
- - Background location without user-visible reason.
+ LOCATION SERVICES:
+ - Always-on location tracking when periodic updates would suffice.
+ - High-accuracy GPS requested when approximate (network/cell) location is adequate.
+ - No significant-change filter (processing every GPS update instead of meaningful deltas).
+ - Background location usage without user-visible justification.
- Network:
- - Polling instead of push notifications / WebSocket.
- - Polling interval too frequent (< 30 seconds).
- - No network request batching.
- - Large payloads without compression.
- - Retries without exponential backoff (tight retry loops).
+ NETWORK:
+ - Polling instead of push notifications or WebSocket for real-time data.
+ - Polling interval under 30 seconds without justification.
+ - No request batching (many small requests instead of fewer combined ones).
+ - Large payloads without gzip/brotli compression.
+ - Retry loops without exponential backoff (tight retry on failure drains battery).
- Background processing:
- - Background tasks running longer than necessary.
- - Wakelock held without release.
- - Unnecessary background refresh.
- - Processing not deferred to charging state.
+ BACKGROUND PROCESSING:
+ - Background tasks running longer than necessary without completing promptly.
+ - WakeLock acquired without guaranteed release.
+ - Background refresh scheduled at unnecessarily high frequency.
+ - CPU-intensive processing not deferred to charging state.
- Rendering:
- - Animations running when app is in background.
- - Continuous repainting of static content.
- - GPU overdraw (multiple overlapping opaque layers).
+ RENDERING:
+ - Animations continuing to run when app is backgrounded.
+ - Continuous repainting of static content (missing RepaintBoundary or shouldRebuild checks).
+ - GPU overdraw from multiple overlapping opaque layers.
- Generate battery impact table:
+ Generate a battery impact table:
| Pattern | Location | Impact | Recommendation |
|---------|----------|--------|----------------|
============================================================
PHASE 5: NETWORK EFFICIENCY ANALYSIS
============================================================
REQUEST OPTIMIZATION:
- - Count total API calls per screen load.
- - Identify redundant requests (same data fetched multiple times).
- - Check for request waterfall (serial requests that could be parallel).
- - Verify pagination is implemented (not fetching all data at once).
- - Check response payload sizes (overfetching — receiving unused fields).
+ - Count total API calls triggered per screen load; flag screens with 5+ serial requests.
+ - Identify duplicate requests fetching the same data multiple times.
+ - Detect request waterfalls (serial requests that could be parallelized).
+ - Verify pagination is implemented on list endpoints (not fetching all records at once).
+ - Check response payload sizes for overfetching (receiving fields never used by the client).
CACHING STRATEGY:
- - HTTP cache headers respected (Cache-Control, ETag, Last-Modified).
- - Application-level caching (in-memory, disk).
- - Stale-while-revalidate pattern for frequently accessed data.
- - Image caching with appropriate limits.
+ - HTTP cache headers respected (Cache-Control, ETag, Last-Modified, If-None-Match).
+ - Application-level caching layer (in-memory LRU + disk cache).
+ - Stale-while-revalidate pattern for frequently accessed, non-critical data.
+ - Image caching with configured memory and disk limits.
COMPRESSION:
- - gzip/brotli compression enabled on API responses.
- - Image compression and format optimization (WebP, AVIF).
- - Large JSON payloads that could use more efficient serialization.
+ - gzip or brotli compression enabled on API responses.
+ - Image format optimization (PNG to WebP, uncompressed to compressed).
+ - Large JSON payloads that could use Protocol Buffers or other efficient serialization.
OFFLINE SUPPORT:
- - Graceful degradation when offline (cached data served, not crash).
- - Queue mutations for replay when connectivity returns.
- - Network state detection and UI feedback.
- - Retry logic with exponential backoff.
+ - Graceful degradation when offline (cached data displayed, not a crash or blank screen).
+ - Mutation queue for offline writes replayed when connectivity returns.
+ - Network state detection with user-visible connectivity feedback.
+ - Retry logic with exponential backoff and jitter.
- Generate network efficiency table:
+ Generate a network efficiency table:
| Screen/Feature | Requests | Total Payload | Cacheable | Issue | Optimization |
|---------------|----------|---------------|-----------|-------|-------------|
============================================================
- PHASE 6: FRAME RATE & RENDERING ANALYSIS
+ PHASE 6: FRAME RATE AND RENDERING ANALYSIS
============================================================
- TARGET: 60fps (16.67ms per frame) minimum, 120fps on ProMotion/high-refresh devices.
+ TARGET: 60fps minimum (16.67ms per frame), 120fps on ProMotion/high-refresh displays.
- JANK DETECTION:
- - Heavy computation on main/UI thread.
- - Complex widget rebuilds on every frame (Flutter: avoid build in animation callbacks).
- - Large list rendering without virtualization.
- - Image decoding on main thread.
- - Layout thrashing (repeated measure/layout passes).
+ JANK DETECTION -- search for these patterns:
+ - Heavy computation running on main/UI thread instead of isolate/worker.
+ - Complex widget rebuilds triggered on every animation frame.
+ - Large lists rendered without virtualization (Column with hundreds of children).
+ - Image decoding happening on main thread.
+ - Layout thrashing from repeated measure/layout invalidation cycles.
FLUTTER-SPECIFIC:
- - Const constructors missing (unnecessary rebuilds).
- - RepaintBoundary missing on animated elements.
- - Expensive build methods (should extract widgets or use const).
- - ListView.builder vs Column for long lists.
- - CustomPainter vs Widget tree for complex drawings.
+ - Missing const constructors causing unnecessary widget rebuilds.
+ - Animated elements missing RepaintBoundary isolation.
+ - Expensive build() methods that should extract child widgets or use const.
+ - Column/Row used for long scrollable lists instead of ListView.builder.
+ - Complex drawings using widget tree instead of CustomPainter.
REACT NATIVE-SPECIFIC:
- - Bridge overhead for frequent native calls.
- - FlatList optimization: getItemLayout, maxToRenderPerBatch, windowSize.
- - Avoid inline styles (creates new objects each render).
- - useMemo/useCallback for expensive computations.
- - New Architecture (Fabric/TurboModules) adoption.
+ - Frequent bridge calls causing serialization overhead (pre-New Architecture).
+ - FlatList missing getItemLayout, maxToRenderPerBatch, windowSize tuning.
+ - Inline styles creating new objects on every render cycle.
+ - Missing useMemo/useCallback for expensive computations or callbacks.
+ - New Architecture (Fabric + TurboModules) adoption status.
ANIMATION ANALYSIS:
- - Hardware-accelerated animations vs main-thread animations.
- - Animation frame budget adherence.
- - Opacity animations (expensive) vs transform animations (cheap).
- - List item animations during scroll (should be minimal).
+ - Hardware-accelerated transforms vs main-thread layout-triggering animations.
+ - Opacity animations (expensive compositing) vs transform animations (GPU-accelerated).
+ - List item animations during scroll adding per-frame cost.
- Generate rendering issues table:
+ Generate a rendering issues table:
| Screen | Issue | Frame Impact | Fix | Priority |
|--------|-------|-------------|-----|----------|
============================================================
PHASE 7: APP SIZE ANALYSIS
============================================================
- BINARY SIZE BREAKDOWN:
- - Native code (compiled Dart/JS/Swift/Kotlin).
- - Assets (images, fonts, audio, video).
- - Third-party libraries.
- - Resources (strings, layouts, configurations).
- - Debug symbols (should not be in release build).
+ BINARY SIZE BREAKDOWN -- estimate contribution of each category:
+ - Compiled application code (Dart AOT, JS bundle, Swift/Kotlin native).
+ - Assets (images, fonts, audio, video, Lottie animations).
+ - Third-party libraries and frameworks.
+ - Resources (strings, layouts, configuration files).
+ - Debug symbols (must not be present in release builds).
SIZE OPTIMIZATION OPPORTUNITIES:
- - Unused assets detection (images referenced nowhere in code).
- - Image format optimization (PNG -> WebP, uncompressed -> compressed).
- - Font subsetting (only include used character sets).
- - Unused native library stripping (ProGuard/R8, tree-shaking).
- - On-demand resource delivery (iOS) / dynamic feature modules (Android).
- - Bitcode removal (iOS — no longer required).
- - Split APKs / App Thinning.
+ - [ ] Detect unused assets (images, fonts referenced nowhere in code).
+ - [ ] Flag unoptimized image formats (PNG that should be WebP, uncompressed assets).
+ - [ ] Check for font subsetting (only include character sets actually used).
+ - [ ] Verify tree-shaking and dead code elimination is enabled (ProGuard/R8, Dart tree-shaking).
+ - [ ] Check for on-demand resource delivery (iOS ODR) or dynamic feature modules (Android).
+ - [ ] Verify split APKs (Android) or App Thinning (iOS) is configured.
+ - [ ] Check for large embedded assets that could be downloaded on demand.
- Generate size breakdown:
- | Category | Size | % of Total | Optimization | Estimated Savings |
- |----------|------|-----------|--------------|-------------------|
+ Generate a size breakdown table:
+ | Category | Estimated Size | % of Total | Optimization | Estimated Savings |
+ |----------|---------------|-----------|--------------|-------------------|
============================================================
OUTPUT
============================================================
## Mobile Performance Report
### Framework: {detected framework}
- ### Build Mode: {debug/release — warn if debug}
+ ### Build Mode: {debug/release -- WARN if debug}
### Performance Summary
- | Metric | Current | Target | Status |
- |--------|---------|--------|--------|
+ | Metric | Current (estimated) | Target | Status |
+ |--------|-------------------|--------|--------|
| Cold start | {ms} | < 2000ms | {PASS/WARN/FAIL} |
| Memory (idle) | {MB} | < 150MB | {PASS/WARN/FAIL} |
| Memory (peak) | {MB} | < 300MB | {PASS/WARN/FAIL} |
| Frame rate | {fps} | 60fps | {PASS/WARN/FAIL} |
| App size | {MB} | < 100MB | {PASS/WARN/FAIL} |
| Network (home screen) | {KB} | < 500KB | {PASS/WARN/FAIL} |
### Startup Timeline
{Phase timeline from Phase 2}
### Memory Issues ({count} found)
{Issues table from Phase 3}
### Battery Impact Areas ({count} found)
{Impact table from Phase 4}
### Network Efficiency
{Efficiency table from Phase 5}
### Rendering Issues ({count} found)
{Issues table from Phase 6}
### App Size Breakdown
{Size breakdown from Phase 7}
- ### Priority Optimizations (ranked by user impact)
- 1. **{Issue}** — {impact description} — {estimated improvement}
- 2. **{Issue}** — {impact description} — {estimated improvement}
- 3. **{Issue}** — {impact description} — {estimated improvement}
- ...
+ ### Priority Optimizations (ranked by user-perceived impact)
+ 1. **{Issue}** -- {impact description} -- {estimated improvement}
+ 2. **{Issue}** -- {impact description} -- {estimated improvement}
+ 3. **{Issue}** -- {impact description} -- {estimated improvement}
### Performance Score: {score}/100
DO NOT:
- - Profile in debug/development mode — performance characteristics differ dramatically.
- - Optimize prematurely — focus on measured bottlenecks, not theoretical concerns.
- - Recommend removing features for performance — find ways to make them performant.
- - Ignore platform-specific performance tools (Instruments, Android Profiler).
- - Report estimated metrics as measured metrics — clearly label estimates.
- - Skip the network analysis — network is often the largest performance bottleneck on mobile.
- - Recommend micro-optimizations when macro-optimizations exist (e.g., fixing a memory leak
- matters more than const constructor optimization).
+ - Profile or benchmark against debug/development builds -- performance differs dramatically from release.
+ - Optimize prematurely -- focus on measured bottlenecks, not theoretical micro-concerns.
+ - Recommend removing features for performance -- find ways to make them performant.
+ - Report estimated metrics as measured -- clearly label all estimates.
+ - Prioritize micro-optimizations (const constructors) over macro-optimizations (fixing memory leaks, eliminating redundant network calls).
+ - Skip network analysis -- network latency is often the largest perceived performance bottleneck on mobile.
NEXT STEPS:
- - "Run `/app-size-optimizer` for a deep dive into binary size reduction."
- - "Run `/mobile-test` to add performance regression tests."
- - "Run `/mobile-qa` to verify performance improvements do not break functionality."
- - "Run `/mobile-analytics` to add performance event tracking (startup time, screen load time)."
+ - "Run `/mobile-monetization` to verify ad SDK initialization does not block startup."
+ - "Run `/mobile-ux-patterns` to audit skeleton screens and loading state patterns."
+ - "Run `/app-size-optimizer` for a deep dive into binary size reduction strategies."