diff --git a/src/tsc/tsc.ts b/src/tsc/tsc.ts index d396607126502..557957af2fc96 100644 --- a/src/tsc/tsc.ts +++ b/src/tsc/tsc.ts @@ -218,8 +218,42 @@ namespace ts { return builder.buildAllProjects(); } + function cachePerfMarkNames(cacheName: string) { + return { + misses: `${cacheName} cache misses`, + hits: `${cacheName} cache hits`, + }; + } + + function addCache(func: (arg: string) => T, perfName: string) { + const cache = createMap(); + const perfNames = cachePerfMarkNames(perfName); + return (arg: string) => { + let result = cache.get(arg); + if (result !== undefined) { + performance.mark(perfNames.hits); + return result; + } + + performance.mark(perfNames.misses); + + result = func(arg); + cache.set(arg, result); + return result; + }; + } + + function addCachesToHost(host: CompilerHost) { + host.fileExists = addCache(host.fileExists, "fileExists"); + + if (host.directoryExists !== undefined) { + host.directoryExists = addCache(host.directoryExists, "directoryExists"); + } + } + function performCompilation(rootNames: string[], projectReferences: ReadonlyArray | undefined, options: CompilerOptions, configFileParsingDiagnostics?: ReadonlyArray) { const host = createCompilerHost(options); + addCachesToHost(host); enableStatistics(options); const programOptions: CreateProgramOptions = { @@ -297,6 +331,15 @@ namespace ts { const emitTime = performance.getDuration("Emit"); if (compilerOptions.extendedDiagnostics) { performance.forEachMeasure((name, duration) => reportTimeStatistic(`${name} time`, duration)); + + forEach([ + "fileExists", + "directoryExists" + ], (cacheName: string) => { + const fileExistCacheNames = cachePerfMarkNames(cacheName); + reportCountStatistic(`${fileExistCacheNames.hits} count`, performance.getCount(fileExistCacheNames.hits)); + reportCountStatistic(`${fileExistCacheNames.misses} count`, performance.getCount(fileExistCacheNames.misses)); + }); } else { // Individual component times.