Skip to content

Commit 3c63740

Browse files
authored
Use performance.now when possible, re-disable unconditional perf marking on all Node versions (#57875)
1 parent b75261d commit 3c63740

File tree

2 files changed

+57
-77
lines changed

2 files changed

+57
-77
lines changed

src/compiler/performance.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ export function enable(system: System = sys) {
180180
if (!enabled) {
181181
enabled = true;
182182
perfHooks ||= tryGetNativePerformanceHooks();
183-
if (perfHooks) {
183+
if (perfHooks?.performance) {
184184
timeorigin = perfHooks.performance.timeOrigin;
185185
// NodeJS's Web Performance API is currently slower than expected, but we'd still like
186186
// to be able to leverage native trace events when node is run with either `--cpu-prof`

src/compiler/performanceCore.ts

+56-76
Original file line numberDiff line numberDiff line change
@@ -7,104 +7,86 @@ import {
77

88
/** @internal */
99
export interface PerformanceHooks {
10-
/** Indicates whether we should write native performance events */
1110
shouldWriteNativeEvents: boolean;
12-
performance: Performance;
13-
PerformanceObserver: PerformanceObserverConstructor;
11+
performance?: Performance;
12+
performanceTime?: PerformanceTime;
1413
}
1514

1615
/** @internal */
17-
export interface Performance {
18-
mark(name: string): void;
19-
measure(name: string, startMark?: string, endMark?: string): void;
20-
clearMeasures(name?: string): void;
21-
clearMarks(name?: string): void;
16+
export interface PerformanceTime {
2217
now(): number;
2318
timeOrigin: number;
2419
}
2520

2621
/** @internal */
27-
export interface PerformanceEntry {
28-
name: string;
29-
entryType: string;
30-
startTime: number;
31-
duration: number;
32-
}
33-
34-
/** @internal */
35-
export interface PerformanceObserverEntryList {
36-
getEntries(): PerformanceEntryList;
37-
getEntriesByName(name: string, type?: string): PerformanceEntryList;
38-
getEntriesByType(type: string): PerformanceEntryList;
39-
}
40-
41-
/** @internal */
42-
export interface PerformanceObserver {
43-
disconnect(): void;
44-
observe(options: { entryTypes: readonly ("mark" | "measure")[]; }): void;
22+
export interface Performance extends PerformanceTime {
23+
mark(name: string): void;
24+
measure(name: string, startMark?: string, endMark?: string): void;
25+
clearMeasures(name?: string): void;
26+
clearMarks(name?: string): void;
4527
}
4628

47-
/** @internal */
48-
export type PerformanceObserverConstructor = new (callback: (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void) => PerformanceObserver;
49-
/** @internal */
50-
export type PerformanceEntryList = PerformanceEntry[];
51-
5229
// Browser globals for the Web Performance User Timings API
5330
declare const performance: Performance | undefined;
54-
declare const PerformanceObserver: PerformanceObserverConstructor | undefined;
5531

56-
// eslint-disable-next-line @typescript-eslint/naming-convention
57-
function hasRequiredAPI(performance: Performance | undefined, PerformanceObserver: PerformanceObserverConstructor | undefined) {
58-
return typeof performance === "object" &&
59-
typeof performance.timeOrigin === "number" &&
60-
typeof performance.mark === "function" &&
61-
typeof performance.measure === "function" &&
62-
typeof performance.now === "function" &&
63-
typeof performance.clearMarks === "function" &&
64-
typeof performance.clearMeasures === "function" &&
65-
typeof PerformanceObserver === "function";
66-
}
32+
function tryGetPerformance() {
33+
if (isNodeLikeSystem()) {
34+
try {
35+
// By default, only write native events when generating a cpu profile or using the v8 profiler.
36+
const { performance } = require("perf_hooks") as typeof import("perf_hooks");
37+
return {
38+
shouldWriteNativeEvents: false,
39+
performance,
40+
};
41+
}
42+
catch {
43+
// ignore errors
44+
}
45+
}
6746

68-
function tryGetWebPerformanceHooks(): PerformanceHooks | undefined {
69-
if (
70-
typeof performance === "object" &&
71-
typeof PerformanceObserver === "function" &&
72-
hasRequiredAPI(performance, PerformanceObserver)
73-
) {
47+
if (typeof performance === "object") {
48+
// For now we always write native performance events when running in the browser. We may
49+
// make this conditional in the future if we find that native web performance hooks
50+
// in the browser also slow down compilation.
7451
return {
75-
// For now we always write native performance events when running in the browser. We may
76-
// make this conditional in the future if we find that native web performance hooks
77-
// in the browser also slow down compilation.
7852
shouldWriteNativeEvents: true,
7953
performance,
80-
PerformanceObserver,
8154
};
8255
}
56+
57+
return undefined;
8358
}
8459

85-
function tryGetNodePerformanceHooks(): PerformanceHooks | undefined {
86-
if (isNodeLikeSystem()) {
87-
try {
88-
const { performance, PerformanceObserver } = require("perf_hooks") as typeof import("perf_hooks");
89-
if (hasRequiredAPI(performance, PerformanceObserver)) {
90-
return {
91-
// By default, only write native events when generating a cpu profile or using the v8 profiler.
92-
shouldWriteNativeEvents: false,
93-
performance,
94-
PerformanceObserver,
95-
};
96-
}
97-
}
98-
catch {
99-
// ignore errors
100-
}
60+
function tryGetPerformanceHooks(): PerformanceHooks | undefined {
61+
const p = tryGetPerformance();
62+
if (!p) return undefined;
63+
const { shouldWriteNativeEvents, performance } = p;
64+
65+
const hooks: PerformanceHooks = {
66+
shouldWriteNativeEvents,
67+
performance: undefined,
68+
performanceTime: undefined,
69+
};
70+
71+
if (typeof performance.timeOrigin === "number" && typeof performance.now === "function") {
72+
hooks.performanceTime = performance;
10173
}
74+
75+
if (
76+
hooks.performanceTime &&
77+
typeof performance.mark === "function" &&
78+
typeof performance.measure === "function" &&
79+
typeof performance.clearMarks === "function" &&
80+
typeof performance.clearMeasures === "function"
81+
) {
82+
hooks.performance = performance;
83+
}
84+
85+
return hooks;
10286
}
10387

104-
// Unlike with the native Map/Set 'tryGet' functions in corePublic.ts, we eagerly evaluate these
105-
// since we will need them for `timestamp`, below.
106-
const nativePerformanceHooks = tryGetWebPerformanceHooks() || tryGetNodePerformanceHooks();
107-
const nativePerformance = nativePerformanceHooks?.performance;
88+
const nativePerformanceHooks = tryGetPerformanceHooks();
89+
const nativePerformanceTime = nativePerformanceHooks?.performanceTime;
10890

10991
/** @internal */
11092
export function tryGetNativePerformanceHooks() {
@@ -116,6 +98,4 @@ export function tryGetNativePerformanceHooks() {
11698
*
11799
* @internal
118100
*/
119-
export const timestamp = nativePerformance ? () => nativePerformance.now() :
120-
Date.now ? Date.now :
121-
() => +(new Date());
101+
export const timestamp = nativePerformanceTime ? () => nativePerformanceTime.now() : Date.now;

0 commit comments

Comments
 (0)