Date: December 3, 2025 Authors: Jordan Koch
Current Flow (6 Phases):
- Bonjour/mDNS Discovery (0-25%): 10 seconds fixed duration
- Import Bonjour Devices (25-40%): Variable
- Port Scanning (40-60%): Sequential, ~2-5 seconds per device
- dns-sd Direct Lookup (60-75%): ~5 seconds
- Combine Results (75-85%): ~2 seconds
- Final Classification (85-100%): ~1-2 seconds
Total Time: 25-60 seconds depending on network size
Current Flow (4 Phases):
- Ping Subnet (0-20%): ~10-30 seconds for 254 IPs
- MAC Address Collection (20-30%): ~5-10 seconds
- Bonjour Discovery (30-40%): 10 seconds fixed
- Port Scanning (40-100%): Sequential, ~2-5 seconds per device
Total Time: 35-70 seconds for typical network
###1 Fixed 10-Second Bonjour Wait
Location: BonjourScanner.swift:181-186
for i in 1...10 {
try? await Task.sleep(nanoseconds: 1_000_000_000) // 1 second
// ... progress updates
}Impact: Always waits 10 full seconds even if all devices discovered in 2 seconds Optimization Opportunity: HIGH
Location: IntegratedDashboardViewV3.swift:1096-1110
for (index, host) in sortedHosts.enumerated() {
let openPorts = await portScanner.scanPorts(host: host, ports: portsToScan)
// Sequential - each host must complete before next starts
}Impact: With 20 devices × 3 seconds each = 60 seconds Optimization Opportunity: CRITICAL
Impact: Both HomeKit tab and Dashboard run full Bonjour scans separately Optimization Opportunity: MEDIUM
Impact: Scanning 100+ ports per device when HomeKit only uses ~5 ports Optimization Opportunity: HIGH
Location: AdvancedPortScanner.swift:129
try process.run()
process.waitUntilExit() // Blocks until completeImpact: Synchronous blocking prevents parallelization Optimization Opportunity: HIGH
Time Savings: 50-70%
Current:
for host in hosts {
await portScanner.scanPorts(host, ports) // Sequential: 3s each
}
// Total for 20 hosts: 60 secondsOptimized:
await withTaskGroup(of: (String, [Int]).self) { group in
for host in hosts {
group.addTask {
let ports = await self.portScanner.scanPorts(host, self.portsToScan)
return (host, ports)
}
}
for await (host, ports) in group {
// Process results as they complete
updateDevice(host, ports)
}
}
// Total for 20 hosts: ~5-8 seconds (parallel)Implementation:
- Modify
scanPortsOnDevices()inIntegratedDashboardViewV3.swift(line 1192) - Add concurrency limit (e.g., 10 concurrent scans max to avoid overwhelming network)
- Update progress based on completed scans vs total
Time Savings: 40-60%
Current:
- Always waits 10 seconds
- Discovery might complete in 2-3 seconds
Optimized:
// Early termination when discovery stabilizes
var discoveredCount = 0
var stableCount = 0
let maxWait = 10
let earlyExitThreshold = 3 // Exit if no new devices for 3 seconds
for i in 1...maxWait {
try? await Task.sleep(nanoseconds: 1_000_000_000)
let currentCount = discoveredDevices.count
if currentCount == discoveredCount {
stableCount += 1
if stableCount >= earlyExitThreshold {
print("🔍 Bonjour: Early exit - no new devices for \(earlyExitThreshold)s")
break
}
} else {
discoveredCount = currentCount
stableCount = 0
}
}Benefits:
- Typical completion: 3-5 seconds instead of 10
- Still captures all devices (waits for stability)
- Falls back to 10s if devices keep appearing
Time Savings: 30-50% for HomeKit scans
Current:
- Scans 100+ common ports per device
- Most irrelevant for HomeKit
Optimized:
// HomeKit-specific ports
let homeKitPorts = [
80, // HTTP (HAP)
443, // HTTPS (secure HAP)
5353, // mDNS
8080, // Alternate HTTP
8443, // Alternate HTTPS
62078 // HAP (HomeKit Accessory Protocol)
]
// Use focused port list for HomeKit scans
if scanType == .homeKit {
portsToScan = homeKitPorts
} else {
portsToScan = commonPorts // Full list for general scans
}Implementation:
- Add
ScanTypeenum to distinguish HomeKit vs general scans - Use optimized port list in
HomeKitTabView.scanForHomeKitDevices() - Keep full port list for dashboard scans
Time Savings: 10-15 seconds on repeat scans
Strategy:
class BonjourCache {
static let shared = BonjourCache()
private var cache: [String: BonjourDeviceMetadata] = [:]
private var cacheTime: Date?
private let cacheValidDuration: TimeInterval = 300 // 5 minutes
func getCachedResults() -> [String: BonjourDeviceMetadata]? {
guard let time = cacheTime,
Date().timeIntervalSince(time) < cacheValidDuration else {
return nil
}
return cache
}
func updateCache(_ results: [String: BonjourDeviceMetadata]) {
cache = results
cacheTime = Date()
}
}Benefits:
- Repeated scans within 5 minutes use cached data
- Refresh button forces new scan
- Automatic expiration ensures freshness
Time Savings: 20-40% for large subnets
Current:
pingSubnet()likely sequential or limited parallelism
Optimized:
func pingSubnet(_ subnet: String) async -> Set<String> {
return await withTaskGroup(of: String?.self) { group in
var aliveHosts: Set<String> = []
// Ping in batches of 50 to avoid overwhelming
for i in 1...254 {
group.addTask {
let host = "\(subnet).\(i)"
return await self.ping(host) ? host : nil
}
// Process results as they complete
if i % 50 == 0 || i == 254 {
for await result in group {
if let host = result {
aliveHosts.insert(host)
}
}
}
}
return aliveHosts
}
}- ✅ Parallel port scanning with concurrency limit
- ✅ Smart Bonjour early termination
- ✅ HomeKit-specific port list
- Bonjour result caching
- Concurrent ping scanning
- Progressive result display (show devices as discovered)
- Background refresh (update without full re-scan)
- Incremental scanning (only scan new IPs)
- Before: 25-60 seconds
- After: 8-15 seconds
- Improvement: 70-80% faster
- Before: 35-70 seconds
- After: 12-20 seconds
- Improvement: 65-75% faster
- ✅ Verify all devices still discovered (no false negatives)
- ✅ Test on networks with 5, 10, 20, 50 devices
- ✅ Test with various HomeKit device types
- ✅ Verify timeout handling still works
- ✅ Measure actual scan times before/after
- ✅ Monitor CPU and network usage
- ✅ Test with slow-responding devices
- ✅ Verify UI remains responsive
- ✅ Empty network (no devices)
- ✅ Large network (100+ devices)
- ✅ Mixed device types (HomeKit, non-HomeKit)
- ✅ Devices joining/leaving during scan
Pros:
- Dramatically faster
- Better resource utilization
Cons:
- Higher network load during scan
- May trigger IDS/IPS on enterprise networks
- Need concurrency limits
Mitigation:
- Limit to 10-15 concurrent scans
- Add option for "gentle mode" (sequential) for sensitive networks
- Respect rate limiting
Pros:
- Faster when few devices
- Still accurate
Cons:
- Might miss slow-responding devices
- Need tuning of stability threshold
Mitigation:
- Configurable threshold (2-5 seconds)
- Always respect minimum wait time (e.g., 3 seconds)
- Log early exits for debugging
Pros:
- Much faster for HomeKit scans
- Less network noise
Cons:
- Might miss non-standard ports
- Need different lists for different scan types
Mitigation:
- Keep full port list option
- Document port choices
- Allow custom port lists in settings
- BonjourScanner.swift:181-186 - Add early termination
- IntegratedDashboardViewV3.swift:1096-1163 - Parallel port scanning
- HomeKitTabView.swift:180 - Add HomeKit-specific ports
- IntegratedDashboardViewV3.swift:1192-1310 - Parallel port scanning
- PingScanner.swift - Add concurrent ping scanning
- Create BonjourCache.swift - New file for caching
- Parallel scanning is more "noisy" - may be detected as attack
- Add user-configurable "scan intensity" settings:
- Gentle: Sequential, slower (current behavior)
- Normal: Moderate parallelism (5 concurrent)
- Aggressive: High parallelism (15 concurrent)
- Implement exponential backoff for failed connections
- Respect network congestion signals
- Add delays between scan phases if network errors detected
- Document that aggressive scanning may trigger security alerts
- Add disclaimer about network scanning policies
- Respect Do Not Scan lists if implemented
- Update user guide with performance expectations
- Document scan intensity settings
- Add troubleshooting for slow scans
- Explain early termination logic
- Document HomeKit port list rationale
Next Steps:
- Implement Priority 1-3 optimizations
- Test thoroughly on various network sizes
- Measure and document performance improvements
- Deploy optimized version as v8.4.0
Authors: Jordan Koch