You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
796 lines
26 KiB
796 lines
26 KiB
/**
|
|
* DailyNotificationPerformanceOptimizer.swift
|
|
*
|
|
* iOS Performance Optimizer for database, memory, and battery optimization
|
|
* Implements query optimization, memory management, and battery tracking
|
|
*
|
|
* @author Matthew Raymer
|
|
* @version 1.0.0
|
|
*/
|
|
|
|
import Foundation
|
|
import os
|
|
|
|
/**
|
|
* Optimizes performance through database, memory, and battery management
|
|
*
|
|
* This class implements the critical performance optimization functionality:
|
|
* - Database query optimization with indexes
|
|
* - Memory usage monitoring and optimization
|
|
* - Object pooling for frequently used objects
|
|
* - Battery usage tracking and optimization
|
|
* - Background CPU usage minimization
|
|
* - Network request optimization
|
|
*/
|
|
class DailyNotificationPerformanceOptimizer {
|
|
|
|
// MARK: - Constants
|
|
|
|
private static let TAG = "DailyNotificationPerformanceOptimizer"
|
|
|
|
// Performance monitoring intervals
|
|
private static let MEMORY_CHECK_INTERVAL_SECONDS: TimeInterval = 5 * 60 // 5 minutes
|
|
private static let BATTERY_CHECK_INTERVAL_SECONDS: TimeInterval = 10 * 60 // 10 minutes
|
|
private static let PERFORMANCE_REPORT_INTERVAL_SECONDS: TimeInterval = 60 * 60 // 1 hour
|
|
|
|
// Memory thresholds
|
|
private static let MEMORY_WARNING_THRESHOLD_MB: Int = 50
|
|
private static let MEMORY_CRITICAL_THRESHOLD_MB: Int = 100
|
|
|
|
// Object pool sizes
|
|
private static let DEFAULT_POOL_SIZE = 10
|
|
private static let MAX_POOL_SIZE = 50
|
|
|
|
// MARK: - Properties
|
|
|
|
private let logger: DailyNotificationLogger
|
|
private let database: DailyNotificationDatabase
|
|
|
|
// Performance metrics
|
|
private let metrics = PerformanceMetrics()
|
|
|
|
// Object pools
|
|
private var objectPools: [String: ObjectPool] = [:]
|
|
private let poolQueue = DispatchQueue(label: "performance.pool", attributes: .concurrent)
|
|
|
|
// Memory monitoring
|
|
private var lastMemoryCheck: Date = Date()
|
|
private var lastBatteryCheck: Date = Date()
|
|
|
|
// MARK: - Initialization
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param logger Logger instance for debugging
|
|
* @param database Database instance for optimization
|
|
*/
|
|
init(logger: DailyNotificationLogger, database: DailyNotificationDatabase) {
|
|
self.logger = logger
|
|
self.database = database
|
|
|
|
// Initialize object pools
|
|
initializeObjectPools()
|
|
|
|
// Start performance monitoring
|
|
startPerformanceMonitoring()
|
|
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "PerformanceOptimizer initialized")
|
|
}
|
|
|
|
// MARK: - Database Optimization
|
|
|
|
/**
|
|
* Optimize database performance
|
|
*/
|
|
func optimizeDatabase() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Optimizing database performance")
|
|
|
|
// Add database indexes
|
|
addDatabaseIndexes()
|
|
|
|
// Optimize query performance
|
|
optimizeQueryPerformance()
|
|
|
|
// Implement connection pooling
|
|
optimizeConnectionPooling()
|
|
|
|
// Analyze database performance
|
|
analyzeDatabasePerformance()
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Database optimization completed")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error optimizing database: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add database indexes for query optimization
|
|
*/
|
|
private func addDatabaseIndexes() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Adding database indexes for query optimization")
|
|
|
|
// Add indexes for common queries
|
|
try database.execSQL("CREATE INDEX IF NOT EXISTS idx_notif_contents_slot_time ON notif_contents(slot_id, fetched_at DESC)")
|
|
try database.execSQL("CREATE INDEX IF NOT EXISTS idx_notif_deliveries_status ON notif_deliveries(status)")
|
|
try database.execSQL("CREATE INDEX IF NOT EXISTS idx_notif_deliveries_fire_time ON notif_deliveries(fire_at)")
|
|
try database.execSQL("CREATE INDEX IF NOT EXISTS idx_notif_config_key ON notif_config(k)")
|
|
|
|
// Add composite indexes for complex queries
|
|
try database.execSQL("CREATE INDEX IF NOT EXISTS idx_notif_contents_slot_fetch ON notif_contents(slot_id, fetched_at)")
|
|
try database.execSQL("CREATE INDEX IF NOT EXISTS idx_notif_deliveries_slot_status ON notif_deliveries(slot_id, status)")
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Database indexes added successfully")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error adding database indexes: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Optimize query performance
|
|
*/
|
|
private func optimizeQueryPerformance() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Optimizing query performance")
|
|
|
|
// Set database optimization pragmas
|
|
try database.execSQL("PRAGMA optimize")
|
|
try database.execSQL("PRAGMA analysis_limit=1000")
|
|
try database.execSQL("PRAGMA optimize")
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Query performance optimization completed")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error optimizing query performance: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Optimize connection pooling
|
|
*/
|
|
private func optimizeConnectionPooling() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Optimizing connection pooling")
|
|
|
|
// Set connection pool settings
|
|
try database.execSQL("PRAGMA cache_size=10000")
|
|
try database.execSQL("PRAGMA temp_store=MEMORY")
|
|
try database.execSQL("PRAGMA mmap_size=268435456") // 256MB
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Connection pooling optimization completed")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error optimizing connection pooling: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Analyze database performance
|
|
*/
|
|
private func analyzeDatabasePerformance() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Analyzing database performance")
|
|
|
|
// Get database statistics
|
|
let pageCount = try database.getPageCount()
|
|
let pageSize = try database.getPageSize()
|
|
let cacheSize = try database.getCacheSize()
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Database stats: pages=\(pageCount), pageSize=\(pageSize), cacheSize=\(cacheSize)")
|
|
|
|
// Update metrics
|
|
metrics.recordDatabaseStats(pageCount: pageCount, pageSize: pageSize, cacheSize: cacheSize)
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error analyzing database performance: \(error)")
|
|
}
|
|
}
|
|
|
|
// MARK: - Memory Optimization
|
|
|
|
/**
|
|
* Optimize memory usage
|
|
*/
|
|
func optimizeMemory() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Optimizing memory usage")
|
|
|
|
// Check current memory usage
|
|
let memoryUsage = getCurrentMemoryUsage()
|
|
|
|
if memoryUsage > DailyNotificationPerformanceOptimizer.MEMORY_CRITICAL_THRESHOLD_MB {
|
|
logger.warning(DailyNotificationPerformanceOptimizer.TAG, "Critical memory usage detected: \(memoryUsage)MB")
|
|
performCriticalMemoryCleanup()
|
|
} else if memoryUsage > DailyNotificationPerformanceOptimizer.MEMORY_WARNING_THRESHOLD_MB {
|
|
logger.warning(DailyNotificationPerformanceOptimizer.TAG, "High memory usage detected: \(memoryUsage)MB")
|
|
performMemoryCleanup()
|
|
}
|
|
|
|
// Optimize object pools
|
|
optimizeObjectPools()
|
|
|
|
// Update metrics
|
|
metrics.recordMemoryUsage(memoryUsage)
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Memory optimization completed")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error optimizing memory: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get current memory usage in MB
|
|
*
|
|
* @return Memory usage in MB
|
|
*/
|
|
private func getCurrentMemoryUsage() -> Int {
|
|
do {
|
|
var info = mach_task_basic_info()
|
|
var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size)/4
|
|
|
|
let kerr: kern_return_t = withUnsafeMutablePointer(to: &info) {
|
|
$0.withMemoryRebound(to: integer_t.self, capacity: 1) {
|
|
task_info(mach_task_self_, task_flavor_t(MACH_TASK_BASIC_INFO), $0, &count)
|
|
}
|
|
}
|
|
|
|
if kerr == KERN_SUCCESS {
|
|
return Int(info.resident_size / 1024 / 1024) // Convert to MB
|
|
} else {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error getting memory usage: \(kerr)")
|
|
return 0
|
|
}
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error getting memory usage: \(error)")
|
|
return 0
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Perform critical memory cleanup
|
|
*/
|
|
private func performCriticalMemoryCleanup() {
|
|
do {
|
|
logger.warning(DailyNotificationPerformanceOptimizer.TAG, "Performing critical memory cleanup")
|
|
|
|
// Clear object pools
|
|
clearObjectPools()
|
|
|
|
// Clear caches
|
|
clearCaches()
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Critical memory cleanup completed")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error performing critical memory cleanup: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Perform regular memory cleanup
|
|
*/
|
|
private func performMemoryCleanup() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Performing regular memory cleanup")
|
|
|
|
// Clean up expired objects in pools
|
|
cleanupObjectPools()
|
|
|
|
// Clear old caches
|
|
clearOldCaches()
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Regular memory cleanup completed")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error performing memory cleanup: \(error)")
|
|
}
|
|
}
|
|
|
|
// MARK: - Object Pooling
|
|
|
|
/**
|
|
* Initialize object pools
|
|
*/
|
|
private func initializeObjectPools() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Initializing object pools")
|
|
|
|
// Create pools for frequently used objects
|
|
createObjectPool(type: "String", initialSize: DailyNotificationPerformanceOptimizer.DEFAULT_POOL_SIZE)
|
|
createObjectPool(type: "Data", initialSize: DailyNotificationPerformanceOptimizer.DEFAULT_POOL_SIZE)
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Object pools initialized")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error initializing object pools: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create object pool for a type
|
|
*
|
|
* @param type Type to create pool for
|
|
* @param initialSize Initial pool size
|
|
*/
|
|
private func createObjectPool(type: String, initialSize: Int) {
|
|
do {
|
|
let pool = ObjectPool(type: type, maxSize: initialSize)
|
|
|
|
poolQueue.async(flags: .barrier) {
|
|
self.objectPools[type] = pool
|
|
}
|
|
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Object pool created for \(type) with size \(initialSize)")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error creating object pool for \(type): \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get object from pool
|
|
*
|
|
* @param type Type of object to get
|
|
* @return Object from pool or new instance
|
|
*/
|
|
func getObject(type: String) -> Any? {
|
|
do {
|
|
var pool: ObjectPool?
|
|
poolQueue.sync {
|
|
pool = objectPools[type]
|
|
}
|
|
|
|
if let pool = pool {
|
|
return pool.getObject()
|
|
}
|
|
|
|
// Create new instance if no pool exists
|
|
return createNewObject(type: type)
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error getting object from pool: \(error)")
|
|
return nil
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return object to pool
|
|
*
|
|
* @param type Type of object
|
|
* @param object Object to return
|
|
*/
|
|
func returnObject(type: String, object: Any) {
|
|
do {
|
|
var pool: ObjectPool?
|
|
poolQueue.sync {
|
|
pool = objectPools[type]
|
|
}
|
|
|
|
if let pool = pool {
|
|
pool.returnObject(object)
|
|
}
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error returning object to pool: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create new object of specified type
|
|
*
|
|
* @param type Type to create
|
|
* @return New object instance
|
|
*/
|
|
private func createNewObject(type: String) -> Any? {
|
|
switch type {
|
|
case "String":
|
|
return ""
|
|
case "Data":
|
|
return Data()
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Optimize object pools
|
|
*/
|
|
private func optimizeObjectPools() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Optimizing object pools")
|
|
|
|
poolQueue.async(flags: .barrier) {
|
|
for pool in self.objectPools.values {
|
|
pool.optimize()
|
|
}
|
|
}
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Object pools optimized")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error optimizing object pools: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clean up object pools
|
|
*/
|
|
private func cleanupObjectPools() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Cleaning up object pools")
|
|
|
|
poolQueue.async(flags: .barrier) {
|
|
for pool in self.objectPools.values {
|
|
pool.cleanup()
|
|
}
|
|
}
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Object pools cleaned up")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error cleaning up object pools: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear object pools
|
|
*/
|
|
private func clearObjectPools() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Clearing object pools")
|
|
|
|
poolQueue.async(flags: .barrier) {
|
|
for pool in self.objectPools.values {
|
|
pool.clear()
|
|
}
|
|
}
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Object pools cleared")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error clearing object pools: \(error)")
|
|
}
|
|
}
|
|
|
|
// MARK: - Battery Optimization
|
|
|
|
/**
|
|
* Optimize battery usage
|
|
*/
|
|
func optimizeBattery() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Optimizing battery usage")
|
|
|
|
// Minimize background CPU usage
|
|
minimizeBackgroundCPUUsage()
|
|
|
|
// Optimize network requests
|
|
optimizeNetworkRequests()
|
|
|
|
// Track battery usage
|
|
trackBatteryUsage()
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Battery optimization completed")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error optimizing battery: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Minimize background CPU usage
|
|
*/
|
|
private func minimizeBackgroundCPUUsage() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Minimizing background CPU usage")
|
|
|
|
// Reduce background task frequency
|
|
// This would adjust task intervals based on battery level
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Background CPU usage minimized")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error minimizing background CPU usage: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Optimize network requests
|
|
*/
|
|
private func optimizeNetworkRequests() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Optimizing network requests")
|
|
|
|
// Batch network requests when possible
|
|
// Reduce request frequency during low battery
|
|
// Use efficient data formats
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Network requests optimized")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error optimizing network requests: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Track battery usage
|
|
*/
|
|
private func trackBatteryUsage() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Tracking battery usage")
|
|
|
|
// This would integrate with battery monitoring APIs
|
|
// Track battery consumption patterns
|
|
// Adjust behavior based on battery level
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Battery usage tracking completed")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error tracking battery usage: \(error)")
|
|
}
|
|
}
|
|
|
|
// MARK: - Performance Monitoring
|
|
|
|
/**
|
|
* Start performance monitoring
|
|
*/
|
|
private func startPerformanceMonitoring() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Starting performance monitoring")
|
|
|
|
// Schedule memory monitoring
|
|
Timer.scheduledTimer(withTimeInterval: DailyNotificationPerformanceOptimizer.MEMORY_CHECK_INTERVAL_SECONDS, repeats: true) { _ in
|
|
self.checkMemoryUsage()
|
|
}
|
|
|
|
// Schedule battery monitoring
|
|
Timer.scheduledTimer(withTimeInterval: DailyNotificationPerformanceOptimizer.BATTERY_CHECK_INTERVAL_SECONDS, repeats: true) { _ in
|
|
self.checkBatteryUsage()
|
|
}
|
|
|
|
// Schedule performance reporting
|
|
Timer.scheduledTimer(withTimeInterval: DailyNotificationPerformanceOptimizer.PERFORMANCE_REPORT_INTERVAL_SECONDS, repeats: true) { _ in
|
|
self.reportPerformance()
|
|
}
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Performance monitoring started")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error starting performance monitoring: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check memory usage
|
|
*/
|
|
private func checkMemoryUsage() {
|
|
do {
|
|
let currentTime = Date()
|
|
if currentTime.timeIntervalSince(lastMemoryCheck) < DailyNotificationPerformanceOptimizer.MEMORY_CHECK_INTERVAL_SECONDS {
|
|
return
|
|
}
|
|
|
|
lastMemoryCheck = currentTime
|
|
|
|
let memoryUsage = getCurrentMemoryUsage()
|
|
metrics.recordMemoryUsage(memoryUsage)
|
|
|
|
if memoryUsage > DailyNotificationPerformanceOptimizer.MEMORY_WARNING_THRESHOLD_MB {
|
|
logger.warning(DailyNotificationPerformanceOptimizer.TAG, "High memory usage detected: \(memoryUsage)MB")
|
|
optimizeMemory()
|
|
}
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error checking memory usage: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check battery usage
|
|
*/
|
|
private func checkBatteryUsage() {
|
|
do {
|
|
let currentTime = Date()
|
|
if currentTime.timeIntervalSince(lastBatteryCheck) < DailyNotificationPerformanceOptimizer.BATTERY_CHECK_INTERVAL_SECONDS {
|
|
return
|
|
}
|
|
|
|
lastBatteryCheck = currentTime
|
|
|
|
// This would check actual battery usage
|
|
// For now, we'll just log the check
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Battery usage check performed")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error checking battery usage: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Report performance metrics
|
|
*/
|
|
private func reportPerformance() {
|
|
do {
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Performance Report:")
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, " Memory Usage: \(metrics.getAverageMemoryUsage())MB")
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, " Database Queries: \(metrics.getTotalDatabaseQueries())")
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, " Object Pool Hits: \(metrics.getObjectPoolHits())")
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, " Performance Score: \(metrics.getPerformanceScore())")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error reporting performance: \(error)")
|
|
}
|
|
}
|
|
|
|
// MARK: - Utility Methods
|
|
|
|
/**
|
|
* Clear caches
|
|
*/
|
|
private func clearCaches() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Clearing caches")
|
|
|
|
// Clear database caches
|
|
try database.execSQL("PRAGMA cache_size=0")
|
|
try database.execSQL("PRAGMA cache_size=1000")
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Caches cleared")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error clearing caches: \(error)")
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clear old caches
|
|
*/
|
|
private func clearOldCaches() {
|
|
do {
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Clearing old caches")
|
|
|
|
// This would clear old cache entries
|
|
// For now, we'll just log the action
|
|
|
|
logger.info(DailyNotificationPerformanceOptimizer.TAG, "Old caches cleared")
|
|
|
|
} catch {
|
|
logger.error(DailyNotificationPerformanceOptimizer.TAG, "Error clearing old caches: \(error)")
|
|
}
|
|
}
|
|
|
|
// MARK: - Public API
|
|
|
|
/**
|
|
* Get performance metrics
|
|
*
|
|
* @return PerformanceMetrics with current statistics
|
|
*/
|
|
func getMetrics() -> PerformanceMetrics {
|
|
return metrics
|
|
}
|
|
|
|
/**
|
|
* Reset performance metrics
|
|
*/
|
|
func resetMetrics() {
|
|
metrics.reset()
|
|
logger.debug(DailyNotificationPerformanceOptimizer.TAG, "Performance metrics reset")
|
|
}
|
|
|
|
// MARK: - Data Classes
|
|
|
|
/**
|
|
* Object pool for managing object reuse
|
|
*/
|
|
private class ObjectPool {
|
|
let type: String
|
|
private var pool: [Any] = []
|
|
private let maxSize: Int
|
|
private var currentSize: Int = 0
|
|
|
|
init(type: String, maxSize: Int) {
|
|
self.type = type
|
|
self.maxSize = maxSize
|
|
}
|
|
|
|
func getObject() -> Any? {
|
|
if !pool.isEmpty {
|
|
let object = pool.removeFirst()
|
|
currentSize -= 1
|
|
return object
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func returnObject(_ object: Any) {
|
|
if currentSize < maxSize {
|
|
pool.append(object)
|
|
currentSize += 1
|
|
}
|
|
}
|
|
|
|
func optimize() {
|
|
// Remove excess objects
|
|
while currentSize > maxSize / 2 && !pool.isEmpty {
|
|
pool.removeFirst()
|
|
currentSize -= 1
|
|
}
|
|
}
|
|
|
|
func cleanup() {
|
|
pool.removeAll()
|
|
currentSize = 0
|
|
}
|
|
|
|
func clear() {
|
|
pool.removeAll()
|
|
currentSize = 0
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Performance metrics
|
|
*/
|
|
class PerformanceMetrics {
|
|
private var totalMemoryUsage: Int = 0
|
|
private var memoryCheckCount: Int = 0
|
|
private var totalDatabaseQueries: Int = 0
|
|
private var objectPoolHits: Int = 0
|
|
private var performanceScore: Int = 100
|
|
|
|
func recordMemoryUsage(_ usage: Int) {
|
|
totalMemoryUsage += usage
|
|
memoryCheckCount += 1
|
|
}
|
|
|
|
func recordDatabaseQuery() {
|
|
totalDatabaseQueries += 1
|
|
}
|
|
|
|
func recordObjectPoolHit() {
|
|
objectPoolHits += 1
|
|
}
|
|
|
|
func updatePerformanceScore(_ score: Int) {
|
|
performanceScore = max(0, min(100, score))
|
|
}
|
|
|
|
func recordDatabaseStats(pageCount: Int, pageSize: Int, cacheSize: Int) {
|
|
// Update performance score based on database stats
|
|
let score = max(0, min(100, 100 - (pageCount / 1000)))
|
|
updatePerformanceScore(score)
|
|
}
|
|
|
|
func reset() {
|
|
totalMemoryUsage = 0
|
|
memoryCheckCount = 0
|
|
totalDatabaseQueries = 0
|
|
objectPoolHits = 0
|
|
performanceScore = 100
|
|
}
|
|
|
|
func getAverageMemoryUsage() -> Int {
|
|
return memoryCheckCount > 0 ? totalMemoryUsage / memoryCheckCount : 0
|
|
}
|
|
|
|
func getTotalDatabaseQueries() -> Int {
|
|
return totalDatabaseQueries
|
|
}
|
|
|
|
func getObjectPoolHits() -> Int {
|
|
return objectPoolHits
|
|
}
|
|
|
|
func getPerformanceScore() -> Int {
|
|
return performanceScore
|
|
}
|
|
}
|
|
}
|
|
|