From e124b0ff7d926c14575fda90a2bfc4852670f81b Mon Sep 17 00:00:00 2001 From: Dom Harrington Date: Sat, 2 Nov 2024 17:05:24 +0000 Subject: [PATCH] doc: broken `PerformanceObserver` code sample The code sample at the top of the "Performance measurements API" section of the docs does not run. The code in question: ```js const { PerformanceObserver, performance } = require('node:perf_hooks'); const obs = new PerformanceObserver((items) => { console.log(items.getEntries()[0].duration); performance.clearMarks(); }); obs.observe({ type: 'measure' }); performance.measure('Start to Now'); performance.mark('A'); doSomeLongRunningProcess(() => { performance.measure('A to Now', 'A'); performance.mark('B'); performance.measure('A to B', 'A', 'B'); }); ``` If you replace `doSomeLongRunningProcess` with an IIFE with a sleep() at the top of it, you get this: ```js const { PerformanceObserver, performance } = require('node:perf_hooks'); const obs = new PerformanceObserver((items) => { console.log(items.getEntries()[0].duration); performance.clearMarks(); }); obs.observe({ type: 'measure' }); performance.measure('Start to Now'); performance.mark('A'); (async function doSomeLongRunningProcess() { await new Promise(r => setTimeout(r, 5000)); performance.measure('A to Now', 'A'); performance.mark('B'); performance.measure('A to B', 'A', 'B'); })() ``` When you run this, you get the following output: ```sh $ node performance-test.js 17.873416 node:internal/per_context/domexception:53 ErrorCaptureStackTrace(this); ^ DOMException [SyntaxError]: The "A" performance mark has not been set at new DOMException (node:internal/per_context/domexception:53:5) at __node_internal_ (node:internal/util:695:10) at getMark (node:internal/perf/usertiming:65:11) at calculateStartDuration (node:internal/perf/usertiming:202:13) at measure (node:internal/perf/usertiming:220:7) at Performance.measure (node:internal/perf/performance:135:12) at /private/tmp/performance-test.js:14:15 Node.js v20.11.1 ``` I believe it's due to the call to `performance.clearMarks();` in the PerformanceObserver callback. If you remove that, it works as expected: ```js const { PerformanceObserver, performance } = require('node:perf_hooks'); const obs = new PerformanceObserver((items) => { console.log(items.getEntries()[0].duration); }); obs.observe({ type: 'measure' }); performance.measure('Start to Now'); performance.mark('A'); (async function doSomeLongRunningProcess() { await new Promise(r => setTimeout(r, 5000)); performance.measure('A to Now', 'A'); performance.mark('B'); performance.measure('A to B', 'A', 'B'); })() ``` ```sh $ node performance-test.js 17.761083 5002.468417 ``` PR-URL: https://github.com/nodejs/node/pull/54227 Reviewed-By: Chengzhong Wu --- doc/api/perf_hooks.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/api/perf_hooks.md b/doc/api/perf_hooks.md index 74f8c115b486d4..7c3144939244b6 100644 --- a/doc/api/perf_hooks.md +++ b/doc/api/perf_hooks.md @@ -22,18 +22,18 @@ const { PerformanceObserver, performance } = require('node:perf_hooks'); const obs = new PerformanceObserver((items) => { console.log(items.getEntries()[0].duration); - performance.clearMarks(); }); obs.observe({ type: 'measure' }); performance.measure('Start to Now'); performance.mark('A'); -doSomeLongRunningProcess(() => { +(async function doSomeLongRunningProcess() { + await new Promise(r => setTimeout(r, 5000)); performance.measure('A to Now', 'A'); performance.mark('B'); performance.measure('A to B', 'A', 'B'); -}); +})(); ``` ## `perf_hooks.performance`