diff --git a/preload.php b/preload.php index fb3aa5c1b..3b4f52bfc 100644 --- a/preload.php +++ b/preload.php @@ -1,297 +1,743 @@ 0, + 'skipped' => 0, + 'errors' => [], + 'start_time' => hrtime(true), + 'start_memory' => memory_get_usage(true), +]; + +// ============================================================================= +// PRELOAD FUNCTIONS +// ============================================================================= /** - * Compile a file into OPcache without executing it + * Compile a single file into OPcache + * Returns true if successfully compiled */ function preloadFile(string $path): bool { - global $preloadedCount, $skippedCount; + global $stats; + // Fast path checks if (!is_file($path) || !is_readable($path)) { return false; } + + // Skip empty files + if (filesize($path) === 0) { + return false; + } try { - if (opcache_compile_file($path)) { - $preloadedCount++; + if (@opcache_compile_file($path)) { + $stats['preloaded']++; return true; } } catch (Throwable $e) { - // Silently skip files that can't be preloaded (syntax errors, etc.) + $stats['errors'][] = basename($path) . ': ' . $e->getMessage(); } - $skippedCount++; + $stats['skipped']++; return false; } /** - * Recursively preload all PHP files in a directory + * Preload files from array with existence check */ -function preloadDirectory(string $dir, array $excludePatterns = []): void +function preloadFiles(array $files): void { - if (!is_dir($dir)) { + foreach ($files as $file) { + preloadFile($file); + } +} + +/** + * Recursively preload directory with filtering + */ +function preloadDirectory(string $dir, array $excludePatterns = [], int $maxDepth = 20): void +{ + if (!is_dir($dir) || !is_readable($dir)) { return; } $iterator = new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS), + new RecursiveDirectoryIterator( + $dir, + FilesystemIterator::SKIP_DOTS | FilesystemIterator::FOLLOW_SYMLINKS + ), RecursiveIteratorIterator::LEAVES_ONLY ); + $iterator->setMaxDepth($maxDepth); + $files = []; foreach ($iterator as $file) { if (!$file->isFile() || $file->getExtension() !== 'php') { continue; } $path = $file->getRealPath(); + if ($path === false) { + continue; + } - // Skip excluded patterns + // Apply exclude patterns + $skip = false; foreach ($excludePatterns as $pattern) { if (preg_match($pattern, $path)) { - continue 2; + $skip = true; + break; } } - + + if (!$skip) { + $files[] = $path; + } + } + + // Sort for consistent ordering (helps with JIT optimization) + sort($files, SORT_STRING); + + foreach ($files as $path) { preloadFile($path); } } /** - * Preload specific files from a list + * Preload specific classes from a namespace (using Composer's classmap) */ -function preloadFiles(array $files): void +function preloadClassmap(string $classmapFile): void { - foreach ($files as $file) { - if (is_file($file)) { - preloadFile($file); - } + if (!is_file($classmapFile)) { + return; + } + + $classmap = require $classmapFile; + if (!is_array($classmap)) { + return; + } + + foreach ($classmap as $class => $file) { + preloadFile($file); } } +// Global exclusion patterns (tests, stubs, dev-only files) +$excludePatterns = [ + '#[/\\\\][Tt]ests?[/\\\\]#', + '#[/\\\\][Ss]tubs?[/\\\\]#', + '#[/\\\\][Ff]ixtures?[/\\\\]#', + '#[/\\\\][Mm]ocks?[/\\\\]#', + '#[Tt]est\.php$#', + '#[Ss]tub\.php$#', + '#[Ss]pec\.php$#', + '#phpunit#i', + '#[/\\\\]\.#', // Hidden files/dirs +]; + // ============================================================================= -// 1. LARAVEL CACHED/COMPILED FILES (Most Critical) +// PHASE 1: COMPOSER AUTOLOADER (Load First - Critical) // ============================================================================= -$cachedFiles = [ +// Autoloader must be preloaded first for class resolution +$composerFiles = [ + $basePath . '/vendor/composer/ClassLoader.php', + $basePath . '/vendor/composer/InstalledVersions.php', + $basePath . '/vendor/composer/autoload_real.php', + $basePath . '/vendor/composer/autoload_static.php', + $basePath . '/vendor/composer/autoload_classmap.php', + $basePath . '/vendor/composer/autoload_files.php', + $basePath . '/vendor/composer/autoload_namespaces.php', + $basePath . '/vendor/composer/autoload_psr4.php', + $basePath . '/vendor/autoload.php', +]; + +preloadFiles($composerFiles); + +// Preload entire Composer classmap for maximum performance +if (is_file($basePath . '/vendor/composer/autoload_classmap.php')) { + preloadClassmap($basePath . '/vendor/composer/autoload_classmap.php'); +} + +// ============================================================================= +// PHASE 2: LARAVEL CACHED FILES (High Priority) +// ============================================================================= + +$laravelCacheFiles = [ + // Core cached files $basePath . '/bootstrap/cache/packages.php', $basePath . '/bootstrap/cache/services.php', $basePath . '/bootstrap/cache/config.php', $basePath . '/bootstrap/cache/routes-v7.php', $basePath . '/bootstrap/cache/events.php', + + // Filament cache $basePath . '/bootstrap/cache/filament.php', + $basePath . '/bootstrap/cache/filament/panels.php', + + // Livewire cache $basePath . '/bootstrap/cache/livewire-components.php', + + // Icons cache (Blade Icons) + $basePath . '/bootstrap/cache/blade-icons.php', ]; -preloadFiles($cachedFiles); +preloadFiles($laravelCacheFiles); // ============================================================================= -// 2. COMPOSER AUTOLOADER (Essential for class resolution) +// PHASE 3: PSR INTERFACES (Required for type resolution) // ============================================================================= -preloadFiles([ - $basePath . '/vendor/autoload.php', - $basePath . '/vendor/composer/autoload_real.php', - $basePath . '/vendor/composer/ClassLoader.php', - $basePath . '/vendor/composer/autoload_static.php', -]); +$psrDirs = [ + $basePath . '/vendor/psr/container/src', + $basePath . '/vendor/psr/http-message/src', + $basePath . '/vendor/psr/http-client/src', + $basePath . '/vendor/psr/http-factory/src', + $basePath . '/vendor/psr/log/src', + $basePath . '/vendor/psr/cache/src', + $basePath . '/vendor/psr/simple-cache/src', + $basePath . '/vendor/psr/event-dispatcher/src', + $basePath . '/vendor/psr/clock/src', +]; + +foreach ($psrDirs as $dir) { + preloadDirectory($dir, $excludePatterns); +} // ============================================================================= -// 3. LARAVEL CORE FRAMEWORK +// PHASE 4: SYMFONY COMPONENTS (Laravel's HTTP Foundation) // ============================================================================= -$laravelCoreDirs = [ - // Foundation & Core - $basePath . '/vendor/laravel/framework/src/Illuminate/Foundation', - $basePath . '/vendor/laravel/framework/src/Illuminate/Container', +$symfonyComponents = [ + // HTTP Foundation (most critical) + $basePath . '/vendor/symfony/http-foundation', + + // HTTP Kernel + $basePath . '/vendor/symfony/http-kernel', + + // Routing + $basePath . '/vendor/symfony/routing', + + // Event Dispatcher + $basePath . '/vendor/symfony/event-dispatcher', + $basePath . '/vendor/symfony/event-dispatcher-contracts', + + // Console (for Artisan commands) + $basePath . '/vendor/symfony/console', + + // Error Handler + $basePath . '/vendor/symfony/error-handler', + + // Finder + $basePath . '/vendor/symfony/finder', + + // Process + $basePath . '/vendor/symfony/process', + + // Service Contracts + $basePath . '/vendor/symfony/service-contracts', + + // Translation + $basePath . '/vendor/symfony/translation', + $basePath . '/vendor/symfony/translation-contracts', + + // Var Dumper (for debugging) + $basePath . '/vendor/symfony/var-dumper', + + // Mime + $basePath . '/vendor/symfony/mime', + + // Mailer + $basePath . '/vendor/symfony/mailer', + + // String (Slugger, etc.) + $basePath . '/vendor/symfony/string', + + // UID + $basePath . '/vendor/symfony/uid', + + // Clock + $basePath . '/vendor/symfony/clock', +]; + +foreach ($symfonyComponents as $dir) { + preloadDirectory($dir, $excludePatterns, 10); +} + +// ============================================================================= +// PHASE 5: LARAVEL FRAMEWORK CORE +// ============================================================================= + +$laravelCore = [ + // Contracts (interfaces - load first) $basePath . '/vendor/laravel/framework/src/Illuminate/Contracts', + // Container (DI) + $basePath . '/vendor/laravel/framework/src/Illuminate/Container', + + // Foundation + $basePath . '/vendor/laravel/framework/src/Illuminate/Foundation', + + // Support (helpers, traits, collections) + $basePath . '/vendor/laravel/framework/src/Illuminate/Support', + $basePath . '/vendor/laravel/framework/src/Illuminate/Collections', + $basePath . '/vendor/laravel/framework/src/Illuminate/Conditionable', + $basePath . '/vendor/laravel/framework/src/Illuminate/Macroable', + // HTTP Layer $basePath . '/vendor/laravel/framework/src/Illuminate/Http', $basePath . '/vendor/laravel/framework/src/Illuminate/Routing', $basePath . '/vendor/laravel/framework/src/Illuminate/Pipeline', - // Database & Eloquent + // Database & Eloquent (critical for your app) $basePath . '/vendor/laravel/framework/src/Illuminate/Database', - // Support utilities - $basePath . '/vendor/laravel/framework/src/Illuminate/Support', - $basePath . '/vendor/laravel/framework/src/Illuminate/Collections', - - // Session & Auth + // Auth $basePath . '/vendor/laravel/framework/src/Illuminate/Auth', + + // Session & Cookie $basePath . '/vendor/laravel/framework/src/Illuminate/Session', $basePath . '/vendor/laravel/framework/src/Illuminate/Cookie', + // Cache + $basePath . '/vendor/laravel/framework/src/Illuminate/Cache', + + // Events + $basePath . '/vendor/laravel/framework/src/Illuminate/Events', + + // Queue + $basePath . '/vendor/laravel/framework/src/Illuminate/Queue', + + // Validation + $basePath . '/vendor/laravel/framework/src/Illuminate/Validation', + // Views & Blade $basePath . '/vendor/laravel/framework/src/Illuminate/View', - // Events & Queue - $basePath . '/vendor/laravel/framework/src/Illuminate/Events', - $basePath . '/vendor/laravel/framework/src/Illuminate/Queue', - - // Validation & Cache - $basePath . '/vendor/laravel/framework/src/Illuminate/Validation', - $basePath . '/vendor/laravel/framework/src/Illuminate/Cache', + // Mail + $basePath . '/vendor/laravel/framework/src/Illuminate/Mail', + $basePath . '/vendor/laravel/framework/src/Illuminate/Notifications', // Encryption & Hashing $basePath . '/vendor/laravel/framework/src/Illuminate/Encryption', $basePath . '/vendor/laravel/framework/src/Illuminate/Hashing', + + // Filesystem + $basePath . '/vendor/laravel/framework/src/Illuminate/Filesystem', + + // Console + $basePath . '/vendor/laravel/framework/src/Illuminate/Console', + + // Log + $basePath . '/vendor/laravel/framework/src/Illuminate/Log', + + // Config + $basePath . '/vendor/laravel/framework/src/Illuminate/Config', + + // Translation + $basePath . '/vendor/laravel/framework/src/Illuminate/Translation', + + // Pagination + $basePath . '/vendor/laravel/framework/src/Illuminate/Pagination', + + // Bus (Commands) + $basePath . '/vendor/laravel/framework/src/Illuminate/Bus', + + // Process + $basePath . '/vendor/laravel/framework/src/Illuminate/Process', + + // Concurrency + $basePath . '/vendor/laravel/framework/src/Illuminate/Concurrency', ]; -// Exclude test files and stubs -$excludePatterns = [ - '/[Tt]est[s]?\.php$/', - '/[Ss]tub[s]?\.php$/', - '/[Ff]ixture[s]?/', -]; - -foreach ($laravelCoreDirs as $dir) { +foreach ($laravelCore as $dir) { preloadDirectory($dir, $excludePatterns); } // ============================================================================= -// 4. LIVEWIRE (Critical for your app) +// PHASE 6: LARAVEL OCTANE (High Performance Server) +// ============================================================================= + +preloadDirectory($basePath . '/vendor/laravel/octane/src', $excludePatterns); + +// ============================================================================= +// PHASE 7: LARAVEL PASSPORT (API Authentication) +// ============================================================================= + +preloadDirectory($basePath . '/vendor/laravel/passport/src', $excludePatterns); +preloadDirectory($basePath . '/vendor/league/oauth2-server/src', $excludePatterns); +preloadDirectory($basePath . '/vendor/lcobucci/jwt/src', $excludePatterns); +preloadDirectory($basePath . '/vendor/lcobucci/clock/src', $excludePatterns); + +// ============================================================================= +// PHASE 8: LIVEWIRE 3 // ============================================================================= preloadDirectory($basePath . '/vendor/livewire/livewire/src', $excludePatterns); preloadDirectory($basePath . '/vendor/livewire/volt/src', $excludePatterns); // ============================================================================= -// 5. FILAMENT (Admin Panel - Critical for your app) +// PHASE 9: FILAMENT 3 (Admin Panel) // ============================================================================= -$filamentDirs = [ +$filamentPackages = [ + // Core $basePath . '/vendor/filament/filament/src', $basePath . '/vendor/filament/support/src', + + // Components $basePath . '/vendor/filament/forms/src', $basePath . '/vendor/filament/tables/src', $basePath . '/vendor/filament/actions/src', $basePath . '/vendor/filament/infolists/src', $basePath . '/vendor/filament/notifications/src', $basePath . '/vendor/filament/widgets/src', + + // Spatie integration + $basePath . '/vendor/filament/spatie-laravel-media-library-plugin/src', + $basePath . '/vendor/filament/spatie-laravel-settings-plugin/src', + $basePath . '/vendor/filament/spatie-laravel-tags-plugin/src', + $basePath . '/vendor/filament/spatie-laravel-translatable-plugin/src', ]; -foreach ($filamentDirs as $dir) { +foreach ($filamentPackages as $dir) { preloadDirectory($dir, $excludePatterns); } // ============================================================================= -// 6. COMMON DEPENDENCIES +// PHASE 10: BLADE ICONS (Multiple icon sets you're using) // ============================================================================= -$commonDeps = [ - // Symfony HTTP Foundation - $basePath . '/vendor/symfony/http-foundation/Request.php', - $basePath . '/vendor/symfony/http-foundation/Response.php', - $basePath . '/vendor/symfony/http-foundation/HeaderBag.php', - $basePath . '/vendor/symfony/http-foundation/ParameterBag.php', - $basePath . '/vendor/symfony/http-foundation/InputBag.php', - $basePath . '/vendor/symfony/http-foundation/FileBag.php', - $basePath . '/vendor/symfony/http-foundation/ServerBag.php', - $basePath . '/vendor/symfony/http-foundation/Cookie.php', - $basePath . '/vendor/symfony/http-foundation/Session/Session.php', - - // Symfony HTTP Kernel - $basePath . '/vendor/symfony/http-kernel/HttpKernel.php', - - // PSR Interfaces - $basePath . '/vendor/psr/container/src/ContainerInterface.php', - $basePath . '/vendor/psr/http-message/src/MessageInterface.php', - $basePath . '/vendor/psr/http-message/src/RequestInterface.php', - $basePath . '/vendor/psr/http-message/src/ResponseInterface.php', - $basePath . '/vendor/psr/log/src/LoggerInterface.php', - - // Carbon (Date handling) - $basePath . '/vendor/nesbot/carbon/src/Carbon/Carbon.php', - $basePath . '/vendor/nesbot/carbon/src/Carbon/CarbonInterface.php', - $basePath . '/vendor/nesbot/carbon/src/Carbon/CarbonImmutable.php', +$bladeIconPackages = [ + $basePath . '/vendor/blade-ui-kit/blade-icons/src', + $basePath . '/vendor/blade-ui-kit/blade-heroicons/src', + $basePath . '/vendor/andreiio/blade-remix-icon/src', + $basePath . '/vendor/codeat3/blade-coolicons/src', + $basePath . '/vendor/codeat3/blade-devicons/src', + $basePath . '/vendor/codeat3/blade-file-icons/src', + $basePath . '/vendor/codeat3/blade-vaadin-icons/src', + $basePath . '/vendor/faisal50x/blade-ionicons/src', + $basePath . '/vendor/postare/blade-mdi/src', ]; -preloadFiles($commonDeps); +foreach ($bladeIconPackages as $dir) { + preloadDirectory($dir, $excludePatterns); +} // ============================================================================= -// 7. APPLICATION CODE (Your code) +// PHASE 11: SPATIE PACKAGES // ============================================================================= -$appDirs = [ - // Models (Most frequently accessed) - $basePath . '/app/Models', - +$spatiePackages = [ + $basePath . '/vendor/spatie/laravel-cookie-consent/src', + $basePath . '/vendor/spatie/laravel-query-builder/src', + $basePath . '/vendor/spatie/laravel-package-tools/src', +]; + +foreach ($spatiePackages as $dir) { + preloadDirectory($dir, $excludePatterns); +} + +// ============================================================================= +// PHASE 12: OTHER CRITICAL DEPENDENCIES +// ============================================================================= + +// Carbon (DateTime handling) +preloadDirectory($basePath . '/vendor/nesbot/carbon/src', $excludePatterns); + +// Monolog (Logging) +preloadDirectory($basePath . '/vendor/monolog/monolog/src', $excludePatterns); + +// Flysystem (File storage) +preloadDirectory($basePath . '/vendor/league/flysystem/src', $excludePatterns); +preloadDirectory($basePath . '/vendor/league/flysystem-local/src', $excludePatterns); + +// Guzzle HTTP (API calls) +preloadDirectory($basePath . '/vendor/guzzlehttp/guzzle/src', $excludePatterns); +preloadDirectory($basePath . '/vendor/guzzlehttp/psr7/src', $excludePatterns); +preloadDirectory($basePath . '/vendor/guzzlehttp/promises/src', $excludePatterns); + +// DomPDF (PDF generation) +preloadDirectory($basePath . '/vendor/barryvdh/laravel-dompdf/src', $excludePatterns); +preloadDirectory($basePath . '/vendor/dompdf/dompdf/src', $excludePatterns); + +// QR Code +preloadDirectory($basePath . '/vendor/endroid/qr-code/src', $excludePatterns); + +// Two Factor Auth +preloadFile($basePath . '/vendor/robthree/twofactorauth/lib/TwoFactorAuth.php'); +preloadDirectory($basePath . '/vendor/robthree/twofactorauth/lib', $excludePatterns); + +// Laravel Socialite (Social auth) +preloadDirectory($basePath . '/vendor/laravel/socialite/src', $excludePatterns); +preloadDirectory($basePath . '/vendor/socialiteproviders/discord/src', $excludePatterns); +preloadDirectory($basePath . '/vendor/socialiteproviders/manager/src', $excludePatterns); + +// ApexCharts +preloadDirectory($basePath . '/vendor/akaunting/laravel-apexcharts/src', $excludePatterns); + +// Laravel Trend +preloadDirectory($basePath . '/vendor/flowframe/laravel-trend/src', $excludePatterns); + +// Laravel Themer +preloadDirectory($basePath . '/vendor/qirolab/laravel-themer/src', $excludePatterns); + +// JSON API +preloadDirectory($basePath . '/vendor/timacdonald/json-api/src', $excludePatterns); + +// Cookie Consent +preloadDirectory($basePath . '/vendor/whitecube/laravel-cookie-consent/src', $excludePatterns); + +// Ramsey UUID +preloadDirectory($basePath . '/vendor/ramsey/uuid/src', $excludePatterns); +preloadDirectory($basePath . '/vendor/ramsey/collection/src', $excludePatterns); + +// Doctrine (DBAL for migrations, Inflector for pluralization) +preloadDirectory($basePath . '/vendor/doctrine/inflector/lib', $excludePatterns); +preloadDirectory($basePath . '/vendor/doctrine/lexer/src', $excludePatterns); + +// Vite manifest helper +preloadDirectory($basePath . '/vendor/laravel/framework/src/Illuminate/Foundation/Vite', $excludePatterns); + +// ============================================================================= +// PHASE 13: APPLICATION CODE (Your Code - Highest Priority) +// ============================================================================= + +// Models (most frequently accessed) +$modelFiles = [ + $basePath . '/app/Models/User.php', + $basePath . '/app/Models/Service.php', + $basePath . '/app/Models/Product.php', + $basePath . '/app/Models/Invoice.php', + $basePath . '/app/Models/InvoiceItem.php', + $basePath . '/app/Models/InvoiceTransaction.php', + $basePath . '/app/Models/Order.php', + $basePath . '/app/Models/Ticket.php', + $basePath . '/app/Models/TicketMessage.php', + $basePath . '/app/Models/Gateway.php', + $basePath . '/app/Models/Server.php', + $basePath . '/app/Models/Category.php', + $basePath . '/app/Models/Price.php', + $basePath . '/app/Models/Plan.php', + $basePath . '/app/Models/ConfigOption.php', + $basePath . '/app/Models/Coupon.php', + $basePath . '/app/Models/Property.php', + $basePath . '/app/Models/Extension.php', + $basePath . '/app/Models/Currency.php', + $basePath . '/app/Models/Setting.php', + $basePath . '/app/Models/Session.php', + $basePath . '/app/Models/Role.php', + $basePath . '/app/Models/ServiceConfig.php', + $basePath . '/app/Models/ServiceCancellation.php', + $basePath . '/app/Models/ServiceUpgrade.php', + $basePath . '/app/Models/TaxRate.php', + $basePath . '/app/Models/EmailTemplate.php', + $basePath . '/app/Models/Credit.php', + $basePath . '/app/Models/ApiKey.php', + $basePath . '/app/Models/AuditLog.php', +]; + +preloadFiles($modelFiles); + +// Preload remaining models +preloadDirectory($basePath . '/app/Models', $excludePatterns); + +// Core application directories +$appDirectories = [ // HTTP Layer $basePath . '/app/Http/Controllers', $basePath . '/app/Http/Middleware', $basePath . '/app/Http/Requests', - // Livewire Components + // Livewire Components (critical for UI) $basePath . '/app/Livewire', - // Filament Admin + // Filament Admin Panel $basePath . '/app/Admin/Resources', $basePath . '/app/Admin/Pages', $basePath . '/app/Admin/Widgets', + $basePath . '/app/Admin/Components', + $basePath . '/app/Admin/Actions', + $basePath . '/app/Admin/Clusters', // Service Providers $basePath . '/app/Providers', - // Jobs & Events + // Background Jobs $basePath . '/app/Jobs', + + // Events & Listeners $basePath . '/app/Events', $basePath . '/app/Listeners', - // Helpers & Classes + // Observers + $basePath . '/app/Observers', + + // Policies + $basePath . '/app/Policies', + + // Classes & Helpers $basePath . '/app/Classes', $basePath . '/app/Helpers', + $basePath . '/app/Support', $basePath . '/app/Traits', - // Policies & Rules - $basePath . '/app/Policies', + // Validation Rules $basePath . '/app/Rules', + + // Mail + $basePath . '/app/Mail', + + // View Components + $basePath . '/app/View', + + // Attributes + $basePath . '/app/Attributes', + + // Exceptions + $basePath . '/app/Exceptions', + + // Console Commands + $basePath . '/app/Console/Commands', ]; -foreach ($appDirs as $dir) { - preloadDirectory($dir); +foreach ($appDirectories as $dir) { + preloadDirectory($dir, $excludePatterns); } // ============================================================================= -// 8. BLADE COMPILED VIEWS (if using view caching) +// PHASE 14: EXTENSIONS (Payment Gateways, Servers, etc.) +// ============================================================================= + +$extensionDirs = [ + $basePath . '/extensions/Gateways', + $basePath . '/extensions/Servers', + $basePath . '/extensions/Others', +]; + +foreach ($extensionDirs as $dir) { + preloadDirectory($dir, $excludePatterns); +} + +// ============================================================================= +// PHASE 15: THEMES +// ============================================================================= + +preloadDirectory($basePath . '/themes/lucentui', $excludePatterns); + +// ============================================================================= +// PHASE 16: COMPILED BLADE VIEWS (Most Recent) // ============================================================================= -// Only preload if compiled views exist and are recent $compiledViewsPath = $basePath . '/storage/framework/views'; if (is_dir($compiledViewsPath)) { - // Limit to most recently modified compiled views (top 200) $viewFiles = glob($compiledViewsPath . '/*.php'); if ($viewFiles) { // Sort by modification time, newest first - usort($viewFiles, fn($a, $b) => filemtime($b) - filemtime($a)); - $viewFiles = array_slice($viewFiles, 0, 200); + usort($viewFiles, static fn($a, $b) => filemtime($b) <=> filemtime($a)); + // Preload top 500 most recently used views + $viewFiles = array_slice($viewFiles, 0, 500); preloadFiles($viewFiles); } } // ============================================================================= -// SUMMARY (logged to error_log for debugging) +// PHASE 17: CONFIG FILES // ============================================================================= -if (php_sapi_name() === 'cli') { - echo "OPcache Preload Complete: {$preloadedCount} files preloaded, {$skippedCount} skipped\n"; - echo "Memory usage: " . round(memory_get_usage(true) / 1024 / 1024, 2) . " MB\n"; +preloadDirectory($basePath . '/config', $excludePatterns); +preloadFile($basePath . '/bootstrap/app.php'); +preloadFile($basePath . '/bootstrap/providers.php'); + +// ============================================================================= +// PRELOAD SUMMARY & LOGGING +// ============================================================================= + +$stats['end_time'] = hrtime(true); +$stats['end_memory'] = memory_get_usage(true); + +$duration = round(($stats['end_time'] - $stats['start_time']) / 1e6, 2); // ms +$memoryUsed = round(($stats['end_memory'] - $stats['start_memory']) / 1024 / 1024, 2); // MB +$totalMemory = round($stats['end_memory'] / 1024 / 1024, 2); // MB + +$summary = sprintf( + 'OPcache Preload: %d files preloaded, %d skipped in %.2fms (Memory: %.2fMB used, %.2fMB total)', + $stats['preloaded'], + $stats['skipped'], + $duration, + $memoryUsed, + $totalMemory +); + +// Log summary +if (PHP_SAPI === 'cli') { + echo $summary . PHP_EOL; + + if (!empty($stats['errors'])) { + echo "Errors (" . count($stats['errors']) . "):\n"; + foreach (array_slice($stats['errors'], 0, 10) as $error) { + echo " - {$error}\n"; + } + if (count($stats['errors']) > 10) { + echo " ... and " . (count($stats['errors']) - 10) . " more errors\n"; + } + } + + // Show OPcache status + if (function_exists('opcache_get_status')) { + $status = opcache_get_status(false); + if ($status) { + echo sprintf( + "OPcache Status: %d cached scripts, %.2fMB memory used, %.2f%% hit rate\n", + $status['opcache_statistics']['num_cached_scripts'] ?? 0, + ($status['memory_usage']['used_memory'] ?? 0) / 1024 / 1024, + $status['opcache_statistics']['opcache_hit_rate'] ?? 0 + ); + } + } } else { - error_log("OPcache Preload: {$preloadedCount} files preloaded, {$skippedCount} skipped"); + error_log($summary); } + +// Force garbage collection to free memory +gc_collect_cycles();