diff --git a/src/compiler/performance.ts b/src/compiler/performance.ts index 1605fa5e3562a..40b333041e636 100644 --- a/src/compiler/performance.ts +++ b/src/compiler/performance.ts @@ -180,7 +180,7 @@ export function enable(system: System = sys) { if (!enabled) { enabled = true; perfHooks ||= tryGetNativePerformanceHooks(); - if (perfHooks) { + if (perfHooks?.performance) { timeorigin = perfHooks.performance.timeOrigin; // NodeJS's Web Performance API is currently slower than expected, but we'd still like // to be able to leverage native trace events when node is run with either `--cpu-prof` diff --git a/src/compiler/performanceCore.ts b/src/compiler/performanceCore.ts index a214ced47ef2c..e788836d11866 100644 --- a/src/compiler/performanceCore.ts +++ b/src/compiler/performanceCore.ts @@ -7,104 +7,86 @@ import { /** @internal */ export interface PerformanceHooks { - /** Indicates whether we should write native performance events */ shouldWriteNativeEvents: boolean; - performance: Performance; - PerformanceObserver: PerformanceObserverConstructor; + performance?: Performance; + performanceTime?: PerformanceTime; } /** @internal */ -export interface Performance { - mark(name: string): void; - measure(name: string, startMark?: string, endMark?: string): void; - clearMeasures(name?: string): void; - clearMarks(name?: string): void; +export interface PerformanceTime { now(): number; timeOrigin: number; } /** @internal */ -export interface PerformanceEntry { - name: string; - entryType: string; - startTime: number; - duration: number; -} - -/** @internal */ -export interface PerformanceObserverEntryList { - getEntries(): PerformanceEntryList; - getEntriesByName(name: string, type?: string): PerformanceEntryList; - getEntriesByType(type: string): PerformanceEntryList; -} - -/** @internal */ -export interface PerformanceObserver { - disconnect(): void; - observe(options: { entryTypes: readonly ("mark" | "measure")[]; }): void; +export interface Performance extends PerformanceTime { + mark(name: string): void; + measure(name: string, startMark?: string, endMark?: string): void; + clearMeasures(name?: string): void; + clearMarks(name?: string): void; } -/** @internal */ -export type PerformanceObserverConstructor = new (callback: (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void) => PerformanceObserver; -/** @internal */ -export type PerformanceEntryList = PerformanceEntry[]; - // Browser globals for the Web Performance User Timings API declare const performance: Performance | undefined; -declare const PerformanceObserver: PerformanceObserverConstructor | undefined; -// eslint-disable-next-line @typescript-eslint/naming-convention -function hasRequiredAPI(performance: Performance | undefined, PerformanceObserver: PerformanceObserverConstructor | undefined) { - return typeof performance === "object" && - typeof performance.timeOrigin === "number" && - typeof performance.mark === "function" && - typeof performance.measure === "function" && - typeof performance.now === "function" && - typeof performance.clearMarks === "function" && - typeof performance.clearMeasures === "function" && - typeof PerformanceObserver === "function"; -} +function tryGetPerformance() { + if (isNodeLikeSystem()) { + try { + // By default, only write native events when generating a cpu profile or using the v8 profiler. + const { performance } = require("perf_hooks") as typeof import("perf_hooks"); + return { + shouldWriteNativeEvents: false, + performance, + }; + } + catch { + // ignore errors + } + } -function tryGetWebPerformanceHooks(): PerformanceHooks | undefined { - if ( - typeof performance === "object" && - typeof PerformanceObserver === "function" && - hasRequiredAPI(performance, PerformanceObserver) - ) { + if (typeof performance === "object") { + // For now we always write native performance events when running in the browser. We may + // make this conditional in the future if we find that native web performance hooks + // in the browser also slow down compilation. return { - // For now we always write native performance events when running in the browser. We may - // make this conditional in the future if we find that native web performance hooks - // in the browser also slow down compilation. shouldWriteNativeEvents: true, performance, - PerformanceObserver, }; } + + return undefined; } -function tryGetNodePerformanceHooks(): PerformanceHooks | undefined { - if (isNodeLikeSystem()) { - try { - const { performance, PerformanceObserver } = require("perf_hooks") as typeof import("perf_hooks"); - if (hasRequiredAPI(performance, PerformanceObserver)) { - return { - // By default, only write native events when generating a cpu profile or using the v8 profiler. - shouldWriteNativeEvents: false, - performance, - PerformanceObserver, - }; - } - } - catch { - // ignore errors - } +function tryGetPerformanceHooks(): PerformanceHooks | undefined { + const p = tryGetPerformance(); + if (!p) return undefined; + const { shouldWriteNativeEvents, performance } = p; + + const hooks: PerformanceHooks = { + shouldWriteNativeEvents, + performance: undefined, + performanceTime: undefined, + }; + + if (typeof performance.timeOrigin === "number" && typeof performance.now === "function") { + hooks.performanceTime = performance; } + + if ( + hooks.performanceTime && + typeof performance.mark === "function" && + typeof performance.measure === "function" && + typeof performance.clearMarks === "function" && + typeof performance.clearMeasures === "function" + ) { + hooks.performance = performance; + } + + return hooks; } -// Unlike with the native Map/Set 'tryGet' functions in corePublic.ts, we eagerly evaluate these -// since we will need them for `timestamp`, below. -const nativePerformanceHooks = tryGetWebPerformanceHooks() || tryGetNodePerformanceHooks(); -const nativePerformance = nativePerformanceHooks?.performance; +const nativePerformanceHooks = tryGetPerformanceHooks(); +const nativePerformanceTime = nativePerformanceHooks?.performanceTime; /** @internal */ export function tryGetNativePerformanceHooks() { @@ -116,6 +98,4 @@ export function tryGetNativePerformanceHooks() { * * @internal */ -export const timestamp = nativePerformance ? () => nativePerformance.now() : - Date.now ? Date.now : - () => +(new Date()); +export const timestamp = nativePerformanceTime ? () => nativePerformanceTime.now() : Date.now;