From 94e2aee71d3dfd2e0c319180c0ebc62e394a3a1b Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Sun, 20 Sep 2026 10:37:15 +0800 Subject: [PATCH] feat(build): add anonymous opcode caching mechanism - Implemented anonymous file detection and separate cache directory handling - Added SHA256-based cache key generation for anonymous opcodes - Created dedicated cache directories for anonymous files with build signature - Added force clear functionality for anonymous opcode caches - Updated cache hit tracking to distinguish between vendor and anonymous files - Added progress output for anonymous opcode cache statistics - Integrated anonymous file processing into existing opcode pipeline flow --- src/Build/SourcePipelineTrait.php | 33 +++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/Build/SourcePipelineTrait.php b/src/Build/SourcePipelineTrait.php index 4818f328..dfdcdd3c 100644 --- a/src/Build/SourcePipelineTrait.php +++ b/src/Build/SourcePipelineTrait.php @@ -381,8 +381,25 @@ trait SourcePipelineTrait $otherFiles = []; $vendorRoots = []; $vendorFiles = []; + $anonymousFiles = []; $fileCacheDirs = []; foreach ($files as $file) { + if (isset($this->anonymousOpcodeKeys[$file])) { + // These files are emitted by this compiler, so their exact + // contents provide a safe cache key independent of any + // user-supplied directory timestamp. + $key = hash('sha256', implode("\n", [ + 'anonymous-opcodes-v1', $file, + hash_file('sha256', $file), $this->opcodeBuildSignature, + ])); + $cacheDir = $this->getBuildDir() . '/cache/opcache/anonymous-' . substr($key, 0, 20); + if ($this->climate->arguments->defined('force')) { + $this->clearOpcodeCacheDirectory($cacheDir); + } + $fileCacheDirs[$file] = $cacheDir; + $anonymousFiles[$file] = true; + continue; + } $vendorRoot = $this->vendorRootForOpcodeFile($file); if ($vendorRoot === null) { $otherFiles[] = $file; @@ -446,12 +463,17 @@ PHP // function names do not conflict while creating their bytecode. $pending = []; $vendorHits = 0; + $anonymousHits = 0; foreach ($files as $file) { $cacheDir = $fileCacheDirs[$file]; - if (isset($vendorFiles[$file]) + if ((isset($vendorFiles[$file]) || isset($anonymousFiles[$file])) && ($blob = $this->findOpcodeBlob($cacheDir, $file)) !== null) { $blobs[$file] = $blob; - ++$vendorHits; + if (isset($anonymousFiles[$file])) { + ++$anonymousHits; + } else { + ++$vendorHits; + } } else { $pending[] = $file; } @@ -464,6 +486,13 @@ PHP 'lightBlue', ); } + if ($anonymousFiles !== []) { + $this->output( + 'Anonymous opcode cache: ' . $anonymousHits . ' reused, ' + . (count($anonymousFiles) - $anonymousHits) . ' to generate', + 'lightBlue', + ); + } $progress = $this->startOpcodeProgress('Opcodes', count($pending)); $completed = 0; foreach ($pending as $file) {