This snapshot establishes the camera-to-result recognition flow and related tests while checking in the project skill/docs assets required for the configured local tooling.
379 lines
13 KiB
Markdown
379 lines
13 KiB
Markdown
---
|
|
name: axiom-energy-diag
|
|
description: Symptom-based energy troubleshooting - decision trees for 'app at top of battery settings', 'phone gets hot', 'background drain', 'high cellular usage', with time-cost analysis for each diagnosis path
|
|
license: MIT
|
|
metadata:
|
|
version: "1.0.0"
|
|
---
|
|
|
|
# Energy Diagnostics
|
|
|
|
Symptom-based troubleshooting for energy issues. Start with your symptom, follow the decision tree, get the fix.
|
|
|
|
**Related skills**: `axiom-energy` (patterns, checklists), `axiom-energy-ref` (API reference)
|
|
|
|
---
|
|
|
|
## Symptom 1: App at Top of Battery Settings
|
|
|
|
Users or you notice your app consuming significant battery.
|
|
|
|
### Diagnosis Decision Tree
|
|
|
|
```
|
|
App at top of Battery Settings?
|
|
│
|
|
├─ Step 1: Run Power Profiler (15 min)
|
|
│ ├─ CPU Power Impact high?
|
|
│ │ ├─ Continuous? → Timer leak or polling loop
|
|
│ │ │ └─ Fix: Check timers, add tolerance, convert to push
|
|
│ │ └─ Spikes during actions? → Eager loading or repeated parsing
|
|
│ │ └─ Fix: Use LazyVStack, cache parsed data
|
|
│ │
|
|
│ ├─ Network Power Impact high?
|
|
│ │ ├─ Many small requests? → Batching issue
|
|
│ │ │ └─ Fix: Batch requests, use discretionary URLSession
|
|
│ │ └─ Regular intervals? → Polling pattern
|
|
│ │ └─ Fix: Convert to push notifications
|
|
│ │
|
|
│ ├─ GPU Power Impact high?
|
|
│ │ ├─ Animations? → Running when not visible
|
|
│ │ │ └─ Fix: Stop in viewWillDisappear
|
|
│ │ └─ Blur effects? → Over dynamic content
|
|
│ │ └─ Fix: Remove or use static backgrounds
|
|
│ │
|
|
│ └─ Display Power Impact high?
|
|
│ └─ Light backgrounds on OLED?
|
|
│ └─ Fix: Implement Dark Mode (up to 70% savings)
|
|
│
|
|
└─ Step 2: Check background section in Battery Settings
|
|
├─ High background time?
|
|
│ ├─ Location icon visible? → Continuous location
|
|
│ │ └─ Fix: Switch to significant-change monitoring
|
|
│ ├─ Audio active? → Session not deactivated
|
|
│ │ └─ Fix: Deactivate audio session when not playing
|
|
│ └─ BGTasks running long? → Not completing promptly
|
|
│ └─ Fix: Call setTaskCompleted sooner
|
|
│
|
|
└─ Background time appropriate?
|
|
└─ Issue is in foreground usage → Focus on CPU/GPU fixes above
|
|
```
|
|
|
|
### Time-Cost Analysis
|
|
|
|
| Approach | Time | Accuracy |
|
|
|----------|------|----------|
|
|
| Run Power Profiler, identify subsystem | 15-20 min | High |
|
|
| Guess and optimize random areas | 4+ hours | Low |
|
|
| Read all code looking for issues | 2+ hours | Medium |
|
|
|
|
**Recommendation**: Always use Power Profiler first. It costs 15 minutes but guarantees you optimize the right subsystem.
|
|
|
|
---
|
|
|
|
## Symptom 2: Device Gets Hot
|
|
|
|
Device temperature increases noticeably during app use.
|
|
|
|
### Diagnosis Decision Tree
|
|
|
|
```
|
|
Device gets hot during app use?
|
|
│
|
|
├─ Hot during specific action?
|
|
│ │
|
|
│ ├─ During video/camera use?
|
|
│ │ ├─ Video encoding? → Expected, but check efficiency
|
|
│ │ │ └─ Fix: Use hardware encoding, reduce resolution if possible
|
|
│ │ └─ Camera active unnecessarily? → Not releasing session
|
|
│ │ └─ Fix: Call stopRunning() when done
|
|
│ │
|
|
│ ├─ During scroll/animation?
|
|
│ │ ├─ GPU-intensive effects? → Blur, shadows, many layers
|
|
│ │ │ └─ Fix: Reduce effects, cache rendered content
|
|
│ │ └─ High frame rate? → Unnecessary 120fps
|
|
│ │ └─ Fix: Use CADisplayLink preferredFrameRateRange
|
|
│ │
|
|
│ └─ During data processing?
|
|
│ ├─ JSON parsing? → Repeated or large payloads
|
|
│ │ └─ Fix: Cache parsed results, paginate
|
|
│ └─ Image processing? → Synchronous on main thread
|
|
│ └─ Fix: Move to background, cache results
|
|
│
|
|
├─ Hot during normal use (no specific action)?
|
|
│ │
|
|
│ ├─ Run Power Profiler to identify:
|
|
│ │ ├─ CPU high continuously → Timer, polling, tight loop
|
|
│ │ ├─ GPU high continuously → Animation leak
|
|
│ │ └─ Network high continuously → Polling pattern
|
|
│ │
|
|
│ └─ Check for infinite loops or runaway recursion
|
|
│ └─ Use Time Profiler in Instruments
|
|
│
|
|
└─ Hot only in background?
|
|
├─ Location updates continuous? → High accuracy or no stop
|
|
│ └─ Fix: Reduce accuracy, stop when done
|
|
├─ Audio session active? → Hardware kept powered
|
|
│ └─ Fix: Deactivate when not playing
|
|
└─ BGTask running too long? → System may throttle
|
|
└─ Fix: Complete tasks faster, use requiresExternalPower
|
|
```
|
|
|
|
### Time-Cost Analysis
|
|
|
|
| Approach | Time | Outcome |
|
|
|----------|------|---------|
|
|
| Power Profiler + Time Profiler | 20-30 min | Identifies exact cause |
|
|
| Check code for obvious issues | 1-2 hours | May miss non-obvious causes |
|
|
| Wait for user complaints | N/A | Reputation damage |
|
|
|
|
---
|
|
|
|
## Symptom 3: Background Battery Drain
|
|
|
|
App drains battery even when user isn't actively using it.
|
|
|
|
### Diagnosis Decision Tree
|
|
|
|
```
|
|
High background battery usage?
|
|
│
|
|
├─ Step 1: Check Info.plist background modes
|
|
│ │
|
|
│ ├─ "location" enabled?
|
|
│ │ ├─ Actually need background location?
|
|
│ │ │ ├─ YES → Use significant-change, lowest accuracy
|
|
│ │ │ └─ NO → Remove background mode, use when-in-use only
|
|
│ │ └─ Check: Is stopUpdatingLocation called?
|
|
│ │
|
|
│ ├─ "audio" enabled?
|
|
│ │ ├─ Audio playing? → Expected
|
|
│ │ ├─ Audio NOT playing? → Session still active
|
|
│ │ │ └─ Fix: Deactivate session, use autoShutdownEnabled
|
|
│ │ └─ Playing silent audio? → Anti-pattern for keeping app alive
|
|
│ │ └─ Fix: Use proper background API (BGTask)
|
|
│ │
|
|
│ ├─ "fetch" enabled?
|
|
│ │ └─ Check: Is earliestBeginDate reasonable? (not too frequent)
|
|
│ │
|
|
│ └─ "remote-notification" enabled?
|
|
│ └─ Expected for push updates, check didReceiveRemoteNotification efficiency
|
|
│
|
|
├─ Step 2: Check BGTaskScheduler usage
|
|
│ │
|
|
│ ├─ BGAppRefreshTask scheduled too frequently?
|
|
│ │ └─ Fix: Increase earliestBeginDate interval
|
|
│ │
|
|
│ ├─ BGProcessingTask not using requiresExternalPower?
|
|
│ │ └─ Fix: Add requiresExternalPower = true for non-urgent work
|
|
│ │
|
|
│ └─ Tasks not completing? (setTaskCompleted not called)
|
|
│ └─ Fix: Always call setTaskCompleted, implement expirationHandler
|
|
│
|
|
└─ Step 3: Check beginBackgroundTask usage
|
|
│
|
|
├─ endBackgroundTask called promptly?
|
|
│ └─ Fix: Call immediately after work completes, not at expiration
|
|
│
|
|
└─ Multiple overlapping background tasks?
|
|
└─ Fix: Track task IDs, ensure each is ended
|
|
```
|
|
|
|
### Common Background Drain Patterns
|
|
|
|
| Pattern | Power Profiler Signature | Fix |
|
|
|---------|-------------------------|-----|
|
|
| Continuous location | CPU lane + location icon | significant-change |
|
|
| Audio session leak | CPU lane steady | setActive(false) |
|
|
| Timer not invalidated | CPU spikes at intervals | invalidate in background |
|
|
| Polling from background | Network lane at intervals | Push notifications |
|
|
| BGTask too long | CPU sustained | Faster completion |
|
|
|
|
### Time-Cost Analysis
|
|
|
|
| Approach | Time | Outcome |
|
|
|----------|------|---------|
|
|
| Check Info.plist + BGTask code | 30 min | Finds common issues |
|
|
| On-device Power Profiler trace | 1-2 hours (real usage) | Captures real behavior |
|
|
| User-collected trace | Variable | Best for unreproducible issues |
|
|
|
|
---
|
|
|
|
## Symptom 4: High Energy Only on Cellular
|
|
|
|
Battery drains faster on cellular than WiFi.
|
|
|
|
### Diagnosis Decision Tree
|
|
|
|
```
|
|
High battery drain on cellular only?
|
|
│
|
|
├─ Expected: Cellular radio uses more power than WiFi
|
|
│ └─ But: Excessive drain indicates optimization opportunity
|
|
│
|
|
├─ Check URLSession configuration
|
|
│ │
|
|
│ ├─ allowsExpensiveNetworkAccess = true (default)?
|
|
│ │ └─ Fix: Set to false for non-urgent requests
|
|
│ │
|
|
│ ├─ isDiscretionary = false (default)?
|
|
│ │ └─ Fix: Set to true for background downloads
|
|
│ │
|
|
│ └─ waitsForConnectivity = false (default)?
|
|
│ └─ Fix: Set to true to avoid failed connection retries
|
|
│
|
|
├─ Check request patterns
|
|
│ │
|
|
│ ├─ Many small requests? → High connection overhead
|
|
│ │ └─ Fix: Batch into fewer larger requests
|
|
│ │
|
|
│ ├─ Polling? → Radio stays active
|
|
│ │ └─ Fix: Push notifications
|
|
│ │
|
|
│ └─ Large downloads in foreground? → Could wait for WiFi
|
|
│ └─ Fix: Use background URLSession with discretionary
|
|
│
|
|
└─ Check Low Data Mode handling
|
|
├─ Respecting allowsConstrainedNetworkAccess?
|
|
│ └─ Fix: Set to false for non-essential requests
|
|
│
|
|
└─ Checking ProcessInfo.processInfo.isLowDataModeEnabled?
|
|
└─ Fix: Reduce payload sizes, defer non-essential transfers
|
|
```
|
|
|
|
### Time-Cost Analysis
|
|
|
|
| Approach | Time | Outcome |
|
|
|----------|------|---------|
|
|
| Review URLSession configs | 15 min | Quick wins |
|
|
| Add discretionary flags | 30 min | Significant savings |
|
|
| Convert poll to push | 2-4 hours | Largest impact |
|
|
|
|
---
|
|
|
|
## Symptom 5: Energy Spike During Specific Action
|
|
|
|
Noticeable battery drain or heat when performing particular operation.
|
|
|
|
### Diagnosis Decision Tree
|
|
|
|
```
|
|
Energy spike during specific action?
|
|
│
|
|
├─ Step 1: Record Power Profiler during action
|
|
│ └─ Note which subsystem spikes (CPU/GPU/Network/Display)
|
|
│
|
|
├─ CPU spike?
|
|
│ │
|
|
│ ├─ Is it parsing data?
|
|
│ │ ├─ Same data parsed repeatedly?
|
|
│ │ │ └─ Fix: Cache parsed results (lazy var)
|
|
│ │ └─ Large JSON/XML payload?
|
|
│ │ └─ Fix: Paginate, stream parse, or use binary format
|
|
│ │
|
|
│ ├─ Is it creating views?
|
|
│ │ ├─ Many views at once?
|
|
│ │ │ └─ Fix: Use LazyVStack/LazyHStack
|
|
│ │ └─ Complex view hierarchies?
|
|
│ │ └─ Fix: Simplify, use drawingGroup()
|
|
│ │
|
|
│ └─ Is it image processing?
|
|
│ ├─ On main thread?
|
|
│ │ └─ Fix: Move to background queue
|
|
│ └─ No caching?
|
|
│ └─ Fix: Cache processed images
|
|
│
|
|
├─ GPU spike?
|
|
│ │
|
|
│ ├─ Starting animation?
|
|
│ │ └─ Fix: Ensure frame rate appropriate
|
|
│ │
|
|
│ ├─ Showing blur effect?
|
|
│ │ └─ Fix: Use solid color or pre-rendered blur
|
|
│ │
|
|
│ └─ Complex render? (shadows, masks, many layers)
|
|
│ └─ Fix: Simplify, use shouldRasterize, cache
|
|
│
|
|
├─ Network spike?
|
|
│ │
|
|
│ ├─ Large download started?
|
|
│ │ └─ Fix: Use background URLSession, show progress
|
|
│ │
|
|
│ ├─ Many parallel requests?
|
|
│ │ └─ Fix: Limit concurrency, batch
|
|
│ │
|
|
│ └─ Retrying failed requests?
|
|
│ └─ Fix: Exponential backoff, waitsForConnectivity
|
|
│
|
|
└─ Display spike?
|
|
└─ Unusual unless changing brightness programmatically
|
|
└─ Fix: Don't modify brightness, let system control
|
|
```
|
|
|
|
### Time-Cost Analysis
|
|
|
|
| Approach | Time | Outcome |
|
|
|----------|------|---------|
|
|
| Power Profiler during action | 5-10 min | Identifies subsystem |
|
|
| Time Profiler for CPU details | 10-15 min | Identifies function |
|
|
| Code review without profiling | 1+ hours | May miss actual cause |
|
|
|
|
---
|
|
|
|
## Quick Diagnostic Checklist
|
|
|
|
Use this when you need fast answers:
|
|
|
|
### 30-Second Check
|
|
- [ ] Device plugged in? (Power metrics show 0)
|
|
- [ ] Debug build? (Less optimized than release)
|
|
- [ ] Low Power Mode on? (May affect measurements)
|
|
|
|
### 5-Minute Check (Power Profiler)
|
|
- [ ] Which subsystem is dominant? (CPU/GPU/Network/Display)
|
|
- [ ] Sustained or spiky?
|
|
- [ ] Foreground or background?
|
|
|
|
### 15-Minute Investigation
|
|
- [ ] If CPU: Run Time Profiler to identify function
|
|
- [ ] If Network: Check request frequency and size
|
|
- [ ] If GPU: Check animation frame rates
|
|
- [ ] If Background: Check Info.plist modes
|
|
|
|
### Common Quick Fixes
|
|
|
|
| Finding | Quick Fix | Time |
|
|
|---------|-----------|------|
|
|
| Timer without tolerance | Add `.tolerance = 0.1` | 1 min |
|
|
| VStack with large ForEach | Change to LazyVStack | 1 min |
|
|
| allowsExpensiveNetworkAccess = true | Set to false | 1 min |
|
|
| Missing stopUpdatingLocation | Add stop call | 2 min |
|
|
| No Dark Mode | Add asset variants | 30 min |
|
|
| Audio session always active | Add setActive(false) | 5 min |
|
|
|
|
---
|
|
|
|
## When to Escalate
|
|
|
|
### Use `axiom-energy` skill when
|
|
- Need full audit checklist
|
|
- Want comprehensive patterns with code
|
|
- Planning proactive optimization
|
|
|
|
### Use `axiom-energy-ref` skill when
|
|
- Need specific API details
|
|
- Want complete code examples
|
|
- Implementing from scratch
|
|
|
|
### Use `energy-auditor` agent when
|
|
- Want automated codebase scan
|
|
- Looking for anti-patterns at scale
|
|
- Pre-release energy audit
|
|
|
|
Run: `/axiom:audit energy`
|
|
|
|
---
|
|
|
|
**Last Updated**: 2025-12-26
|
|
**Platforms**: iOS 26+, iPadOS 26+
|