Newwebshop/app/Core/PerformanceOptimizer.php

589 lines
17 KiB
PHP

<?php
/**
* Copyright seit 2024 Webshop System
*
* Performance-Optimierung für PrestaShop-Modul-Kompatibilität
*
* @author Webshop System
* @license GPL v3
*/
namespace App\Core;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Exception;
class PerformanceOptimizer
{
private static $instance = null;
private $cache;
private $logger;
private $enabled = true;
private $redisEnabled = false;
private $memcachedEnabled = false;
private $lazyLoadingEnabled = true;
private $databaseOptimizationEnabled = true;
private $memoryOptimizationEnabled = true;
private function __construct()
{
$this->cache = Cache::getInstance();
$this->logger = Logger::getInstance();
$this->loadSettings();
}
/**
* Singleton-Instanz abrufen
*/
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Einstellungen laden
*/
private function loadSettings()
{
try {
$conn = DriverManager::getConnection([
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
]);
$stmt = $conn->prepare('
SELECT setting_key, setting_value
FROM ws_performance_settings
WHERE active = 1
');
$stmt->execute();
$settings = $stmt->fetchAllAssociative();
foreach ($settings as $setting) {
switch ($setting['setting_key']) {
case 'enabled':
$this->enabled = (bool)$setting['setting_value'];
break;
case 'redis_enabled':
$this->redisEnabled = (bool)$setting['setting_value'];
break;
case 'memcached_enabled':
$this->memcachedEnabled = (bool)$setting['setting_value'];
break;
case 'lazy_loading_enabled':
$this->lazyLoadingEnabled = (bool)$setting['setting_value'];
break;
case 'database_optimization_enabled':
$this->databaseOptimizationEnabled = (bool)$setting['setting_value'];
break;
case 'memory_optimization_enabled':
$this->memoryOptimizationEnabled = (bool)$setting['setting_value'];
break;
}
}
} catch (Exception $e) {
$this->logger->error('Performance-Einstellungen laden Fehler', [
'error' => $e->getMessage()
]);
}
}
/**
* Redis-Cache initialisieren
*/
public function initRedisCache()
{
if (!$this->redisEnabled) {
return false;
}
try {
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);
// Redis-Konfiguration
$redis->setOption(\Redis::OPT_SERIALIZER, \Redis::SERIALIZER_PHP);
$redis->setOption(\Redis::OPT_PREFIX, 'webshop:');
return $redis;
} catch (\Exception $e) {
$this->logger->error('Redis-Verbindung Fehler', [
'error' => $e->getMessage()
]);
return false;
}
}
/**
* Memcached-Cache initialisieren
*/
public function initMemcachedCache()
{
if (!$this->memcachedEnabled) {
return false;
}
try {
$memcached = new \Memcached();
$memcached->addServer('127.0.0.1', 11211);
return $memcached;
} catch (\Exception $e) {
$this->logger->error('Memcached-Verbindung Fehler', [
'error' => $e->getMessage()
]);
return false;
}
}
/**
* Lazy-Loading für Module
*/
public function lazyLoadModule($moduleName)
{
if (!$this->lazyLoadingEnabled) {
return false;
}
try {
$cacheKey = 'lazy_loaded_module_' . $moduleName;
// Cache prüfen
$cached = $this->cache->get($cacheKey);
if ($cached !== null) {
return $cached;
}
// Module-Klasse laden
$moduleClass = $this->loadModuleClass($moduleName);
if ($moduleClass) {
// Cache setzen
$this->cache->set($cacheKey, $moduleClass, 3600); // 1 Stunde
$this->logger->info('Module lazy geladen', [
'module_name' => $moduleName
]);
return $moduleClass;
}
return false;
} catch (\Exception $e) {
$this->logger->error('Lazy-Loading Fehler', [
'module_name' => $moduleName,
'error' => $e->getMessage()
]);
return false;
}
}
/**
* Module-Klasse laden
*/
private function loadModuleClass($moduleName)
{
$modulePath = __DIR__ . '/../../../modules/' . $moduleName . '/Module.php';
if (!file_exists($modulePath)) {
return false;
}
require_once $modulePath;
$className = ucfirst($moduleName) . 'Module';
if (!class_exists($className)) {
return false;
}
return $className;
}
/**
* Database-Optimierung
*/
public function optimizeDatabase()
{
if (!$this->databaseOptimizationEnabled) {
return false;
}
try {
$conn = DriverManager::getConnection([
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
]);
// Module-Tabellen optimieren
$tables = [
'ws_modules',
'ws_hooks',
'ws_overrides',
'ws_events',
'ws_cache',
'ws_logs',
'ws_plugins',
'ws_extensions',
'ws_dependencies'
];
foreach ($tables as $table) {
$stmt = $conn->prepare('OPTIMIZE TABLE ' . $table);
$stmt->execute();
}
// Indizes analysieren
foreach ($tables as $table) {
$stmt = $conn->prepare('ANALYZE TABLE ' . $table);
$stmt->execute();
}
$this->logger->info('Database-Optimierung abgeschlossen', [
'tables_optimized' => count($tables)
]);
return true;
} catch (Exception $e) {
$this->logger->error('Database-Optimierung Fehler', [
'error' => $e->getMessage()
]);
return false;
}
}
/**
* Memory-Optimierung
*/
public function optimizeMemory()
{
if (!$this->memoryOptimizationEnabled) {
return false;
}
try {
// Garbage Collection erzwingen
gc_collect_cycles();
// Memory-Limit prüfen
$memoryLimit = ini_get('memory_limit');
$memoryUsage = memory_get_usage(true);
$memoryPeak = memory_get_peak_usage(true);
// Cache optimieren
$this->optimizeCache();
// Unused Variables löschen
$this->cleanupUnusedVariables();
$this->logger->info('Memory-Optimierung abgeschlossen', [
'memory_limit' => $memoryLimit,
'memory_usage' => $this->formatBytes($memoryUsage),
'memory_peak' => $this->formatBytes($memoryPeak)
]);
return true;
} catch (\Exception $e) {
$this->logger->error('Memory-Optimierung Fehler', [
'error' => $e->getMessage()
]);
return false;
}
}
/**
* Cache optimieren
*/
private function optimizeCache()
{
// Alte Cache-Einträge löschen
$this->cache->cleanup();
// Cache-Größe reduzieren
$this->cache->optimize();
}
/**
* Unused Variables löschen
*/
private function cleanupUnusedVariables()
{
// Globale Variablen prüfen
$globalVars = get_defined_vars();
foreach ($globalVars as $var => $value) {
if (is_object($value) && method_exists($value, '__destruct')) {
unset($globalVars[$var]);
}
}
}
/**
* Performance-Monitoring
*/
public function monitorPerformance()
{
$metrics = [
'memory_usage' => memory_get_usage(true),
'memory_peak' => memory_get_peak_usage(true),
'execution_time' => microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'],
'database_queries' => $this->getDatabaseQueryCount(),
'cache_hits' => $this->cache->getHitCount(),
'cache_misses' => $this->cache->getMissCount()
];
// Metrics speichern
$this->savePerformanceMetrics($metrics);
// Alerts bei Performance-Problemen
$this->checkPerformanceAlerts($metrics);
return $metrics;
}
/**
* Database-Query-Count abrufen
*/
private function getDatabaseQueryCount()
{
// Vereinfachte Implementierung
// In der Praxis würde hier ein Query-Counter verwendet
return 0;
}
/**
* Performance-Metrics speichern
*/
private function savePerformanceMetrics($metrics)
{
try {
$conn = DriverManager::getConnection([
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
]);
$stmt = $conn->prepare('
INSERT INTO ws_performance_metrics (
memory_usage, memory_peak, execution_time,
database_queries, cache_hits, cache_misses, created_at
) VALUES (?, ?, ?, ?, ?, ?, NOW())
');
$stmt->execute([
$metrics['memory_usage'],
$metrics['memory_peak'],
$metrics['execution_time'],
$metrics['database_queries'],
$metrics['cache_hits'],
$metrics['cache_misses']
]);
} catch (Exception $e) {
$this->logger->error('Performance-Metrics speichern Fehler', [
'error' => $e->getMessage()
]);
}
}
/**
* Performance-Alerts prüfen
*/
private function checkPerformanceAlerts($metrics)
{
$alerts = [];
// Memory-Alert
if ($metrics['memory_usage'] > 100 * 1024 * 1024) { // 100MB
$alerts[] = 'High memory usage: ' . $this->formatBytes($metrics['memory_usage']);
}
// Execution-Time-Alert
if ($metrics['execution_time'] > 5.0) { // 5 Sekunden
$alerts[] = 'Slow execution time: ' . round($metrics['execution_time'], 2) . 's';
}
// Cache-Alert
$cacheHitRate = $metrics['cache_hits'] / max(1, $metrics['cache_hits'] + $metrics['cache_misses']);
if ($cacheHitRate < 0.8) { // 80%
$alerts[] = 'Low cache hit rate: ' . round($cacheHitRate * 100, 1) . '%';
}
if (!empty($alerts)) {
$this->logger->warning('Performance-Alerts', [
'alerts' => $alerts
]);
}
}
/**
* Bytes formatieren
*/
private function formatBytes($bytes)
{
$units = ['B', 'KB', 'MB', 'GB'];
for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
$bytes /= 1024;
}
return round($bytes, 2) . ' ' . $units[$i];
}
/**
* Performance-Statistiken abrufen
*/
public function getPerformanceStatistics()
{
try {
$conn = DriverManager::getConnection([
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
]);
// Durchschnittliche Performance-Metrics
$stmt = $conn->prepare('
SELECT
AVG(memory_usage) as avg_memory_usage,
AVG(memory_peak) as avg_memory_peak,
AVG(execution_time) as avg_execution_time,
AVG(database_queries) as avg_database_queries,
AVG(cache_hits) as avg_cache_hits,
AVG(cache_misses) as avg_cache_misses,
COUNT(*) as total_requests
FROM ws_performance_metrics
WHERE created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)
');
$stmt->execute();
$stats = $stmt->fetchAssociative();
// Cache-Hit-Rate berechnen
$totalCacheRequests = $stats['avg_cache_hits'] + $stats['avg_cache_misses'];
$cacheHitRate = $totalCacheRequests > 0 ? ($stats['avg_cache_hits'] / $totalCacheRequests) * 100 : 0;
return [
'avg_memory_usage' => $this->formatBytes($stats['avg_memory_usage'] ?? 0),
'avg_memory_peak' => $this->formatBytes($stats['avg_memory_peak'] ?? 0),
'avg_execution_time' => round($stats['avg_execution_time'] ?? 0, 3),
'avg_database_queries' => round($stats['avg_database_queries'] ?? 0, 1),
'cache_hit_rate' => round($cacheHitRate, 1),
'total_requests' => $stats['total_requests'] ?? 0
];
} catch (Exception $e) {
$this->logger->error('Performance-Statistiken abrufen Fehler', [
'error' => $e->getMessage()
]);
return [];
}
}
/**
* Performance-Einstellungen speichern
*/
public function saveSettings($settings)
{
try {
$conn = DriverManager::getConnection([
'url' => getenv('DATABASE_URL') ?: 'mysql://root:password@localhost/webshop'
]);
foreach ($settings as $key => $value) {
$stmt = $conn->prepare('
INSERT INTO ws_performance_settings (
setting_key, setting_value, active, updated_at
) VALUES (?, ?, 1, NOW())
ON DUPLICATE KEY UPDATE
setting_value = ?, updated_at = NOW()
');
$stmt->execute([$key, $value, $value]);
}
// Einstellungen neu laden
$this->loadSettings();
$this->logger->info('Performance-Einstellungen gespeichert', [
'settings' => $settings
]);
return true;
} catch (Exception $e) {
$this->logger->error('Performance-Einstellungen speichern Fehler', [
'error' => $e->getMessage()
]);
return false;
}
}
/**
* Performance-Optimizer aktivieren/deaktivieren
*/
public function setEnabled($enabled)
{
$this->enabled = $enabled;
return $this;
}
/**
* Performance-Optimizer Status prüfen
*/
public function isEnabled()
{
return $this->enabled;
}
/**
* Redis-Cache Status prüfen
*/
public function isRedisEnabled()
{
return $this->redisEnabled;
}
/**
* Memcached-Cache Status prüfen
*/
public function isMemcachedEnabled()
{
return $this->memcachedEnabled;
}
/**
* Lazy-Loading Status prüfen
*/
public function isLazyLoadingEnabled()
{
return $this->lazyLoadingEnabled;
}
/**
* Database-Optimierung Status prüfen
*/
public function isDatabaseOptimizationEnabled()
{
return $this->databaseOptimizationEnabled;
}
/**
* Memory-Optimierung Status prüfen
*/
public function isMemoryOptimizationEnabled()
{
return $this->memoryOptimizationEnabled;
}
}