Skip to content

Add markPaintTime() explainer#1303

Open
JosephJin0815 wants to merge 10 commits intoMicrosoftEdge:mainfrom
JosephJin0815:user/wangsongj/mark-paint-time
Open

Add markPaintTime() explainer#1303
JosephJin0815 wants to merge 10 commits intoMicrosoftEdge:mainfrom
JosephJin0815:user/wangsongj/mark-paint-time

Conversation

@JosephJin0815
Copy link
Copy Markdown

Explainer for performance.markPaintTime() — a new Performance API that lets developers capture paintTime and presentationTime for visual update on demand, extending the timing capability currently available only through browser-detected entries (FP, FCP, LCP, Event Timing, LoAF)

@JosephJin0815 JosephJin0815 marked this pull request as ready for review April 16, 2026 22:37

Web developers need to measure when their visual updates actually render — not just the browser-detected milestones like First Paint or Largest Contentful Paint, but any update they care about: a component mount, a state transition, a style change.

The platform already captures paint and presentation timestamps for key moments via PaintTimingMixin, but only for entries the browser selects automatically. `performance.markPaintTime()` extends this capability to let developers capture the same `paintTime` and `presentationTime` for any visual update, on demand.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide href to PaintTimingMixin.

- Deliver timestamps through `PerformanceObserver`, consistent with modern performance APIs.

## Non-goals
- **Replacing existing paint timing entries.** FP, FCP, LCP, Event Timing, and LoAF continue to serve their existing purposes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use hrefs for any existing API references.

Without an on-demand API, developers resort to workarounds like double-rAF or rAF+setTimeout to approximate when the rendering update completes, but these workarounds are unreliable (see [Nolan Lawson's analysis](https://nolanlawson.com/2018/09/25/accurately-measuring-layout-on-the-web/)). Furthermore, no workaround can provide `presentationTime` — the actual time when pixels appear on screen. For example, a developer wants to measure when a chat input box appears after the page loads, but the component is rendered asynchronously by a framework. A typical pattern uses `IntersectionObserver` to detect when the element enters the viewport, then `requestAnimationFrame` to approximate the paint time:

### Single requestAnimationFrame

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be helpful to include an end-to-end example covering a page, the area of interest, and the solution.

| `entryType` | Always `"mark-paint-time"` |
| `name` | The mark name passed to `markPaintTime()` |
| `startTime` | `performance.now()` at the time `markPaintTime()` was called |
| `duration` | Always `0` |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of duration if it's always zero?

|-----------|-------------|
| `entryType` | Always `"mark-paint-time"` |
| `name` | The mark name passed to `markPaintTime()` |
| `startTime` | `performance.now()` at the time `markPaintTime()` was called |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please mark startTime in the Rendering Pipeline figure?

|-----------|-------------|
| `entryType` | Always `"mark-paint-time"` |
| `name` | The mark name passed to `markPaintTime()` |
| `startTime` | `performance.now()` at the time `markPaintTime()` was called |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m unclear about the meaning of startTime. If it’s recorded from an IntersectionObserver callback, it seems more like a pre‑paint timestamp, since it wouldn’t include earlier stages such as animation, styling, and layout. In Chromium, this would effectively correspond to pre‑paint timing. However, if markPaintTime() is invoked from a different point in the pipeline, the semantics of startTime could vary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants