Skip to content

Performance Monitoring API

WeaveDI provides comprehensive, enterprise-grade performance monitoring tools designed to help you optimize dependency injection performance, identify bottlenecks, and maintain optimal application performance in production environments. This sophisticated monitoring system offers real-time metrics, historical analysis, and automated alerting capabilities.

Overview

The performance monitoring system implements advanced instrumentation to track dependency resolution times, memory usage patterns, registration efficiency, and container performance characteristics. This comprehensive monitoring provides actionable insights for performance optimization, capacity planning, and proactive issue detection.

Key Monitoring Capabilities:

  • Real-time Metrics: Live performance data collection and analysis
  • Historical Tracking: Long-term performance trend analysis
  • Memory Profiling: Detailed memory usage patterns and leak detection
  • Bottleneck Identification: Automatic identification of performance bottlenecks
  • Custom Metrics: Extensible framework for application-specific metrics

Performance Benefits:

  • Proactive Optimization: Identify issues before they impact users
  • Capacity Planning: Data-driven insights for infrastructure scaling
  • Regression Detection: Automatic detection of performance regressions
  • Resource Optimization: Optimize memory and CPU usage patterns
swift
import WeaveDI

// Enable performance monitoring
PerformanceMonitor.shared.enable()

// Monitor specific operations
let metrics = await PerformanceMonitor.shared.measureResolution {
    let service = WeaveDI.Container.shared.resolve(ExpensiveService.self)
    return service
}

print("Resolution took \(metrics.duration)ms")
print("Memory used: \(metrics.memoryDelta) bytes")

Core Monitoring Features

Resolution Performance Tracking

Purpose: Comprehensive tracking of dependency resolution performance to identify slow dependencies and optimize resolution patterns.

Tracking Capabilities:

  • Resolution Time Measurement: Precise timing of individual dependency resolutions
  • Aggregate Statistics: Average, median, and percentile resolution times
  • Performance Trending: Historical performance trends and regression detection
  • Dependency Hotspots: Identification of frequently resolved dependencies

Metrics Collected:

  • Individual Resolution Times: Per-dependency resolution timing
  • Aggregate Performance: Overall container performance statistics
  • Cache Hit/Miss Ratios: Effectiveness of dependency caching
  • Memory Allocation Patterns: Memory usage during resolution operations

Performance Optimization Insights:

  • Slow Dependencies: Identify dependencies with high resolution times
  • Cache Effectiveness: Measure cache performance and optimization opportunities
  • Resolution Patterns: Analyze resolution patterns for optimization
  • Resource Usage: Monitor resource consumption during resolution
swift
// Automatic resolution timing
class PerformanceAwareService {
    @Inject var userService: UserService?
    @Inject var dataService: DataService?

    func performOperation() async {
        // Monitor will automatically track these resolutions
        userService?.loadUser()
        dataService?.processData()

        // Get performance report
        let report = PerformanceMonitor.shared.getResolutionReport()
        print("Recent resolutions: \(report.recentResolutions)")
        print("Average resolution time: \(report.averageResolutionTime)ms")
    }
}

Memory Usage Monitoring

Purpose: Advanced memory profiling and monitoring to detect memory leaks, optimize memory usage, and ensure efficient resource utilization.

Memory Monitoring Features:

  • Real-time Memory Tracking: Continuous monitoring of memory usage patterns
  • Leak Detection: Automatic detection of potential memory leaks
  • Allocation Profiling: Detailed analysis of memory allocation patterns
  • Growth Rate Analysis: Monitoring memory growth rates and trends

Memory Metrics:

  • Current Usage: Real-time memory consumption
  • Peak Usage: Maximum memory usage during operations
  • Growth Rate: Rate of memory usage increase over time
  • Allocation Patterns: Detailed breakdown of memory allocations

Optimization Opportunities:

  • Memory Hotspots: Identify components consuming excessive memory
  • Optimization Targets: Prioritize optimization efforts based on memory impact
  • Resource Planning: Data for capacity planning and resource allocation
  • Performance Correlation: Correlate memory usage with performance metrics
swift
// Monitor memory consumption
class MemoryAwareBootstrap {
    static func setupWithMonitoring() async {
        let initialMemory = PerformanceMonitor.shared.getCurrentMemoryUsage()

        await WeaveDI.Container.bootstrap { container in
            // Register many services
            for i in 0..<1000 {
                container.register(TestService.self, name: "service_\(i)") {
                    TestServiceImpl(id: i)
                }
            }
        }

        let finalMemory = PerformanceMonitor.shared.getCurrentMemoryUsage()
        let memoryIncrease = finalMemory - initialMemory

        print("DI setup memory usage: \(memoryIncrease) bytes")
        print("Memory per service: \(memoryIncrease / 1000) bytes")
    }
}

Real-World Monitoring Examples

CountApp Performance Monitoring

swift
/// Performance-monitored counter with metrics collection
@MainActor
class MonitoredCounterViewModel: ObservableObject {
    @Published var count = 0
    @Published var performanceMetrics: PerformanceMetrics?

    @Inject var repository: CounterRepository?
    @Inject var logger: LoggerProtocol?

    func increment() async {
        let metrics = await PerformanceMonitor.shared.measureOperation("counter_increment") {
            // Measure the complete increment operation
            let startTime = CFAbsoluteTimeGetCurrent()

            count += 1
            await repository?.saveCount(count)

            let endTime = CFAbsoluteTimeGetCurrent()
            logger?.info("⏱️ Increment operation took \(String(format: "%.2f", (endTime - startTime) * 1000))ms")
        }

        // Update UI with performance data
        performanceMetrics = metrics

        // Log performance data
        logger?.info("📊 Performance: Resolution=\(metrics.resolutionTime)ms, Total=\(metrics.totalTime)ms")
    }

    func getPerformanceReport() -> String {
        let report = PerformanceMonitor.shared.getDetailedReport()
        return """
        📈 Counter Performance Report:
        - Total operations: \(report.operationCount)
        - Average resolution time: \(String(format: "%.2f", report.averageResolutionTime))ms
        - Peak memory usage: \(report.peakMemoryUsage) bytes
        - Cache hit rate: \(String(format: "%.1f", report.cacheHitRate * 100))%
        """
    }
}

/// Enhanced counter repository with performance tracking
class PerformanceTrackedCounterRepository: CounterRepository {
    @Inject var logger: LoggerProtocol?

    func getCurrentCount() async -> Int {
        return await PerformanceMonitor.shared.measureOperation("get_current_count") {
            let count = UserDefaults.standard.integer(forKey: "saved_count")
            logger?.debug("📊 Retrieved count: \(count)")
            return count
        }
    }

    func saveCount(_ count: Int) async {
        await PerformanceMonitor.shared.measureOperation("save_count") {
            UserDefaults.standard.set(count, forKey: "saved_count")
            logger?.debug("💾 Saved count: \(count)")
        }
    }

    func getCountHistory() async -> [CounterHistoryItem] {
        return await PerformanceMonitor.shared.measureOperation("get_count_history") {
            guard let data = UserDefaults.standard.data(forKey: "count_history"),
                  let history = try? JSONDecoder().decode([CounterHistoryItem].self, from: data) else {
                return []
            }
            logger?.debug("📜 Retrieved \(history.count) history items")
            return history
        }
    }

    func resetCount() async {
        await PerformanceMonitor.shared.measureOperation("reset_count") {
            UserDefaults.standard.set(0, forKey: "saved_count")
            logger?.debug("🔄 Count reset")
        }
    }
}

WeatherApp Performance Monitoring

swift
/// Weather service with comprehensive performance monitoring
class MonitoredWeatherService: WeatherServiceProtocol {
    @Inject var httpClient: HTTPClientProtocol?
    @Inject var cacheService: CacheServiceProtocol?
    @Inject var logger: LoggerProtocol?

    func fetchCurrentWeather(for city: String) async throws -> Weather {
        return try await PerformanceMonitor.shared.measureAsyncOperation("fetch_weather_\(city)") {
            let startTime = CFAbsoluteTimeGetCurrent()

            // Check cache first
            let cacheMetrics = await PerformanceMonitor.shared.measureOperation("cache_lookup") {
                return await cacheService?.retrieve(forKey: "weather_\(city)")
            }

            if let cachedWeather: Weather = cacheMetrics.result {
                let cacheTime = CFAbsoluteTimeGetCurrent() - startTime
                logger?.info("⚡ Cache hit for \(city) in \(String(format: "%.2f", cacheTime * 1000))ms")
                return cachedWeather
            }

            // Network fetch
            let networkMetrics = await PerformanceMonitor.shared.measureAsyncOperation("network_fetch") {
                guard let client = httpClient else {
                    throw WeatherError.httpClientNotAvailable
                }

                let url = buildWeatherURL(for: city)
                let data = try await client.fetchData(from: url)
                return try JSONDecoder().decode(Weather.self, from: data)
            }

            let weather: Weather = networkMetrics.result

            // Cache the result
            await PerformanceMonitor.shared.measureOperation("cache_store") {
                try? await cacheService?.store(weather, forKey: "weather_\(city)")
            }

            let totalTime = CFAbsoluteTimeGetCurrent() - startTime
            logger?.info("🌤️ Weather fetch for \(city) completed in \(String(format: "%.2f", totalTime * 1000))ms")

            return weather
        }
    }

    private func buildWeatherURL(for city: String) -> URL {
        return URL(string: "https://api.openweathermap.org/data/2.5/weather?q=\(city)&appid=test&units=metric")!
    }
}

/// Performance dashboard for weather app
class WeatherPerformanceDashboard {
    @Inject var logger: LoggerProtocol?

    func generateReport() -> WeatherPerformanceReport {
        let monitor = PerformanceMonitor.shared
        let report = monitor.getDetailedReport()

        let weatherOperations = report.operations.filter { $0.name.contains("weather") }
        let cacheOperations = report.operations.filter { $0.name.contains("cache") }
        let networkOperations = report.operations.filter { $0.name.contains("network") }

        return WeatherPerformanceReport(
            totalWeatherRequests: weatherOperations.count,
            averageWeatherFetchTime: weatherOperations.map(\.duration).average(),
            cacheHitRate: calculateCacheHitRate(cacheOperations),
            networkLatency: networkOperations.map(\.duration).average(),
            memoryUsage: report.currentMemoryUsage,
            recommendations: generateRecommendations(report)
        )
    }

    private func calculateCacheHitRate(_ operations: [OperationMetric]) -> Double {
        let cacheHits = operations.filter { $0.metadata["cache_hit"] as? Bool == true }.count
        return operations.isEmpty ? 0.0 : Double(cacheHits) / Double(operations.count)
    }

    private func generateRecommendations(_ report: PerformanceReport) -> [String] {
        var recommendations: [String] = []

        if report.averageResolutionTime > 10.0 {
            recommendations.append("Consider optimizing dependency resolution - average time is high")
        }

        if report.memoryGrowthRate > 1024 * 1024 { // 1MB/hour
            recommendations.append("Memory usage is growing rapidly - check for memory leaks")
        }

        let cacheHitRate = calculateCacheHitRate(report.operations.filter { $0.name.contains("cache") })
        if cacheHitRate < 0.7 {
            recommendations.append("Cache hit rate is low (\(String(format: "%.1f", cacheHitRate * 100))%) - consider cache strategy optimization")
        }

        return recommendations
    }
}

struct WeatherPerformanceReport {
    let totalWeatherRequests: Int
    let averageWeatherFetchTime: Double
    let cacheHitRate: Double
    let networkLatency: Double
    let memoryUsage: Int64
    let recommendations: [String]

    var formattedReport: String {
        return """
        🌤️ Weather App Performance Report
        ================================
        📊 Total weather requests: \(totalWeatherRequests)
        ⏱️ Average fetch time: \(String(format: "%.2f", averageWeatherFetchTime))ms
        📱 Cache hit rate: \(String(format: "%.1f", cacheHitRate * 100))%
        🌐 Network latency: \(String(format: "%.2f", networkLatency))ms
        💾 Memory usage: \(memoryUsage / 1024 / 1024)MB

        💡 Recommendations:
        \(recommendations.map { "• \($0)" }.joined(separator: "\n"))
        """
    }
}

