From f099ca84026ba2805c87acda7204abb3f7ca5921 Mon Sep 17 00:00:00 2001 From: whwyy Date: Wed, 24 Jun 2026 20:17:55 +0800 Subject: [PATCH] eee --- src/Router.php | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/Router.php b/src/Router.php index e2fc88d..c06af18 100644 --- a/src/Router.php +++ b/src/Router.php @@ -39,6 +39,14 @@ class Router private static ?string $currentSourceFile = null; + /** + * 标记首次完整扫描是否已完成 + * Master 进程中完成扫描后设为 true,Worker 通过 fork 继承此标记 + * Worker 启动时检查此标记,避免重复执行全量 app 目录扫描导致 OOM + * @var bool + */ + private static bool $initialScanDone = false; + /** * @param string $name @@ -186,6 +194,17 @@ class Router /** + * 扫描并构建路由表 + * + * Master 进程:执行完整扫描(路由文件加载 + app 目录扫描 + DeferRegistry 注入) + * Worker 进程(首次启动):仅加载路由文件注册路由表,跳过全量 app 扫描 + * Worker 进程(热重载):检测到文件变更时执行完整扫描流程 + * + * 设计原因: + * - Master 已完成类加载和字节码编译,Worker 通过 fork 继承全部内存 + * - Worker 重复执行 opcache_compile_file + invalidateClasses 不产生新信息 + * - 在应用文件较多时(500+),每个 Worker 的全量扫描会消耗数百 MB 内存导致 OOM + * * @throws */ public function scan_build_route(): void @@ -193,7 +212,21 @@ class Router $coordinator = CoordinatorManager::utility(Coordinator::WORKER_START); $container = Kiri::getDi(); $container->get(DataGrip::class)->reset(static::$type); - $scanner = $container->get(Kiri\Di\Scanner::class); + + $changedFiles = $container->get(HotReloadState::class)->consume(); + + // Worker 首次启动(无变更文件 + Master 已完成扫描):仅加载路由,跳过全量 app 扫描 + if (empty($changedFiles) && self::$initialScanDone) { + $this->read_dir_file(APP_PATH . 'routes'); + $this->reset($container); + $coordinator->done(); + return; + } + + // 标记首次扫描完成(Master 首次启动或 Worker 热重载时执行到此) + self::$initialScanDone = true; + + $scanner = $container->get(Kiri\Di\Scanner::class); $artifactState = $container->get(RouteArtifactState::class); $scanConfig = array_merge( config('servers.reload.scan', []), @@ -201,7 +234,6 @@ class Router ); $scanner->setConfig($scanConfig); - $changedFiles = $container->get(HotReloadState::class)->consume(); $normalizedAppPath = str_replace('\\', '/', APP_PATH . 'app'); $normalizedRoutePath = str_replace('\\', '/', APP_PATH . 'routes'); $routeChanged = false;