From 056b25244a87a05259800393367d0a36501a701e Mon Sep 17 00:00:00 2001 From: gonzaloriestra <14979109+gonzaloriestra@users.noreply.github.com> Date: Sun, 5 Jul 2026 00:35:20 +0000 Subject: [PATCH] [Performance] Memoize isStdinPiped in cli-kit Memoize the `isStdinPiped` function in `packages/cli-kit/src/public/node/system.ts` to avoid redundant synchronous `fstatSync(0)` calls. The piping status of stdin is constant for the duration of the process. Added an exported `_resetIsStdinPipedCache` utility for test isolation and updated `system.test.ts` to verify memoization. Expected impact: Reduces CPU time by skipping redundant syscalls in high-frequency paths or utility functions that depend on stdin status. --- .../cli-kit/src/public/node/system.test.ts | 19 +++++++++++++++- packages/cli-kit/src/public/node/system.ts | 22 +++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/cli-kit/src/public/node/system.test.ts b/packages/cli-kit/src/public/node/system.test.ts index ed12516ba40..2a080b7ff1e 100644 --- a/packages/cli-kit/src/public/node/system.test.ts +++ b/packages/cli-kit/src/public/node/system.test.ts @@ -1,6 +1,7 @@ import * as system from './system.js' +import {_resetIsStdinPipedCache} from './system.js' import {execa} from 'execa' -import {describe, expect, test, vi} from 'vitest' +import {beforeEach, describe, expect, test, vi} from 'vitest' import which from 'which' import {Readable} from 'stream' @@ -16,6 +17,10 @@ vi.mock('fs', async (importOriginal) => { } }) +beforeEach(() => { + _resetIsStdinPipedCache() +}) + describe('captureOutput', () => { test('runs the command when it is not found in the current directory', async () => { // Given @@ -351,6 +356,18 @@ describe('isStdinPiped', () => { // Then expect(got).toBe(false) }) + + test('memoizes the result', () => { + // Given + vi.mocked(fs.fstatSync).mockReturnValue({isFIFO: () => true, isFile: () => false} as fs.Stats) + + // When + system.isStdinPiped() + system.isStdinPiped() + + // Then + expect(fs.fstatSync).toHaveBeenCalledTimes(1) + }) }) describe('readStdinString', () => { diff --git a/packages/cli-kit/src/public/node/system.ts b/packages/cli-kit/src/public/node/system.ts index 3f449f8ff34..3b84c7fe2b4 100644 --- a/packages/cli-kit/src/public/node/system.ts +++ b/packages/cli-kit/src/public/node/system.ts @@ -364,6 +364,19 @@ export async function isWsl(): Promise { return wsl.default } +/** + * Memoized value for the stdin piped check. + */ +let memoizedIsStdinPiped: boolean | undefined + +/** + * Reset the memoized value for the stdin piped check. + * This is only used for testing. + */ +export function _resetIsStdinPipedCache(): void { + memoizedIsStdinPiped = undefined +} + /** * Check if stdin has piped data available. * This distinguishes between actual piped input (e.g., `echo "query" | cmd`) @@ -372,13 +385,18 @@ export async function isWsl(): Promise { * @returns True if stdin is receiving piped data or file redirect, false otherwise. */ export function isStdinPiped(): boolean { + if (memoizedIsStdinPiped !== undefined) { + return memoizedIsStdinPiped + } + try { const stats = fstatSync(0) - return stats.isFIFO() || stats.isFile() + memoizedIsStdinPiped = stats.isFIFO() || stats.isFile() // eslint-disable-next-line no-catch-all/no-catch-all } catch { - return false + memoizedIsStdinPiped = false } + return memoizedIsStdinPiped } /**