Advanced Monitoring Features

Custom Metrics Collection

Purpose: Extensible framework for collecting application-specific performance metrics beyond standard dependency injection metrics.

Custom Metrics Benefits:

  • Application-Specific Insights: Monitor metrics specific to your application domain
  • Business Logic Performance: Track performance of critical business operations
  • Integration Points: Monitor performance of external service integrations
  • User Experience Metrics: Correlate technical metrics with user experience

Metrics Framework Features:

  • Type-Safe Metrics: Strongly typed metric definitions prevent errors
  • Aggregate Functions: Built-in support for averages, percentiles, and trends
  • Historical Storage: Long-term storage of custom metrics for trend analysis
  • Real-time Analysis: Real-time processing and analysis of custom metrics

Implementation Patterns:

  • Domain-Specific Metrics: Metrics tailored to specific business domains
  • Performance Benchmarks: Custom benchmarks for performance validation
  • Integration Monitoring: Monitor performance of external integrations
  • User Journey Tracking: Track performance across user interaction flows
swift
// Define custom metrics
enum CustomMetric: String, CaseIterable {
    case userLoginTime = "user_login"
    case dataProcessingTime = "data_processing"
    case cacheOperationTime = "cache_operation"
    case databaseQueryTime = "database_query"
}

class CustomMetricsCollector {
    private var metrics: [CustomMetric: [Double]] = [:]

    func recordMetric(_ metric: CustomMetric, value: Double) {
        metrics[metric, default: []].append(value)
        PerformanceMonitor.shared.recordCustomMetric(metric.rawValue, value: value)
    }

    func getAverageTime(for metric: CustomMetric) -> Double {
        guard let values = metrics[metric], !values.isEmpty else { return 0.0 }
        return values.reduce(0, +) / Double(values.count)
    }

    func getPercentile(_ percentile: Double, for metric: CustomMetric) -> Double {
        guard let values = metrics[metric]?.sorted(), !values.isEmpty else { return 0.0 }
        let index = Int(Double(values.count - 1) * percentile / 100.0)
        return values[index]
    }
}

Performance Alerts System

Purpose: Proactive alerting system that automatically detects performance issues and notifies stakeholders before problems impact users.

Alert System Features:

  • Threshold-Based Alerts: Configurable thresholds for various performance metrics
  • Trend-Based Detection: Detect performance degradation trends
  • Multi-Channel Notifications: Support for various notification channels
  • Alert Prioritization: Prioritize alerts based on severity and impact

Alert Types:

  • Performance Degradation: Detect when performance drops below acceptable levels
  • Resource Exhaustion: Alert on memory or CPU resource exhaustion
  • Anomaly Detection: Identify unusual patterns in performance metrics
  • Threshold Breaches: Alert when metrics exceed configured thresholds

Integration Capabilities:

  • External Monitoring Systems: Integration with external monitoring platforms
  • Incident Management: Integration with incident management systems
  • Team Notifications: Configurable notifications for different teams
  • Escalation Policies: Automatic escalation for critical performance issues
swift
protocol PerformanceAlert {
    var threshold: Double { get }
    var message: String { get }
    func shouldTrigger(for metrics: PerformanceReport) -> Bool
}

struct HighResolutionTimeAlert: PerformanceAlert {
    let threshold: Double = 50.0 // ms
    let message = "Dependency resolution time is above 50ms"

    func shouldTrigger(for metrics: PerformanceReport) -> Bool {
        return metrics.averageResolutionTime > threshold
    }
}

struct HighMemoryUsageAlert: PerformanceAlert {
    let threshold: Double = 100 * 1024 * 1024 // 100MB
    let message = "Memory usage is above 100MB"

    func shouldTrigger(for metrics: PerformanceReport) -> Bool {
        return Double(metrics.currentMemoryUsage) > threshold
    }
}

struct LowCacheHitRateAlert: PerformanceAlert {
    let threshold: Double = 0.5 // 50%
    let message = "Cache hit rate is below 50%"

