This guide provides actionable performance optimizations for the Cloudflare Network Diagnostic Tool. Implementing these recommendations will reduce diagnostic runtime from ~70ms to ~25ms (3x faster) and eliminate UI blocking during exports.
Key Areas:
- π DNS Benchmarking Parallelization
- π€ Background Thread Exports
- π Batched Logging Operations
- π― Health Score Caching
- π§Ή Efficient Log Cleanup
| Layer | Current Issue | Optimization | Expected Gain |
|---|---|---|---|
| Network Layer | Sequential DNS requests | Parallel async/await | 67ms β 22ms (3x) |
| Trace Layer | No caching | Memoization | -30% redundancy |
| Benchmark Layer | Blocking on main thread | Background dispatch | Non-blocking |
| Health Layer | Full recalculation | Component caching | 10x faster |
| Export Layer | UI blocking (500ms) | Background thread | 0ms blocking |
| Logging Layer | 33% Base64 overhead | Batch encoding | -33% overhead |
Problem: DNS queries run sequentially (67ms total instead of 22ms)
Current Pattern (β SLOW):
// Each DNS lookup blocks until complete
let cf = measureDNS(.cloudflare) // ~12ms
let google = measureDNS(.google) // ~18ms
let quad9 = measureDNS(.quad9) // ~15ms
let nextdns = measureDNS(.nextdns) // ~22ms
// Total: ~67ms β οΈOptimized Pattern (β FAST):
// Run all DNS tests concurrently
async let cf = measureDNS(.cloudflare)
async let google = measureDNS(.google)
async let quad9 = measureDNS(.quad9)
async let nextdns = measureDNS(.nextdns)
let results = await (cf, google, quad9, nextdns)
// Total: ~22ms (longest individual test) β
Implementation:
- See:
reference/NetworkLayer-Optimized.swift - Use: Swift 5.5+
async/awaitwith structured concurrency - Test: Xcode Instruments β Time Profiler
- Expected: 3x speedup (67ms β 22ms)
Checklist:
- Identify current sequential DNS implementation
- Convert to
async/awaitpattern - Test with Xcode Instruments
- Verify 3x improvement
- Run performance regression tests
Problem: Default 60s timeout causes hangs on slow networks
Current Pattern (β PROBLEMATIC):
let session = URLSession.shared // Default: 60s timeout β οΈOptimized Pattern (β RECOMMENDED):
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 5.0 // Individual request
config.timeoutIntervalForResource = 30.0 // Total resource
config.httpMaximumConnectionsPerHost = 6 // Connection pooling
config.waitsForConnectivity = false // Fail fast
let session = URLSession(configuration: config)Implementation:
- See:
reference/NetworkLayer-Optimized.swift(lines 18-26) - Use: URLSessionConfiguration for all network requests
- Test: Simulate slow network (Xcode throttling)
- Expected: Prevents hangs, fails gracefully
Checklist:
- Create optimized URLSessionConfiguration
- Apply to all URLSession instances
- Test on throttled network (slow 3G)
- Verify timeout behavior
- Document in troubleshooting
Problem: JSON encoding/pretty-printing blocks UI for 100-500ms
Current Pattern (β BLOCKS UI):
// All on main thread - blocks UI
let jsonData = try JSONSerialization.data(
withJSONObject: diagnostics,
options: .prettyPrinted
)
write(jsonData) // I/O also blocks β οΈOptimized Pattern (β NON-BLOCKING):
// Move to background thread
DispatchQueue.global(qos: .userInitiated).async {
let jsonData = try JSONSerialization.data(
withJSONObject: diagnostics,
options: .prettyPrinted
)
write(jsonData)
// Deliver result on main thread
DispatchQueue.main.async {
completion(jsonData)
}
}Best Pattern (β MODERN):
// Use async/await (Swift 5.5+)
let result = try await withCheckedThrowingContinuation { continuation in
DispatchQueue.global(qos: .userInitiated).async {
do {
let jsonData = try JSONSerialization.data(
withJSONObject: diagnostics,
options: .prettyPrinted
)
continuation.resume(returning: jsonData)
} catch {
continuation.resume(throwing: error)
}
}
}Implementation:
- See:
reference/ExportLayer-Optimized.swift - Use: DispatchQueue or async/await
- Test: Core Animation profiler (check 60 FPS)
- Expected: Zero UI blocking
Checklist:
- Audit current export implementation
- Move encoding to background thread
- Test with large datasets (1000+ items)
- Verify 60 FPS maintained
- Test all export formats
Problem: Every log write triggers encoding, causing 33% overhead + blocking
Current Pattern (β SLOW & BLOCKING):
# Encodes and writes each entry synchronously
for log_entry in diagnostics:
encoded = base64.b64encode(log_entry) # 33% overhead β οΈ
log_file.write(encoded) # I/O blocking β οΈOptimized Pattern (β BATCHED):
# Batch in memory, encode on background thread
log_buffer = []
def write_log(entry):
log_buffer.append(entry)
if len(log_buffer) >= BATCH_SIZE: # Flush every 100 entries
batch = log_buffer.copy()
log_buffer.clear()
executor.submit(flush_batch, batch) # Background thread
def flush_batch(batch):
batch_str = '\\n'.join(batch)
encoded = base64.b64encode(batch_str) # Batch encode
with open(log_file, 'a') as f:
f.write(encoded) # Single I/O operationAlternative (β EVEN BETTER):
# Use compression instead of Base64
# - 40-60% smaller files
# - Better performance
# - More secure
with gzip.open(log_file, 'at') as f:
f.write(json.dumps(entry))Implementation:
- See:
reference/LoggingLayer-Optimized.py - Use: Batching or compression
- Test: Measure I/O performance
- Expected: -33% overhead or compression alternative
Checklist:
- Audit current logging implementation
- Implement batching with 100-entry batch size
- Move encoding to background thread
- Measure I/O improvements
- Consider compression alternative
Problem: Recalculates full score from scratch every time
Current Pattern (β REDUNDANT):
// Every call recalculates everything
let score = calculateHealthScore(dns, doh, trace, warp)
// Even if inputs haven't changed β οΈOptimized Pattern (β CACHED):
// Check cache first
if let cached = cachedScore,
Date().timeIntervalSince(cacheTime) < 300 { // 5-min TTL
return cached // Instant return β
}
// Calculate and cache
let score = _calculateScore(...)
cachedScore = score
cacheTime = Date()
return scoreAdvanced Pattern (β MEMOIZED COMPONENTS):
// Cache individual component scores
var dnsScoreCache: [String: Double] = [:]
var dohScoreCache: [String: Double] = [:]
var locationScoreCache: [String: Double] = [:]
// Return immediately if in cache
if let cached = dnsScoreCache[key] {
return cached
}
// Calculate and cache
let score = _calculateDNSScore(...)
dnsScoreCache[key] = score
return scoreImplementation:
- See:
reference/HealthScoring-Optimized.swift - Use: TTL-based cache (300s) + component memoization
- Test: Measure repeated diagnostics
- Expected: 10x faster on repeated calls
Checklist:
- Identify all score calculations
- Add TTL-based cache
- Implement component memoization
- Test with repeated diagnostics
- Add cache statistics
Problem: Scanning all logs sequentially for deletion can stall app
Current Pattern (β SLOW):
// Checks modification date of every single file
for file in allLogFiles {
let modDate = file.modificationDate // I/O call per file β οΈ
if modDate < cutoffDate {
delete(file)
}
}Optimized Pattern (β DATE-BASED BATCH):
// Extract date from filename (no I/O needed)
let cutoffDate = Date(timeIntervalSinceNow: -30*24*3600)
let cutoffString = ISO8601DateFormatter().string(from: cutoffDate)
for file in logFiles {
// Format: diagnostic_YYYY-MM-DDTHH:MM:SS.cflog
let fileDate = filename.dropFirst(11).prefix(10) // YYYY-MM-DD
if fileDate < cutoffString {
markForDeletion(file)
}
}
// Delete in batches on background thread
deleteInBatches(markedFiles, batchSize: 50)Advanced Pattern (β ASYNC PERIODIC CLEANUP):
func schedulePeriodicCleanup(interval: TimeInterval = 24*3600) {
Task {
while true {
try? await Task.sleep(nanoseconds: UInt64(interval * 1e9))
await cleanupLogsAsync() // Non-blocking
}
}
}Implementation:
- See:
reference/LogCleanup-Optimized.swift - Use: Date-based filtering + batch deletion
- Test: 1000+ log files
- Expected: 10x faster cleanup
Checklist:
- Audit current cleanup implementation
- Extract date from filename instead of stat calls
- Implement batch deletion
- Add async periodic cleanup scheduling
- Test with large log directories
| Metric | Before | After | Target | Status |
|---|---|---|---|---|
| DNS Benchmarking | ~67ms | ~22ms | 3x | π― |
| Export Blocking | ~500ms | 0ms | Non-blocking | π― |
| Log I/O Overhead | +33% | 0% | Optimized | π― |
| Health Score Calc | ~50ms | <5ms | 10x | π― |
| Log Cleanup (1000 files) | ~5000ms | ~500ms | 10x | π― |
| Overall Diagnostic | ~70ms | ~25ms | 3x | π― |
1. Time Profiler (Measure CPU time)
- β Verify DNS parallelization reduces time by 3x
- β Check health score calculation improvements
- Target: < 25ms total diagnostic time
2. Core Animation (Detect UI blocking)
- β Verify exports don't block UI
- β Check export maintains 60 FPS
- Target: 60 FPS maintained during exports
3. System Trace (Thread scheduling)
- β Verify main thread not blocked
- β Check background threads active
- Target: Main thread idle during heavy work
4. Memory Graph (Detect leaks)
- β Check async operations don't leak
- β Verify cache size bounded
- Target: Stable memory usage
5. File Activity (I/O patterns)
- β Verify batched logging works
- β Check fewer I/O operations
- Target: Fewer I/O calls than before
Unit Tests:
- Parallel DNS benchmark correctness
- Export format encoding accuracy
- Health score consistency
- Cache invalidation logic
- Log cleanup date filtering
Integration Tests:
- Full diagnostic pipeline
- All export formats
- Concurrent diagnostics
- Error handling & fallbacks
- Memory leak detection
Device Testing:
- iPhone 12 (A14 Bionic)
- iPhone 14 (A15 Bionic)
- iPhone 15 (A17 Pro)
- iPad (various models)
- macOS (Intel & Apple Silicon)
Monday-Tuesday: Parallel DNS Benchmarking
Wednesday: URLSession Timeout Config
Thursday-Friday: Testing & Validation
Target: 3x diagnostic speedup
Monday-Tuesday: Background Thread Exports
Wednesday: Batched Base64 Logging
Thursday: Testing & Validation
Friday: Documentation
Target: Zero UI blocking
Monday-Tuesday: Health Score Caching
Wednesday: Log Cleanup Optimization
Thursday: Performance Validation
Friday: Final Documentation
Target: All optimizations complete
| File | Purpose | Language |
|---|---|---|
NetworkLayer-Optimized.swift |
Parallel DNS & timeouts | Swift |
ExportLayer-Optimized.swift |
Background exports | Swift |
LoggingLayer-Optimized.py |
Batched encoding | Python |
HealthScoring-Optimized.swift |
Score caching | Swift |
LogCleanup-Optimized.swift |
Efficient cleanup | Swift |
All files include:
- β Before/after comparison patterns
- β Detailed implementation examples
- β Usage examples and integration guide
- β Performance testing strategy
- Apple Swift Concurrency: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/
- Xcode Instruments Guide: https://developer.apple.com/instruments/
- URLSession Best Practices: https://developer.apple.com/documentation/foundation/urlsession
- Performance Optimization WWDC: https://developer.apple.com/videos/play/wwdc2020/10205/
Follow these guidelines when contributing performance improvements:
- Measure First β Use Xcode Instruments to baseline
- Implement β Use reference implementations as guide
- Test β Verify improvement with benchmarks
- Document β Update this guide with metrics
- PR Review β Include performance data
- Performance Issues: GitHub Issues
- Discussion: GitHub Discussions
- Branch: performance-optimization
Cloudflare Network Diagnostic Tool β Fast. Private. Optimized.
Made with β€οΈ for performance | v1.0 Performance Guide | Last updated: June 2026