memoryHistory = new CircularMemoryBuffer(maxSize: 100); $this->emergencyCallback = $emergencyCallback; } /** * Check memory status and take action if needed */ public function check(): GuardResult { $this->checkCounter++; $memoryStatus = $this->memoryManager->getMemoryStatus(); // Track memory history for leak detection using CircularMemoryBuffer $this->memoryHistory->add($memoryStatus->currentUsage); $actions = []; // Handle critical memory situations if ($memoryStatus->status === MemoryStatus::CRITICAL && ! $this->emergencyMode) { $this->emergencyMode = true; $actions[] = GuardAction::EMERGENCY_CLEANUP; if ($this->emergencyCallback) { ($this->emergencyCallback)(); } // Perform immediate cleanup $cleanupResult = $this->memoryManager->performCleanup(); $actions[] = $cleanupResult->wasEffective() ? GuardAction::CLEANUP_SUCCESSFUL : GuardAction::CLEANUP_FAILED; } // Handle warning conditions if ($memoryStatus->status === MemoryStatus::WARNING) { $actions[] = GuardAction::WARNING_ISSUED; // Suggest cleanup if it's time if ($this->memoryManager->shouldCleanup($this->checkCounter)) { $actions[] = GuardAction::CLEANUP_SUGGESTED; } } // Check for memory leaks periodically using CircularMemoryBuffer if ($this->checkCounter % 20 === 0) { $leakInfo = $this->memoryManager->checkForMemoryLeaks($this->memoryHistory); if ($leakInfo !== null) { $actions[] = match ($leakInfo->severity) { LeakSeverity::CRITICAL => GuardAction::CRITICAL_LEAK_DETECTED, LeakSeverity::HIGH => GuardAction::HIGH_LEAK_DETECTED, LeakSeverity::MEDIUM => GuardAction::MEDIUM_LEAK_DETECTED, LeakSeverity::LOW => GuardAction::LOW_LEAK_DETECTED }; } } // Reset emergency mode if memory is back to normal if ($this->emergencyMode && $memoryStatus->status === MemoryStatus::NORMAL) { $this->emergencyMode = false; $actions[] = GuardAction::EMERGENCY_MODE_RESET; } return new GuardResult( memoryStatus: $memoryStatus, actions: $actions, checkNumber: $this->checkCounter, emergencyMode: $this->emergencyMode ); } /** * Force emergency cleanup */ public function forceEmergencyCleanup(): MemoryCleanupResult { $this->emergencyMode = true; if ($this->emergencyCallback) { ($this->emergencyCallback)(); } return $this->memoryManager->performCleanup(); } /** * Get current memory statistics */ public function getStatistics(): GuardStatistics { $memoryStatus = $this->memoryManager->getMemoryStatus(); $samples = $this->memoryHistory->getSamples(); $historyCount = $this->memoryHistory->getCount(); $averageUsage = $historyCount > 0 ? Byte::fromBytes((int) (array_sum(array_map(fn (Byte $byte) => $byte->toBytes(), $samples)) / $historyCount)) : Byte::zero(); $peakUsage = $historyCount > 0 ? array_reduce($samples, fn ($max, $current) => $current->greaterThan($max ?? Byte::zero()) ? $current : $max, Byte::zero()) : Byte::zero(); return new GuardStatistics( totalChecks: $this->checkCounter, currentStatus: $memoryStatus, averageUsage: $averageUsage, peakUsage: $peakUsage, historySize: $historyCount, emergencyMode: $this->emergencyMode ); } /** * Reset guard state */ public function reset(): void { $this->memoryHistory->clear(); $this->checkCounter = 0; $this->emergencyMode = false; } /** * Check if it's safe to continue processing */ public function isSafeToProcess(): bool { $memoryStatus = $this->memoryManager->getMemoryStatus(); return $memoryStatus->status !== MemoryStatus::CRITICAL; } /** * Get recommendations for current memory state * @return string[] */ public function getRecommendations(): array { $memoryStatus = $this->memoryManager->getMemoryStatus(); $recommendations = []; switch ($memoryStatus->status) { case MemoryStatus::CRITICAL: $recommendations[] = 'Immediate action required: Reduce batch size or stop processing'; $recommendations[] = 'Consider switching to STREAMING memory strategy'; $recommendations[] = 'Force garbage collection and cleanup caches'; break; case MemoryStatus::WARNING: $recommendations[] = 'Consider reducing batch size'; $recommendations[] = 'Enable more frequent cleanup cycles'; $recommendations[] = 'Monitor for memory leaks'; break; case MemoryStatus::NORMAL: if ($memoryStatus->memoryPressure->toDecimal() > 0.5) { $recommendations[] = 'Memory usage is moderate - consider optimization'; } break; } // Check for potential leaks using CircularMemoryBuffer if ($this->memoryHistory->getCount() > 10) { $leakInfo = $this->memoryManager->checkForMemoryLeaks($this->memoryHistory); if ($leakInfo !== null) { $recommendations[] = "Memory leak detected ({$leakInfo->severity->value}): Review object retention"; } } return $recommendations; } }