From 077faf56ae6e426f14e0cc0f2b3399364f6df357 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 20 Mar 2026 06:59:20 +0000 Subject: [PATCH] perf: cache configSearch filesystem walks in getStandard() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When phpcbf.configSearch is true, getStandard() previously called findFiles() on every format operation — a walk-up-the-directory-tree search that calls fs.existsSync() for each of the 6 config file names at every directory level between the document and the workspace root. For a file three levels deep this is ~18 syscalls per Ctrl+S. Add a Map cache keyed by 'workspaceRoot\0fileDir' so the walk only happens once per directory per session. The cache is cleared via clearConfigCache() whenever onDidChangeConfiguration fires, so users who add or remove a phpcs.xml mid-session will get fresh results after any phpcbf configuration change (or a Reload Window). No behaviour change for configSearch: false (the existing code path is unchanged). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- extension.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/extension.js b/extension.js index 6457e71..5ca4530 100644 --- a/extension.js +++ b/extension.js @@ -17,9 +17,16 @@ const TmpDir = os.tmpdir(); class PHPCBF { constructor() { + // Cache configSearch results keyed by "workspaceRoot\0fileDir" to avoid + // repeated filesystem walks (fs.existsSync calls) on every format operation. + this._configCache = new Map(); this.loadSettings(); } + clearConfigCache() { + this._configCache.clear(); + } + loadSettings(uri) { // Use the provided URI (e.g. the document being formatted), fall back to // the active editor, or null (global settings) if neither is available. @@ -117,7 +124,18 @@ class PHPCBF { ]; const fileDir = path.relative(workspaceRoot, path.dirname(filePath)); - const confFile = findFiles(workspaceRoot, fileDir, confFileNames); + + // Avoid repeated filesystem walks for the same directory. + // The cache maps "workspaceRoot\0fileDir" -> absolute config path (or null). + // It is cleared whenever phpcbf configuration changes. + const cacheKey = workspaceRoot + "\0" + fileDir; + let confFile; + if (this._configCache.has(cacheKey)) { + confFile = this._configCache.get(cacheKey); + } else { + confFile = findFiles(workspaceRoot, fileDir, confFileNames); + this._configCache.set(cacheKey, confFile); + } standard = confFile || this.standard; } else { @@ -287,6 +305,7 @@ exports.activate = context => { context.subscriptions.push( workspace.onDidChangeConfiguration(() => { + phpcbf.clearConfigCache(); phpcbf.loadSettings(); }) );