    func shouldTrigger(for metrics: PerformanceReport) -> Bool {
        let cacheOps = metrics.operations.filter { $0.name.contains("cache") }
        let hits = cacheOps.filter { $0.metadata["hit"] as? Bool == true }.count
        let rate = cacheOps.isEmpty ? 1.0 : Double(hits) / Double(cacheOps.count)
        return rate < threshold
    }
}

class PerformanceAlertManager {
    private let alerts: [PerformanceAlert] = [
        HighResolutionTimeAlert(),
        HighMemoryUsageAlert(),
        LowCacheHitRateAlert()
    ]

    @Inject var logger: LoggerProtocol?

    func checkAlerts() {
        let report = PerformanceMonitor.shared.getDetailedReport()

        for alert in alerts {
            if alert.shouldTrigger(for: report) {
                logger?.warning("⚠️ Performance Alert: \(alert.message)")

                // Could send to analytics, crash reporting, etc.
                sendAlertToMonitoringService(alert)
            }
        }
    }

    private func sendAlertToMonitoringService(_ alert: PerformanceAlert) {
        // Implementation for external monitoring integration
    }
}

Continuous Performance Monitoring

Purpose: Automated, continuous monitoring system that provides ongoing visibility into application performance without manual intervention.

Continuous Monitoring Benefits:

  • 24/7 Visibility: Round-the-clock monitoring of application performance
  • Automatic Detection: Autonomous detection of performance issues
  • Trend Analysis: Long-term trend analysis for capacity planning
  • Proactive Optimization: Identify optimization opportunities before issues occur

Monitoring Capabilities:

  • Health Checks: Regular health assessments of performance metrics
  • Baseline Establishment: Automatic establishment of performance baselines
  • Deviation Detection: Detection of deviations from established baselines
  • Performance Regression: Automatic detection of performance regressions

Actor-Based Architecture:

  • Thread Safety: Safe concurrent monitoring using Swift actors
  • Resource Efficiency: Efficient monitoring with minimal performance impact
  • Scalable Design: Scalable architecture for high-throughput applications
  • Fault Tolerance: Resilient monitoring that continues even during failures
swift
actor ContinuousMonitor {
    private var isRunning = false
    private let checkInterval: TimeInterval = 30.0 // 30 seconds

    @Inject var logger: LoggerProtocol?

    func start() async {
        guard !isRunning else { return }
        isRunning = true

        logger?.info("🔄 Starting continuous performance monitoring")

        while isRunning {
            await performHealthCheck()
            try? await Task.sleep(nanoseconds: UInt64(checkInterval * 1_000_000_000))
        }
    }

    func stop() {
        isRunning = false
        logger?.info("⏹️ Stopping continuous performance monitoring")
    }

    private func performHealthCheck() async {
        let report = PerformanceMonitor.shared.getDetailedReport()

        // Log key metrics
        logger?.debug("""
        📊 Performance Health Check:
        - Resolution time: \(String(format: "%.2f", report.averageResolutionTime))ms
        - Memory usage: \(report.currentMemoryUsage / 1024 / 1024)MB
        - Cache hit rate: \(String(format: "%.1f", calculateOverallCacheHitRate(report) * 100))%
        """)

        // Check for performance degradation
        await checkForPerformanceDegradation(report)

        // Run alerts
        let alertManager = PerformanceAlertManager()
        alertManager.checkAlerts()
    }

    private func calculateOverallCacheHitRate(_ report: PerformanceReport) -> Double {
        let cacheOps = report.operations.filter { $0.name.contains("cache") }
        let hits = cacheOps.filter { $0.metadata["hit"] as? Bool == true }.count
        return cacheOps.isEmpty ? 1.0 : Double(hits) / Double(cacheOps.count)
    }

    private func checkForPerformanceDegradation(_ current: PerformanceReport) async {
        // Compare with historical data to detect degradation
        let historical = PerformanceMonitor.shared.getHistoricalBaseline()

        if current.averageResolutionTime > historical.averageResolutionTime * 1.5 {
            logger?.warning("⚠️ Resolution time degradation detected: \(String(format: "%.2f", current.averageResolutionTime))ms vs baseline \(String(format: "%.2f", historical.averageResolutionTime))ms")
        }

        if current.currentMemoryUsage > Int64(Double(historical.averageMemoryUsage) * 1.3) {
            logger?.warning("⚠️ Memory usage increase detected: \(current.currentMemoryUsage / 1024 / 1024)MB vs baseline \(historical.averageMemoryUsage / 1024 / 1024)MB")
        }
    }
}

