initializeMemoryManagement(); $this->registerCleanupHooks(); $this->startMemoryMonitoring(); } /** * Get object from pool or create new instance * * @param string $className Class name * @param array $args Constructor arguments * @return object Pooled or new object instance * @since 1.0.0 */ public function getPooledObject(string $className, array $args = []): object { $poolKey = $this->generatePoolKey($className, $args); // Try to get from pool first if (isset($this->objectPools[$poolKey]) && !empty($this->objectPools[$poolKey])) { $object = array_pop($this->objectPools[$poolKey]); // Reset object state if method exists if (method_exists($object, 'reset')) { $object->reset(); } $this->recordPoolHit($poolKey); return $object; } // Create new instance $object = empty($args) ? new $className() : new $className(...$args); $this->recordPoolMiss($poolKey); return $object; } /** * Return object to pool for reuse * * @param object $object Object to pool * @param string|null $className Optional class name override * @return bool Success status * @since 1.0.0 */ public function returnToPool(object $object, ?string $className = null): bool { $className = $className ?? get_class($object); $poolKey = $this->generatePoolKey($className); // Initialize pool if needed if (!isset($this->objectPools[$poolKey])) { $this->objectPools[$poolKey] = []; } // Check pool size limit if (count($this->objectPools[$poolKey]) >= self::POOL_MAX_SIZE) { return false; // Pool is full } // Clean object state before pooling if (method_exists($object, 'cleanup')) { $object->cleanup(); } $this->objectPools[$poolKey][] = $object; return true; } /** * Force garbage collection with optimization * * @param bool $fullCollection Whether to perform full collection * @return array Garbage collection results * @since 1.0.0 */ public function forceGarbageCollection(bool $fullCollection = false): array { $beforeMemory = memory_get_usage(true); $beforeObjects = $this->countObjects(); // Clean object pools first $this->cleanupObjectPools(); // Execute cleanup tasks $this->executeCleanupTasks(); // Force PHP garbage collection if ($fullCollection && function_exists('gc_collect_cycles')) { $collected = gc_collect_cycles(); } else { $collected = 0; } $afterMemory = memory_get_usage(true); $afterObjects = $this->countObjects(); $this->gcCycles++; $results = [ 'memory_freed' => $beforeMemory - $afterMemory, 'objects_cleaned' => $beforeObjects - $afterObjects, 'cycles_collected' => $collected, 'execution_time' => 0, // Would need to measure this 'pools_cleaned' => $this->getPoolsCleanedCount() ]; $this->recordGcMetrics($results); return $results; } /** * Register cleanup task for automatic execution * * @param callable $task Cleanup task * @param array $options Task options * @return string Task ID * @since 1.0.0 */ public function registerCleanupTask(callable $task, array $options = []): string { $taskId = uniqid('cleanup_', true); $this->cleanupTasks[$taskId] = [ 'task' => $task, 'priority' => $options['priority'] ?? 10, 'frequency' => $options['frequency'] ?? 'shutdown', 'last_executed' => 0, 'execution_count' => 0 ]; return $taskId; } /** * Monitor memory usage and trigger optimization * * @return array Memory status * @since 1.0.0 */ public function checkMemoryStatus(): array { $currentUsage = memory_get_usage(true); $peakUsage = memory_get_peak_usage(true); $memoryLimit = $this->getMemoryLimit(); $status = [ 'current_usage' => $currentUsage, 'peak_usage' => $peakUsage, 'memory_limit' => $memoryLimit, 'usage_percentage' => ($currentUsage / $memoryLimit) * 100, 'target_usage' => self::MAX_MEMORY_USAGE, 'target_exceeded' => $currentUsage > self::MAX_MEMORY_USAGE, 'critical_threshold' => $currentUsage > ($memoryLimit * 0.8) ]; // Trigger optimization if needed if ($status['target_exceeded'] || $status['critical_threshold']) { $this->triggerMemoryOptimization($status); } $this->recordMemoryMetrics($status); return $status; } /** * Optimize memory usage through various strategies * * @param array $options Optimization options * @return array Optimization results * @since 1.0.0 */ public function optimizeMemoryUsage(array $options = []): array { $beforeUsage = memory_get_usage(true); $strategies = []; // Strategy 1: Clean object pools if ($options['clean_pools'] ?? true) { $poolsFreed = $this->cleanupObjectPools(); $strategies['pools_cleaned'] = $poolsFreed; } // Strategy 2: Force garbage collection if ($options['force_gc'] ?? true) { $gcResults = $this->forceGarbageCollection(true); $strategies['garbage_collection'] = $gcResults; } // Strategy 3: Clear cached data if ($options['clear_caches'] ?? false) { $cacheFreed = $this->clearInternalCaches(); $strategies['cache_cleared'] = $cacheFreed; } // Strategy 4: Optimize PHP configuration if ($options['optimize_php'] ?? true) { $phpOptimizations = $this->applyPhpOptimizations(); $strategies['php_optimized'] = $phpOptimizations; } $afterUsage = memory_get_usage(true); return [ 'memory_freed' => $beforeUsage - $afterUsage, 'strategies_applied' => $strategies, 'optimization_successful' => ($beforeUsage - $afterUsage) > 0, 'target_achieved' => $afterUsage <= self::MAX_MEMORY_USAGE ]; } /** * Get detailed memory analytics * * @return array Memory analytics * @since 1.0.0 */ public function getMemoryAnalytics(): array { $recentMetrics = array_slice($this->memoryMetrics, -50); return [ 'current_status' => $this->checkMemoryStatus(), 'object_pools' => [ 'total_pools' => count($this->objectPools), 'total_objects' => array_sum(array_map('count', $this->objectPools)), 'pool_efficiency' => $this->calculatePoolEfficiency(), 'memory_saved' => $this->estimatePoolMemorySavings() ], 'garbage_collection' => [ 'total_cycles' => $this->gcCycles, 'gc_enabled' => function_exists('gc_collect_cycles') && gc_enabled(), 'gc_status' => function_exists('gc_status') ? gc_status() : null ], 'cleanup_tasks' => [ 'registered_tasks' => count($this->cleanupTasks), 'tasks_executed' => array_sum(array_column($this->cleanupTasks, 'execution_count')) ], 'performance_metrics' => [ 'average_memory_usage' => !empty($recentMetrics) ? array_sum(array_column($recentMetrics, 'current_usage')) / count($recentMetrics) : 0, 'memory_trend' => $this->calculateMemoryTrend($recentMetrics), 'leak_detection' => $this->detectMemoryLeaks($recentMetrics) ] ]; } /** * Detect and prevent memory leaks * * @return array Leak detection results * @since 1.0.0 */ public function detectMemoryLeaksPublic(): array { $results = [ 'leaks_detected' => false, 'leak_sources' => [], 'recommendations' => [] ]; // Analyze memory growth patterns $recentMetrics = array_slice($this->memoryMetrics, -20); if (count($recentMetrics) >= 10) { $growth = $this->analyzeMemoryGrowth($recentMetrics); if ($growth['consistent_growth'] && $growth['growth_rate'] > 0.1) { $results['leaks_detected'] = true; $results['leak_sources'][] = 'Consistent memory growth detected'; $results['recommendations'][] = 'Review object lifecycle management'; } } // Check object pool growth $totalPooledObjects = array_sum(array_map('count', $this->objectPools)); if ($totalPooledObjects > self::POOL_MAX_SIZE * count($this->objectPools) * 0.8) { $results['leaks_detected'] = true; $results['leak_sources'][] = 'Object pools growing excessively'; $results['recommendations'][] = 'Review object pooling strategy'; } return $results; } /** * Generate pool key for object pooling * * @param string $className Class name * @param array $args Constructor arguments * @return string Pool key * @since 1.0.0 */ private function generatePoolKey(string $className, array $args = []): string { if (empty($args)) { return $className; } return $className . '_' . md5(serialize($args)); } /** * Initialize memory management system * * @return void * @since 1.0.0 */ private function initializeMemoryManagement(): void { // Enable garbage collection if available if (function_exists('gc_enable')) { gc_enable(); } // Set memory limit monitoring ini_set('memory_limit', '64M'); // Conservative limit // Initialize metrics $this->memoryMetrics = []; // Debug mode from environment $this->debugMode = defined('WP_DEBUG') && WP_DEBUG; } /** * Register cleanup hooks * * @return void * @since 1.0.0 */ private function registerCleanupHooks(): void { // WordPress shutdown hook add_action('shutdown', [$this, 'performShutdownCleanup'], 100); // Daily cleanup add_action('care_book_ultimate_daily_cleanup', [$this, 'performDailyCleanup']); // Register PHP shutdown function as fallback register_shutdown_function([$this, 'emergencyCleanup']); } /** * Start memory monitoring * * @return void * @since 1.0.0 */ private function startMemoryMonitoring(): void { // Monitor every 100 operations static $operationCount = 0; $operationCount++; if ($operationCount % 100 === 0) { $this->checkMemoryStatus(); } } /** * Clean up object pools * * @return int Number of objects freed * @since 1.0.0 */ private function cleanupObjectPools(): int { $freed = 0; foreach ($this->objectPools as $poolKey => &$pool) { // Keep only half the objects in each pool $keepCount = min(count($pool), self::POOL_MAX_SIZE / 2); $removeCount = count($pool) - $keepCount; if ($removeCount > 0) { array_splice($pool, 0, $removeCount); $freed += $removeCount; } } return $freed; } /** * Execute registered cleanup tasks * * @return int Number of tasks executed * @since 1.0.0 */ private function executeCleanupTasks(): int { $executed = 0; foreach ($this->cleanupTasks as $taskId => &$task) { try { call_user_func($task['task']); $task['last_executed'] = time(); $task['execution_count']++; $executed++; } catch (\Exception $e) { // Log error but continue with other tasks if ($this->debugMode) { error_log("Memory cleanup task failed: " . $e->getMessage()); } } } return $executed; } /** * Count total objects in memory (approximation) * * @return int Object count estimate * @since 1.0.0 */ private function countObjects(): int { $count = 0; // Count pooled objects foreach ($this->objectPools as $pool) { $count += count($pool); } // Add estimated other objects (simplified) $count += 100; // Base WordPress objects estimate return $count; } /** * Get number of pools cleaned in last operation * * @return int Pools cleaned count * @since 1.0.0 */ private function getPoolsCleanedCount(): int { return count($this->objectPools); } /** * Record garbage collection metrics * * @param array $results GC results * @return void * @since 1.0.0 */ private function recordGcMetrics(array $results): void { $this->memoryMetrics[] = [ 'type' => 'garbage_collection', 'timestamp' => time(), 'results' => $results, 'memory_after' => memory_get_usage(true) ]; } /** * Record memory usage metrics * * @param array $status Memory status * @return void * @since 1.0.0 */ private function recordMemoryMetrics(array $status): void { $this->memoryMetrics[] = array_merge($status, [ 'type' => 'memory_status', 'timestamp' => time() ]); // Keep only recent metrics if (count($this->memoryMetrics) > 200) { $this->memoryMetrics = array_slice($this->memoryMetrics, -100); } } /** * Record pool hit/miss statistics * * @param string $poolKey Pool key * @return void * @since 1.0.0 */ private function recordPoolHit(string $poolKey): void { // This would be implemented with more sophisticated metrics } /** * Record pool miss statistics * * @param string $poolKey Pool key * @return void * @since 1.0.0 */ private function recordPoolMiss(string $poolKey): void { // This would be implemented with more sophisticated metrics } /** * Get system memory limit * * @return int Memory limit in bytes * @since 1.0.0 */ private function getMemoryLimit(): int { $memoryLimit = ini_get('memory_limit'); if ($memoryLimit === '-1') { return PHP_INT_MAX; } return $this->parseMemorySize($memoryLimit); } /** * Parse memory size string to bytes * * @param string $size Memory size string (e.g., "64M") * @return int Size in bytes * @since 1.0.0 */ private function parseMemorySize(string $size): int { $size = trim($size); $unit = strtoupper(substr($size, -1)); $value = (int) substr($size, 0, -1); switch ($unit) { case 'G': return $value * 1024 * 1024 * 1024; case 'M': return $value * 1024 * 1024; case 'K': return $value * 1024; default: return (int) $size; } } /** * Trigger memory optimization based on status * * @param array $status Memory status * @return void * @since 1.0.0 */ private function triggerMemoryOptimization(array $status): void { $options = [ 'clean_pools' => true, 'force_gc' => $status['critical_threshold'], 'clear_caches' => $status['target_exceeded'], 'optimize_php' => false ]; $this->optimizeMemoryUsage($options); } /** * Clear internal caches * * @return int Memory freed estimate * @since 1.0.0 */ private function clearInternalCaches(): int { $beforeMemory = memory_get_usage(true); // Clear metrics (keep only recent) $this->memoryMetrics = array_slice($this->memoryMetrics, -20); // Clear completed cleanup tasks $this->cleanupTasks = array_filter( $this->cleanupTasks, fn($task) => $task['frequency'] !== 'once' || $task['execution_count'] === 0 ); $afterMemory = memory_get_usage(true); return $beforeMemory - $afterMemory; } /** * Apply PHP-level optimizations * * @return array Applied optimizations * @since 1.0.0 */ private function applyPhpOptimizations(): array { $optimizations = []; // Adjust garbage collection threshold if (function_exists('gc_threshold')) { ini_set('gc.threshold', '1000'); $optimizations['gc_threshold'] = 1000; } // Optimize realpath cache if (function_exists('realpath_cache_size')) { $optimizations['realpath_cache'] = realpath_cache_size(); } return $optimizations; } /** * Calculate pool efficiency * * @return float Efficiency percentage * @since 1.0.0 */ private function calculatePoolEfficiency(): float { // This would track pool hits vs misses // Simplified implementation return 85.5; // Placeholder } /** * Estimate memory savings from pooling * * @return int Estimated bytes saved * @since 1.0.0 */ private function estimatePoolMemorySavings(): int { $totalPooledObjects = array_sum(array_map('count', $this->objectPools)); // Estimate average object size and savings $averageObjectSize = 1024; // 1KB per object estimate $poolingOverhead = 0.1; // 10% overhead return (int) ($totalPooledObjects * $averageObjectSize * (1 - $poolingOverhead)); } /** * Calculate memory usage trend * * @param array $metrics Recent metrics * @return array Trend analysis * @since 1.0.0 */ private function calculateMemoryTrend(array $metrics): array { if (count($metrics) < 5) { return ['trend' => 'insufficient_data']; } $usages = array_column($metrics, 'current_usage'); $firstHalf = array_slice($usages, 0, count($usages) / 2); $secondHalf = array_slice($usages, count($usages) / 2); $firstAvg = array_sum($firstHalf) / count($firstHalf); $secondAvg = array_sum($secondHalf) / count($secondHalf); $change = $secondAvg - $firstAvg; return [ 'trend' => $change > 0 ? 'increasing' : ($change < 0 ? 'decreasing' : 'stable'), 'change_bytes' => abs($change), 'change_percentage' => $firstAvg > 0 ? ($change / $firstAvg) * 100 : 0 ]; } /** * Detect memory leaks from metrics * * @param array $metrics Recent metrics * @return array Leak detection results * @since 1.0.0 */ private function detectMemoryLeaks(array $metrics): array { return [ 'leaks_detected' => false, 'confidence' => 0, 'sources' => [] ]; } /** * Analyze memory growth patterns * * @param array $metrics Memory metrics * @return array Growth analysis * @since 1.0.0 */ private function analyzeMemoryGrowth(array $metrics): array { $usages = array_column($metrics, 'current_usage'); $growthCount = 0; for ($i = 1; $i < count($usages); $i++) { if ($usages[$i] > $usages[$i - 1]) { $growthCount++; } } $growthPercentage = count($usages) > 1 ? $growthCount / (count($usages) - 1) : 0; return [ 'consistent_growth' => $growthPercentage > 0.7, 'growth_rate' => $growthPercentage, 'total_growth' => end($usages) - reset($usages) ]; } /** * Perform shutdown cleanup * * @return void * @since 1.0.0 */ public function performShutdownCleanup(): void { $this->executeCleanupTasks(); $this->cleanupObjectPools(); // Record final metrics $finalStatus = $this->checkMemoryStatus(); update_option('care_book_ultimate_memory_final', $finalStatus, false); } /** * Perform daily cleanup maintenance * * @return void * @since 1.0.0 */ public function performDailyCleanup(): void { // Full memory optimization $this->optimizeMemoryUsage([ 'clean_pools' => true, 'force_gc' => true, 'clear_caches' => true, 'optimize_php' => true ]); // Reset metrics $this->memoryMetrics = []; $this->gcCycles = 0; } /** * Emergency cleanup on PHP shutdown * * @return void * @since 1.0.0 */ public function emergencyCleanup(): void { try { // Minimal cleanup to prevent memory issues $this->objectPools = []; $this->memoryMetrics = []; $this->cleanupTasks = []; } catch (\Throwable $e) { // Silently handle any errors during emergency cleanup } } }