perf: fix synchronous I/O in hot paths (#540)

Replace existsSync collision loop with atomic O_CREAT|O_EXCL file
creation, hoist regex to module-level constant, and memoize
getPackageDir() to avoid repeated directory walks.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
TÂCHES 2026-03-15 16:57:22 -06:00 committed by GitHub
parent a43836ffbb
commit bc4d4fcf48
2 changed files with 28 additions and 13 deletions

View file

@ -77,29 +77,33 @@ export function getUpdateInstruction(packageName: string): string {
* - For Node.js (dist/): returns __dirname (the dist/ directory)
* - For tsx (src/): returns parent directory (the package root)
*/
let _cachedPackageDir: string | undefined;
export function getPackageDir(): string {
if (_cachedPackageDir !== undefined) return _cachedPackageDir;
// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)
const envDir = process.env.PI_PACKAGE_DIR;
if (envDir) {
if (envDir === "~") return homedir();
if (envDir.startsWith("~/")) return homedir() + envDir.slice(1);
return envDir;
if (envDir === "~") return (_cachedPackageDir = homedir());
if (envDir.startsWith("~/")) return (_cachedPackageDir = homedir() + envDir.slice(1));
return (_cachedPackageDir = envDir);
}
if (isBunBinary) {
// Bun binary: process.execPath points to the compiled executable
return dirname(process.execPath);
return (_cachedPackageDir = dirname(process.execPath));
}
// Node.js: walk up from __dirname until we find package.json
let dir = __dirname;
while (dir !== dirname(dir)) {
if (existsSync(join(dir, "package.json"))) {
return dir;
return (_cachedPackageDir = dir);
}
dir = dirname(dir);
}
// Fallback (shouldn't happen)
return __dirname;
return (_cachedPackageDir = __dirname);
}
/**

View file

@ -8,10 +8,11 @@
* Diagnostic extraction is handled by session-forensics.ts.
*/
import { writeFileSync, mkdirSync, readdirSync, unlinkSync, statSync } from "node:fs";
import { existsSync } from "node:fs";
import { writeFileSync, mkdirSync, readdirSync, unlinkSync, statSync, openSync, closeSync, constants } from "node:fs";
import { createHash } from "node:crypto";
import { join } from "node:path";
const SEQ_PREFIX_RE = /^(\d+)-/;
import type { ExtensionContext } from "@gsd/pi-coding-agent";
import { gsdRoot } from "./paths.js";
@ -26,7 +27,7 @@ function scanNextSequence(activityDir: string): number {
let maxSeq = 0;
try {
for (const f of readdirSync(activityDir)) {
const match = f.match(/^(\d+)-/);
const match = f.match(SEQ_PREFIX_RE);
if (match) maxSeq = Math.max(maxSeq, parseInt(match[1], 10));
}
} catch {
@ -55,14 +56,24 @@ function nextActivityFilePath(
unitType: string,
safeUnitId: string,
): string {
while (true) {
// Use O_CREAT | O_EXCL for atomic "create if absent" — no directory scan needed.
for (let attempts = 0; attempts < 1000; attempts++) {
const seq = String(state.nextSeq).padStart(3, "0");
const filePath = join(activityDir, `${seq}-${unitType}-${safeUnitId}.jsonl`);
if (!existsSync(filePath)) {
try {
const fd = openSync(filePath, constants.O_CREAT | constants.O_EXCL | constants.O_WRONLY);
closeSync(fd);
return filePath;
} catch (err: any) {
if (err?.code === "EEXIST") {
state.nextSeq++;
continue;
}
throw err;
}
state.nextSeq = scanNextSequence(activityDir);
}
// Fallback: should never reach here in practice
throw new Error(`Failed to find available activity log sequence in ${activityDir}`);
}
export function saveActivityLog(
@ -99,7 +110,7 @@ export function pruneActivityLogs(activityDir: string, retentionDays: number): v
const files = readdirSync(activityDir);
const entries: { seq: number; filePath: string }[] = [];
for (const f of files) {
const match = f.match(/^(\d+)-/);
const match = f.match(SEQ_PREFIX_RE);
if (match) entries.push({ seq: parseInt(match[1], 10), filePath: join(activityDir, f) });
}
if (entries.length === 0) return;