Performance Optimization Recommendations

Dependency Resolution Optimization

Purpose: Advanced optimization strategies for improving dependency resolution performance through caching, batching, and intelligent resolution patterns.

Optimization Strategies:

  • Resolution Caching: Cache frequently resolved dependencies for faster access
  • Batch Resolution: Group multiple resolutions for improved efficiency
  • Lazy Loading: Defer resolution until dependencies are actually needed
  • Preloading: Preload critical dependencies during application startup

Caching Implementation:

  • Thread-Safe Caching: Concurrent-safe caching for multi-threaded applications
  • Cache Invalidation: Intelligent cache invalidation strategies
  • Memory Management: Efficient memory usage for cached dependencies
  • Performance Monitoring: Monitor cache effectiveness and hit rates

Performance Benefits:

  • Reduced Resolution Time: Significantly faster resolution for cached dependencies
  • Improved Throughput: Higher overall application throughput
  • Resource Efficiency: More efficient use of CPU and memory resources
  • Scalability: Better scalability under high load conditions
swift
class OptimizedDependencyManager {
    // Cache frequently resolved dependencies
    private var resolutionCache: [String: Any] = [:]
    private let cacheQueue = DispatchQueue(label: "resolution-cache", attributes: .concurrent)

    func getOptimizedService<T>(_ type: T.Type) -> T? {
        let key = String(describing: type)

        return cacheQueue.sync {
            if let cached = resolutionCache[key] as? T {
                PerformanceMonitor.shared.recordCacheHit(key)
                return cached
            }

            // Resolve and cache
            guard let service = WeaveDI.Container.shared.resolve(type) else { return nil }

            cacheQueue.async(flags: .barrier) {
                self.resolutionCache[key] = service
            }

            PerformanceMonitor.shared.recordCacheMiss(key)
            return service
        }
    }

    func clearCache() {
        cacheQueue.async(flags: .barrier) {
            self.resolutionCache.removeAll()
        }
    }
}

Memory Usage Optimization

Purpose: Comprehensive memory optimization strategies to minimize memory usage, prevent leaks, and improve overall application memory efficiency.

Memory Optimization Techniques:

  • Weak References: Use weak references to prevent retain cycles
  • Memory Warning Handling: Responsive handling of memory pressure conditions
  • Cache Management: Intelligent cache sizing and cleanup strategies
  • Resource Cleanup: Automatic cleanup of unused resources

Memory Management Features:

  • Automatic Cleanup: Automatic cleanup during memory pressure
  • Leak Prevention: Proactive prevention of common memory leak patterns
  • Memory Monitoring: Continuous monitoring of memory usage patterns
  • Resource Recycling: Efficient recycling of expensive resources

Optimization Benefits:

  • Reduced Memory Footprint: Lower overall memory usage
  • Improved Stability: Better application stability under memory pressure
  • Better Performance: Improved performance through efficient memory usage
  • Resource Efficiency: More efficient use of available memory resources
swift
class MemoryOptimizedContainer {
    private weak var container: WeaveDI.Container?

    init(container: WeaveDI.Container) {
        self.container = container
        setupMemoryWarningObserver()
    }

    private func setupMemoryWarningObserver() {
        NotificationCenter.default.addObserver(
            forName: UIApplication.didReceiveMemoryWarningNotification,
            object: nil,
            queue: .main
        ) { [weak self] _ in
            self?.handleMemoryWarning()
        }
    }

    private func handleMemoryWarning() {
        // Clear caches, release non-essential services
        PerformanceMonitor.shared.recordMemoryWarning()

        // Clear internal caches
        container?.clearInternalCaches()

        // Log memory state
        let currentMemory = PerformanceMonitor.shared.getCurrentMemoryUsage()
        print("💾 Memory warning - current usage: \(currentMemory / 1024 / 1024)MB")
    }
}

