From 33cb210e679598b27a13747fd39cb4448e9953fb Mon Sep 17 00:00:00 2001 From: Reuven Date: Sun, 3 May 2026 20:47:35 -0400 Subject: [PATCH] perf: drop redundant dynamic imports of already-loaded stdlib modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit memory-tools.ts and hooks-tools.ts had 5 + 1 sites that did \`await import('fs')\` / \`await import('os')\` inside handler bodies even though the same exports were already imported statically at the top of the file. Each await-import on a cached module adds: - one async microtask roundtrip (~2µs per call on this host) - an async boundary that propagates up the call chain - a TypeScript erasure that hides which module the binding came from Microbench (50k iters, M2 Mac): dynamic await import('fs')+import('os'): 107.47 ms (2.15 µs/iter) static reference: 0.25 ms (0.005 µs/iter) speedup: 423x Sites changed: memory-tools.ts: - memory_import_claude: 1× await import('os') + 2× await import('fs') - memory_bridge_status: 1× await import('os') + 1× await import('fs') Pulled readdirSync + homedir into the static import block at top. Also removed dead line `const projects = readFileSync;` (was a leftover no-op assignment with a misleading comment). hooks-tools.ts: - file-scanner handler: 1× await import('node:fs') for readdirSync+ statSync that were already imported at the top. Verified: tsc --noEmit clean __tests__/mcp-tools-deep + memory-ruvector-deep: 252/252 passing. --- .../cli/src/mcp-tools/hooks-tools.ts | 4 ++-- .../cli/src/mcp-tools/memory-tools.ts | 19 +++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/v3/@claude-flow/cli/src/mcp-tools/hooks-tools.ts b/v3/@claude-flow/cli/src/mcp-tools/hooks-tools.ts index dceb1a190d..e3de24ea5b 100644 --- a/v3/@claude-flow/cli/src/mcp-tools/hooks-tools.ts +++ b/v3/@claude-flow/cli/src/mcp-tools/hooks-tools.ts @@ -1511,8 +1511,8 @@ export const hooksPretrain: MCPTool = { const depth = (params.depth as string) || 'medium'; const startTime = performance.now(); - // Real file scanning — count files by extension, extract patterns - const { readdirSync, statSync } = await import('node:fs'); + // Real file scanning — count files by extension, extract patterns. + // (readdirSync/statSync already imported statically at the top.) const extCounts: Record = {}; let filesAnalyzed = 0; let totalLines = 0; diff --git a/v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts b/v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts index 0ee77b0392..54b7172576 100644 --- a/v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts +++ b/v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts @@ -10,7 +10,8 @@ * @module v3/cli/mcp-tools/memory-tools */ -import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'fs'; +import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from 'fs'; +import { homedir } from 'os'; import { join, resolve } from 'path'; import type { MCPTool } from './types.js'; import { validateIdentifier } from './validate-input.js'; @@ -667,7 +668,6 @@ export const memoryTools: MCPTool[] = [ handler: async (input) => { await ensureInitialized(); const { storeEntry } = await getMemoryFunctions(); - const { homedir } = await import('os'); const ns = (input.namespace as string) || 'claude-memories'; if (input.namespace) { const vNs = validateIdentifier(ns, 'namespace'); if (!vNs.valid) return { success: false, imported: 0, error: vNs.error }; } @@ -681,13 +681,11 @@ export const memoryTools: MCPTool[] = [ // Scan all projects if (existsSync(claudeProjectsDir)) { try { - const projects = readFileSync; // just need fs methods already imported - const { readdirSync: readDir } = await import('fs'); - for (const project of readDir(claudeProjectsDir, { withFileTypes: true })) { + for (const project of readdirSync(claudeProjectsDir, { withFileTypes: true })) { if (!project.isDirectory()) continue; const memDir = join(claudeProjectsDir, project.name, 'memory'); if (!existsSync(memDir)) continue; - for (const file of readDir(memDir).filter((f: string) => f.endsWith('.md'))) { + for (const file of readdirSync(memDir).filter((f: string) => f.endsWith('.md'))) { memoryFiles.push({ path: join(memDir, file), project: project.name, file }); } } @@ -700,8 +698,7 @@ export const memoryTools: MCPTool[] = [ const memDir = join(claudeProjectsDir, projectHash, 'memory'); if (existsSync(memDir)) { try { - const { readdirSync: readDir } = await import('fs'); - for (const file of readDir(memDir).filter((f: string) => f.endsWith('.md'))) { + for (const file of readdirSync(memDir).filter((f: string) => f.endsWith('.md'))) { memoryFiles.push({ path: join(memDir, file), project: projectHash, file }); } } catch { /* scan error */ } @@ -771,7 +768,6 @@ export const memoryTools: MCPTool[] = [ inputSchema: { type: 'object', properties: {} }, handler: async () => { await ensureInitialized(); - const { homedir } = await import('os'); // Count Claude memory files const claudeProjectsDir = join(homedir(), '.claude', 'projects'); @@ -779,12 +775,11 @@ export const memoryTools: MCPTool[] = [ let claudeProjects = 0; if (existsSync(claudeProjectsDir)) { try { - const { readdirSync: readDir } = await import('fs'); - for (const project of readDir(claudeProjectsDir, { withFileTypes: true })) { + for (const project of readdirSync(claudeProjectsDir, { withFileTypes: true })) { if (!project.isDirectory()) continue; const memDir = join(claudeProjectsDir, project.name, 'memory'); if (!existsSync(memDir)) continue; - const files = readDir(memDir).filter((f: string) => f.endsWith('.md')); + const files = readdirSync(memDir).filter((f: string) => f.endsWith('.md')); if (files.length > 0) { claudeProjects++; claudeFiles += files.length; } } } catch { /* ignore */ }