From 93b9f2ed04f1a1f15ddccbb9b056e51a0a4e4f8c Mon Sep 17 00:00:00 2001 From: Guohui Deng Date: Tue, 14 Apr 2026 14:04:20 -0600 Subject: [PATCH 1/6] Move over the explainer to MSEdge repo --- ConditionalTracing/explainer-for-loaf.md | 183 +++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 ConditionalTracing/explainer-for-loaf.md diff --git a/ConditionalTracing/explainer-for-loaf.md b/ConditionalTracing/explainer-for-loaf.md new file mode 100644 index 000000000..03e6f7044 --- /dev/null +++ b/ConditionalTracing/explainer-for-loaf.md @@ -0,0 +1,183 @@ +# Lightweight and Conditional Tracing + +## Contacts + or [noamr](https://github.com/noamr)
+ or [guohuideng2024](https://github.com/guohuideng2024) + +## Participate + +Please join the discussion at this [link](https://github.com/w3c/long-animation-frames/issues/3). + +## Goal + +This proposal introduces a lightweight and conditional tracing to facilitate investigation into performance incidents such as Long Animation Frames (LoAF). + +## User Research + +A number of Performance APIs monitor web site performance, but the information provided by these APIs by themselves may not be sufficient to locate the root cause of performance problems. + +One example is the [wrapper problem](w3c/long-animation-frames#3) of the LoAF API. When application JavaScript execution causes a LoAF, the [script entry point](https://w3c.github.io/long-animation-frames/#create-script-entry-point) in the `PerformanceLongAnimationFrameTiming` exposes the responsible script entry point. Such a script entry point is often not granular enough, e.g. it can be a React callback that hides all the underlying slow functions, and also creates faux attribution: the wrapper function is "blamed" for slowness when it just passes the execution to an underlying function. A similar issue exists for event timing, where the provided timing attributes don't always capture the whole story, and don't always coincide with a more attributable long animation frame. + +The [performance User Timing API](https://www.w3.org/TR/user-timing/) can be used to diagnose performance problems further when additional information is needed to locate the root cause. However, it has some drawbacks: + +- The browser doesn't know the performance user timing points are set to diagnose a particular kind of performance incidents, so the browser cannot manage the coresponding data efficiently. The data cannot be filtered properly based on the the absence of performance incidents. Consequently the sites must process and upload more metric data back to the server than needed. This causes considerable performance overhead on the client. + +- The data collected from performance User Timing API is separate from the data collected from perfornance monitoring APIs like LoAF, requiring developers to relate them after careful analysis. + +This document proposes a lightweight User Timing API extension specifically designed to support LoAF. Compared to the standard User Timing API, this proposal offers lower runtime overhead and improved developer ergonomics. A similar enhancement could be applied to the Event Timing API in the future. + + +## API Changes and Example Code + +This proposal introduces a variation of creating markers and measurements: + +```js +performance.markConditional(markName); +performance.measureConditional(measureName, startMark/*optional*/, endMark /*optional*/); +``` + +In comparison to `performance.mark()` and `performance.measure()`, these don't have the arguments `markOptions` and `measureOptions`. + +The `startMark` and `endMark` refers to the conditional mark points that occur during the time interval for the current relevant PerformanceEntry only. + +Unlike the User Timing API, neither `markConditional` nor `measureConditional` returns a `PerformanceMark` or a `PerformanceMeasure` entry. These conditional `mark`s and `measure`s are tracked for the relevant performance incidents(such as LoAF) only. Therefore they are only provided in the relevant PerformanceEntry(i.e., `PerformanceLongAnimationFrameTiming`) if they occur during a LoAF. + +We report the tracing points with `ConditionalMark` and `ConditionalMeasure` entries. They are similar to `PerformanceMark` and `PerformanceMeasure` entries. But they don't have a `detail` field. + +A new field, `userTimingEntries` is added to `PerformanceLongAnimationFrameTiming` interface. It's an array consisting of relevant `ConditionalMark` and `ConditionalMeasure` entries that occurs during a LoAF. + +Conditional markers and measures do not appear in the global timeline. + +### Sample code + +```js + +// Add a mark. This mark does not appear in the performance timeline, but for LoAF purpose only. +performance.markConditional("mark1"); // at time t1 +// ... later ... +// Add another mark. +performance.markConditional("mark2"); // at time t2 + +// This mark is never refered to by conditional measures, because it's not conditional. +performance.mark("mark1"); // at time tx + +// Combines mark->mark as a single entry with duration. +performance.measureConditional("myMeasure", "mark1", "mark2"); + +// Observe long animation frame entries, and print out the +// conditional tracing results. +const observer = new PerformanceObserver(entries => { + for (const loaf : entries.getEntriesByType("long-animation-frame") { + // This will print all the conditional marks & measures that occur during a LoAF. + for (const userTimingEntry of loaf.userTimingEntries) { + if( userTimingEntry.entryType === "conditionalMark"){ + console.log(userTimingEntry.entryType, userTimingEntry.name, userTimingEntry.startTime); + } + else if ( userTimingEntry.entryType == "conditionalMeasure"){ + console.log(userTimingEntry.entryType, userTimingEntry.name, userTimingEntry.duration); + } + } + } +}); +observer.observe({entryType: "long-animation-frame"}); + +/* Assuming we have a LoAF, during which all the mark and measure points are executed once +at the time indicated in the comment, The output would be: +"conditionalMark", "mark1", t1 +"conditionalMark", "mark2", t2 +"conditionalMeasure", "myMeasure", t2-t1 +*/ + +/* Assuming we have a LoAF, during which conditional mark "mark1" +had never been reached, the output would be: +"conditionalMark", "mark2", t2 +"conditionalMeasure", "myMeasure", t2-0 ==> not t2-tx +*/ +``` + +## Alternatives Considered + +[User-defined script entry point (UDSEP)](https://github.com/w3c/long-animation-frames/blob/main/user-defined-script-entry-point-explainer.md) is another way to annotate code for LoAF. UDSEP monitors script entry point enter and exit timing and keeps track of nesting entry points as well as time spent by microtasks that are not annotated but dispatched within UDSEP. This approach requires [an efficient V8 extension](https://docs.google.com/document/d/1wEXU0nv8DhzN7XpfmlfbRcbsJ2JNWjfAF-3J7qtWiEw/edit?usp=sharing) that allows Blink to be notified at the microtask enter and exit points. Due to the complexty involved, we prefer this conditional tracing approach. + +## Future extention to this proposal + +We can apply the same enhancement to event timing in the future. + +## Stakeholder Feedback/Opposition +TBD. + +## Security/Privacy Considerations +The information exposed by this API is similar to what the User Timing API exposes. The difference is that the data exposed by this API is filtered by performance incidents. + +### [Self-Review Questionnaire: Security and Privacy](https://w3ctag.github.io/security-questionnaire/) + +>1. What information does this feature expose, and for what purposes? + +This feature extends the existing performance User Timing API. The app can add `mark` and `measure` points in a similar fasion but the `PerformanceMark` and `PerformanceMeasure` entries can now be specified for a particular kind of performance incidents, so the UA filters out unrelevant entries and report the relevant ones in the corresponding `PerformanceEntry`. + +The purpose of this new feature is to improve the computational efficiency and ergonomics of the User Timing API when diagnosing the cause of LoAF. + +>2. Do features in your specification expose the minimum amount of information necessary to implement the intended functionality? + +Yes +>3. Do the features in your specification expose personal information, personally-identifiable information (PII), or information derived from either? + +No. +>4. How do the features in your specification deal with sensitive information? + +It does not deal with sensitive information. +>5. Does data exposed by your specification carry related but distinct information that may not be obvious to users?? + +No. +>6. Do the features in your specification introduce state that persists across browsing sessions? + +No. +>7. Do the features in your specification expose information about the underlying platform to origins? + +No. +>8. Does this specification allow an origin to send data to the underlying platform? + +No. +>9. Do features in this specification enable access to device sensors? + +No. +>10. Do features in this specification enable new script execution/loading mechanisms? + +No. +>11. Do features in this specification allow an origin to access other devices? + +No. +>12. Do features in this specification allow an origin some measure of control over a user agent’s native UI? + +No. +>13. What temporary identifiers do the features in this specification create or expose to the web? + +No. +>14. How does this specification distinguish between behavior in first-party and third-party contexts? + +No distinction. +>15. How do the features in this specification work in the context of a browser’s Private Browsing or Incognito mode? + +No difference. +>16. Does this specification have both "Security Considerations" and "Privacy Considerations" sections? + +Yes. +>17. Do features in your specification enable origins to downgrade default security protections? + +No. +>18. What happens when a document that uses your feature is kept alive in BFCache (instead of getting destroyed) after navigation, and potentially gets reused on future navigations back to the document? + +No difference. + +>19. What happens when a document that uses your feature gets disconnected? + +No difference. +>20. Does your spec define when and how new kinds of errors should be raised? + +No new errors should be raised. +>21. Does your feature allow sites to learn about the users use of assistive technology? + +Not directly. +>22. What should this questionnaire have asked? + +Nothing else. From 0add0fa3299f0b763c4e7d070bc396199b7a30c6 Mon Sep 17 00:00:00 2001 From: Guohui Deng Date: Tue, 14 Apr 2026 14:09:11 -0600 Subject: [PATCH 2/6] Fix a broken link --- ConditionalTracing/explainer-for-loaf.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ConditionalTracing/explainer-for-loaf.md b/ConditionalTracing/explainer-for-loaf.md index 03e6f7044..ed1283a33 100644 --- a/ConditionalTracing/explainer-for-loaf.md +++ b/ConditionalTracing/explainer-for-loaf.md @@ -16,7 +16,7 @@ This proposal introduces a lightweight and conditional tracing to facilitate inv A number of Performance APIs monitor web site performance, but the information provided by these APIs by themselves may not be sufficient to locate the root cause of performance problems. -One example is the [wrapper problem](w3c/long-animation-frames#3) of the LoAF API. When application JavaScript execution causes a LoAF, the [script entry point](https://w3c.github.io/long-animation-frames/#create-script-entry-point) in the `PerformanceLongAnimationFrameTiming` exposes the responsible script entry point. Such a script entry point is often not granular enough, e.g. it can be a React callback that hides all the underlying slow functions, and also creates faux attribution: the wrapper function is "blamed" for slowness when it just passes the execution to an underlying function. A similar issue exists for event timing, where the provided timing attributes don't always capture the whole story, and don't always coincide with a more attributable long animation frame. +One example is the [wrapper problem](https://github.com/w3c/long-animation-frames/issues/3) of the LoAF API. When application JavaScript execution causes a LoAF, the [script entry point](https://w3c.github.io/long-animation-frames/#create-script-entry-point) in the `PerformanceLongAnimationFrameTiming` exposes the responsible script entry point. Such a script entry point is often not granular enough, e.g. it can be a React callback that hides all the underlying slow functions, and also creates faux attribution: the wrapper function is "blamed" for slowness when it just passes the execution to an underlying function. A similar issue exists for event timing, where the provided timing attributes don't always capture the whole story, and don't always coincide with a more attributable long animation frame. The [performance User Timing API](https://www.w3.org/TR/user-timing/) can be used to diagnose performance problems further when additional information is needed to locate the root cause. However, it has some drawbacks: From 673e47a0e5cf446b3226340cd477934c77cdeb65 Mon Sep 17 00:00:00 2001 From: Guohui Deng Date: Tue, 14 Apr 2026 14:53:05 -0600 Subject: [PATCH 3/6] fix a few errors. --- ConditionalTracing/explainer-for-loaf.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ConditionalTracing/explainer-for-loaf.md b/ConditionalTracing/explainer-for-loaf.md index ed1283a33..1185c4a51 100644 --- a/ConditionalTracing/explainer-for-loaf.md +++ b/ConditionalTracing/explainer-for-loaf.md @@ -20,9 +20,9 @@ One example is the [wrapper problem](https://github.com/w3c/long-animation-frame The [performance User Timing API](https://www.w3.org/TR/user-timing/) can be used to diagnose performance problems further when additional information is needed to locate the root cause. However, it has some drawbacks: -- The browser doesn't know the performance user timing points are set to diagnose a particular kind of performance incidents, so the browser cannot manage the coresponding data efficiently. The data cannot be filtered properly based on the the absence of performance incidents. Consequently the sites must process and upload more metric data back to the server than needed. This causes considerable performance overhead on the client. +- The browser doesn't know the performance user timing points are set to diagnose a particular kind of performance incidents, so the browser cannot manage the corresponding data efficiently. The data cannot be filtered properly based on the the absence of performance incidents. Consequently the sites must process and upload more metric data back to the server than needed. This causes considerable performance overhead on the client. -- The data collected from performance User Timing API is separate from the data collected from perfornance monitoring APIs like LoAF, requiring developers to relate them after careful analysis. +- The data collected from performance User Timing API is separate from the data collected from performance monitoring APIs like LoAF, requiring developers to relate them after careful analysis. This document proposes a lightweight User Timing API extension specifically designed to support LoAF. Compared to the standard User Timing API, this proposal offers lower runtime overhead and improved developer ergonomics. A similar enhancement could be applied to the Event Timing API in the future. @@ -67,13 +67,13 @@ performance.measureConditional("myMeasure", "mark1", "mark2"); // Observe long animation frame entries, and print out the // conditional tracing results. const observer = new PerformanceObserver(entries => { - for (const loaf : entries.getEntriesByType("long-animation-frame") { + for (const loaf of entries.getEntriesByType("long-animation-frame")) { // This will print all the conditional marks & measures that occur during a LoAF. for (const userTimingEntry of loaf.userTimingEntries) { if( userTimingEntry.entryType === "conditionalMark"){ console.log(userTimingEntry.entryType, userTimingEntry.name, userTimingEntry.startTime); } - else if ( userTimingEntry.entryType == "conditionalMeasure"){ + else if ( userTimingEntry.entryType === "conditionalMeasure"){ console.log(userTimingEntry.entryType, userTimingEntry.name, userTimingEntry.duration); } } From 83774fddf88890c3e188f0241994fba2cccb959c Mon Sep 17 00:00:00 2001 From: Guohui Deng Date: Tue, 14 Apr 2026 14:56:40 -0600 Subject: [PATCH 4/6] fix typos --- ConditionalTracing/explainer-for-loaf.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ConditionalTracing/explainer-for-loaf.md b/ConditionalTracing/explainer-for-loaf.md index 1185c4a51..cb3dd07f5 100644 --- a/ConditionalTracing/explainer-for-loaf.md +++ b/ConditionalTracing/explainer-for-loaf.md @@ -58,7 +58,7 @@ performance.markConditional("mark1"); // at time t1 // Add another mark. performance.markConditional("mark2"); // at time t2 -// This mark is never refered to by conditional measures, because it's not conditional. +// This mark is never referred to by conditional measures, because it's not conditional. performance.mark("mark1"); // at time tx // Combines mark->mark as a single entry with duration. @@ -97,9 +97,9 @@ had never been reached, the output would be: ## Alternatives Considered -[User-defined script entry point (UDSEP)](https://github.com/w3c/long-animation-frames/blob/main/user-defined-script-entry-point-explainer.md) is another way to annotate code for LoAF. UDSEP monitors script entry point enter and exit timing and keeps track of nesting entry points as well as time spent by microtasks that are not annotated but dispatched within UDSEP. This approach requires [an efficient V8 extension](https://docs.google.com/document/d/1wEXU0nv8DhzN7XpfmlfbRcbsJ2JNWjfAF-3J7qtWiEw/edit?usp=sharing) that allows Blink to be notified at the microtask enter and exit points. Due to the complexty involved, we prefer this conditional tracing approach. +[User-defined script entry point (UDSEP)](https://github.com/w3c/long-animation-frames/blob/main/user-defined-script-entry-point-explainer.md) is another way to annotate code for LoAF. UDSEP monitors script entry point enter and exit timing and keeps track of nesting entry points as well as time spent by microtasks that are not annotated but dispatched within UDSEP. This approach requires [an efficient V8 extension](https://docs.google.com/document/d/1wEXU0nv8DhzN7XpfmlfbRcbsJ2JNWjfAF-3J7qtWiEw/edit?usp=sharing) that allows Blink to be notified at the microtask enter and exit points. Due to the complexity involved, we prefer this conditional tracing approach. -## Future extention to this proposal +## Future extension to this proposal We can apply the same enhancement to event timing in the future. @@ -113,7 +113,7 @@ The information exposed by this API is similar to what the User Timing API expos >1. What information does this feature expose, and for what purposes? -This feature extends the existing performance User Timing API. The app can add `mark` and `measure` points in a similar fasion but the `PerformanceMark` and `PerformanceMeasure` entries can now be specified for a particular kind of performance incidents, so the UA filters out unrelevant entries and report the relevant ones in the corresponding `PerformanceEntry`. +This feature extends the existing performance User Timing API. The app can add `mark` and `measure` points in a similar fashion but the `PerformanceMark` and `PerformanceMeasure` entries can now be specified for a particular kind of performance incidents, so the UA filters out irrelevant entries and report the relevant ones in the corresponding `PerformanceEntry`. The purpose of this new feature is to improve the computational efficiency and ergonomics of the User Timing API when diagnosing the cause of LoAF. From 4d48b2b4b8468fac47e3c33b46677097f338177e Mon Sep 17 00:00:00 2001 From: Guohui Deng Date: Wed, 15 Apr 2026 17:05:16 -0600 Subject: [PATCH 5/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- ConditionalTracing/explainer-for-loaf.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ConditionalTracing/explainer-for-loaf.md b/ConditionalTracing/explainer-for-loaf.md index cb3dd07f5..97e2d6bb5 100644 --- a/ConditionalTracing/explainer-for-loaf.md +++ b/ConditionalTracing/explainer-for-loaf.md @@ -113,7 +113,7 @@ The information exposed by this API is similar to what the User Timing API expos >1. What information does this feature expose, and for what purposes? -This feature extends the existing performance User Timing API. The app can add `mark` and `measure` points in a similar fashion but the `PerformanceMark` and `PerformanceMeasure` entries can now be specified for a particular kind of performance incidents, so the UA filters out irrelevant entries and report the relevant ones in the corresponding `PerformanceEntry`. +This feature extends the existing performance User Timing API. The app can add `mark` and `measure` points in a similar fashion but the `PerformanceMark` and `PerformanceMeasure` entries can now be specified for a particular kind of performance incidents, so the UA filters out irrelevant entries and reports the relevant ones in the corresponding `PerformanceEntry`. The purpose of this new feature is to improve the computational efficiency and ergonomics of the User Timing API when diagnosing the cause of LoAF. From 0f779b57932d34e46321fc63ae78d7f4b12159c6 Mon Sep 17 00:00:00 2001 From: Guohui Deng Date: Wed, 15 Apr 2026 17:12:07 -0600 Subject: [PATCH 6/6] Fix grammar errors --- ConditionalTracing/explainer-for-loaf.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ConditionalTracing/explainer-for-loaf.md b/ConditionalTracing/explainer-for-loaf.md index 97e2d6bb5..2749fed8e 100644 --- a/ConditionalTracing/explainer-for-loaf.md +++ b/ConditionalTracing/explainer-for-loaf.md @@ -38,13 +38,13 @@ performance.measureConditional(measureName, startMark/*optional*/, endMark /*opt In comparison to `performance.mark()` and `performance.measure()`, these don't have the arguments `markOptions` and `measureOptions`. -The `startMark` and `endMark` refers to the conditional mark points that occur during the time interval for the current relevant PerformanceEntry only. +The `startMark` and `endMark` refer to the conditional mark points that occur during the time interval for the current relevant PerformanceEntry only. Unlike the User Timing API, neither `markConditional` nor `measureConditional` returns a `PerformanceMark` or a `PerformanceMeasure` entry. These conditional `mark`s and `measure`s are tracked for the relevant performance incidents(such as LoAF) only. Therefore they are only provided in the relevant PerformanceEntry(i.e., `PerformanceLongAnimationFrameTiming`) if they occur during a LoAF. We report the tracing points with `ConditionalMark` and `ConditionalMeasure` entries. They are similar to `PerformanceMark` and `PerformanceMeasure` entries. But they don't have a `detail` field. -A new field, `userTimingEntries` is added to `PerformanceLongAnimationFrameTiming` interface. It's an array consisting of relevant `ConditionalMark` and `ConditionalMeasure` entries that occurs during a LoAF. +A new field, `userTimingEntries` is added to `PerformanceLongAnimationFrameTiming` interface. It's an array consisting of relevant `ConditionalMark` and `ConditionalMeasure` entries that occur during a LoAF. Conditional markers and measures do not appear in the global timeline. @@ -126,7 +126,7 @@ No. >4. How do the features in your specification deal with sensitive information? It does not deal with sensitive information. ->5. Does data exposed by your specification carry related but distinct information that may not be obvious to users?? +>5. Does data exposed by your specification carry related but distinct information that may not be obvious to users? No. >6. Do the features in your specification introduce state that persists across browsing sessions?