Integration with Development Tools

Xcode Instruments Integration

Purpose: Seamless integration with Xcode Instruments for comprehensive performance profiling and analysis using industry-standard development tools.

Instruments Integration Features:

  • Custom Signposts: Custom signposts for dependency injection operations
  • Performance Tracking: Detailed performance tracking in Instruments timeline
  • Memory Profiling: Integration with Instruments memory profiling tools
  • Thread Analysis: Thread usage analysis for concurrent operations

Profiling Capabilities:

  • Time Profiling: Detailed timing analysis of dependency operations
  • Memory Analysis: Comprehensive memory usage analysis
  • CPU Usage: CPU usage patterns during dependency resolution
  • Thread Safety: Analysis of thread safety and concurrency patterns

Development Workflow Integration:

  • Debug Builds: Enhanced profiling for debug builds
  • Performance Testing: Integration with performance test suites
  • Continuous Integration: Automated performance testing in CI/CD pipelines
  • Performance Regression Detection: Automatic detection of performance regressions
swift
class InstrumentsIntegration {
    static func startProfiling() {
        #if DEBUG
        // Enable detailed logging for Instruments
        PerformanceMonitor.shared.enableInstrumentsMode()

        // Add custom signposts
        os_signpost(.begin, log: OSLog(subsystem: "com.app.weavedinew", category: "DI"), name: "DI Container Operation")
        #endif
    }

    static func recordResolution<T>(_ type: T.Type, duration: TimeInterval) {
        #if DEBUG
        os_signpost(.event, log: OSLog(subsystem: "com.app.weavedi", category: "DI"), name: "Dependency Resolution", "Type: %{public}s, Duration: %.2fms", String(describing: type), duration * 1000)
        #endif
    }
}

Performance Testing Integration

Purpose: Comprehensive performance testing framework that validates performance characteristics and ensures performance requirements are met.

Testing Framework Features:

  • Automated Performance Tests: Automated test suites for performance validation
  • Benchmark Testing: Standardized benchmarks for consistent performance measurement
  • Load Testing: Performance testing under various load conditions
  • Regression Testing: Automatic detection of performance regressions

Test Categories:

  • Resolution Performance: Measure dependency resolution performance
  • Memory Usage: Validate memory usage patterns and limits
  • Concurrent Access: Test performance under concurrent access
  • Bootstrap Performance: Measure container initialization performance

Performance Validation:

  • Performance Assertions: Automated assertions for performance requirements
  • Threshold Validation: Validate performance against defined thresholds
  • Trend Analysis: Long-term performance trend analysis
  • Performance Reporting: Comprehensive performance test reporting
swift
class PerformanceTestSuite {
    func runPerformanceTests() async {
        await testResolutionPerformance()
        await testMemoryUsage()
        await testConcurrentAccess()
        await testBootstrapPerformance()
    }

    private func testResolutionPerformance() async {
        let iterations = 10000
        let startTime = CFAbsoluteTimeGetCurrent()

        for _ in 0..<iterations {
            _ = WeaveDI.Container.shared.resolve(TestService.self)
        }

        let endTime = CFAbsoluteTimeGetCurrent()
        let avgTime = (endTime - startTime) / Double(iterations) * 1000

        print("📊 Resolution Performance: \(String(format: "%.4f", avgTime))ms per resolution")
        assert(avgTime < 1.0, "Resolution time too high: \(avgTime)ms")
    }

    private func testMemoryUsage() async {
        let initialMemory = PerformanceMonitor.shared.getCurrentMemoryUsage()

        // Register many services
        for i in 0..<10000 {
            WeaveDI.Container.shared.register(TestService.self, name: "test_\(i)") {
                TestServiceImpl()
            }
        }

        let finalMemory = PerformanceMonitor.shared.getCurrentMemoryUsage()
        let memoryPerService = (finalMemory - initialMemory) / 10000

        print("💾 Memory per service: \(memoryPerService) bytes")
        assert(memoryPerService < 1024, "Memory usage per service too high: \(memoryPerService) bytes")
    }
}

Best Practices

