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
5-Minute Check (Power Profiler)
15-Minute Investigation
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+