1. Enable Monitoring Early

Strategy: Implement performance monitoring from the earliest stages of development to establish baselines and catch performance issues early.

Early Monitoring Benefits:

  • Baseline Establishment: Establish performance baselines during development
  • Early Issue Detection: Catch performance issues before they become problems
  • Development Feedback: Provide immediate feedback on performance impact of changes
  • Optimization Opportunities: Identify optimization opportunities early in development

Implementation Guidelines:

  • Application Startup: Enable monitoring during application initialization
  • Development Environment: Use monitoring in all development environments
  • Continuous Integration: Include monitoring in CI/CD pipelines
  • Team Adoption: Encourage team-wide adoption of monitoring practices
swift
@main
struct App: App {
    init() {
        // Enable monitoring at app start
        PerformanceMonitor.shared.enable()
        PerformanceMonitor.shared.setLogLevel(.info)
    }
}

2. Monitor Critical Paths

Strategy: Focus monitoring efforts on performance-critical code paths to maximize the impact of optimization efforts.

Critical Path Identification:

  • User-Facing Operations: Monitor operations that directly impact user experience
  • High-Frequency Operations: Focus on operations that execute frequently
  • Resource-Intensive Operations: Monitor operations that consume significant resources
  • Business-Critical Functions: Prioritize monitoring of business-critical functionality

Monitoring Implementation:

  • Selective Instrumentation: Instrument critical paths without overwhelming the system
  • Performance Thresholds: Set appropriate performance thresholds for critical operations
  • Alert Configuration: Configure alerts for critical path performance issues
  • Optimization Prioritization: Prioritize optimization efforts based on monitoring data
swift
// Monitor performance-critical operations
func performCriticalOperation() async {
    await PerformanceMonitor.shared.measureOperation("critical_path") {
        // Your critical code here
    }
}

3. Set Up Automated Alerts

Strategy: Implement automated alerting to ensure timely notification of performance issues and enable proactive response.

Alert Configuration Best Practices:

  • Threshold Tuning: Carefully tune alert thresholds to minimize false positives
  • Alert Prioritization: Prioritize alerts based on business impact and urgency
  • Escalation Policies: Implement appropriate escalation policies for different alert types
  • Team Distribution: Distribute alerts to appropriate team members based on expertise

Automation Benefits:

  • Proactive Response: Enable proactive response to performance issues
  • Reduced Downtime: Minimize downtime through early issue detection
  • Team Efficiency: Improve team efficiency through automated monitoring
  • Continuous Improvement: Enable continuous improvement through automated feedback
swift
// Set up regular performance checks
Task {
    let continuousMonitor = ContinuousMonitor()
    await continuousMonitor.start()
}

4. Profile in Different Scenarios

Strategy: Comprehensive performance profiling across different usage scenarios to ensure robust performance under all conditions.

Profiling Scenarios:

  • Load Testing: Profile performance under expected production loads
  • Stress Testing: Test performance under extreme conditions
  • Concurrent Usage: Profile concurrent usage patterns
  • Edge Cases: Test performance under edge case conditions

Scenario-Based Testing Benefits:

  • Comprehensive Coverage: Ensure performance across all usage scenarios
  • Bottleneck Identification: Identify bottlenecks under different conditions
  • Capacity Planning: Inform capacity planning with realistic performance data
  • Performance Validation: Validate performance requirements across scenarios

Implementation Strategies:

  • Automated Testing: Automate scenario-based performance testing
  • Environment Consistency: Ensure consistent testing environments
  • Data Collection: Collect comprehensive data across all scenarios
  • Analysis and Reporting: Provide detailed analysis and reporting of scenario results
swift
// Test performance under different conditions
func profileUnderLoad() async {
    PerformanceMonitor.shared.startProfiling("load_test")

    await withTaskGroup(of: Void.self) { group in
        for _ in 0..<100 {
            group.addTask {
                // Simulate concurrent usage
                _ = WeaveDI.Container.shared.resolve(HeavyService.self)
            }
        }
    }

    let report = PerformanceMonitor.shared.stopProfiling("load_test")
    print("Load test results: \(report)")
}

See Also

Released under the MIT License.