Performance
Elide implements the [WinterCG Minimum Common API][wintercg]'s performance surface — the
[Performance][hr-time] interface, [User Timing][user-timing] (mark, measure,
PerformanceMark, PerformanceMeasure), and [Performance Timeline][perf-timeline]
(PerformanceEntry, PerformanceObserver, PerformanceObserverEntryList). A single
realm-bound timeline backs both globalThis.performance and the Node-style
node:perf_hooks module — every entry is observable through both
surfaces.
[wintercg]: https://min-common-api.proposal.wintercg.org/ [hr-time]: https://w3c.github.io/hr-time/ [user-timing]: https://w3c.github.io/user-timing/ [perf-timeline]: https://w3c.github.io/performance-timeline/
globalThis.performance
Singleton instance of Performance, installed on every realm at agent init. Inherits from
EventTarget, so addEventListener / removeEventListener / dispatchEvent work on it
(Performance has no built-in events of its own — the inheritance is for guest extensions).
declare const performance: Performance;
interface Performance extends EventTarget {
readonly timeOrigin: DOMHighResTimeStamp;
now(): DOMHighResTimeStamp;
mark(name: string, options?: PerformanceMarkOptions): PerformanceMark;
measure(
name: string,
startOrOptions?: string | PerformanceMeasureOptions,
endMark?: string,
): PerformanceMeasure;
getEntries(): PerformanceEntry[];
getEntriesByName(name: string, type?: string): PerformanceEntry[];
getEntriesByType(type: string): PerformanceEntry[];
clearMarks(name?: string): void;
clearMeasures(name?: string): void;
toJSON(): object;
}Performance is not constructible from JavaScript. new Performance() and plain-call
Performance() raise TypeError.
Time
performance.timeOrigin— the wall-clock millisecond timestamp at which the realm was created.[SameObject]: identical value across reads.performance.now()— high-resolution time in milliseconds sincetimeOrigin. Resolution is limited only by the host clock (typically ≥ 1 µs); the spec only mandates ≥ 5 µs.
mark(name, options?)
Records a PerformanceMark and registers it for later reference by name in measure(...).
options.startTime, when supplied, is used verbatim as the mark's startTime; otherwise the
current now() is captured. Negative startTime raises TypeError. options.detail is
[structured-cloned][clone] at construction time — subsequent mutation of the source value
does not bleed into the mark. The clone subset is the same one documented for
postMessage: primitives, plain objects, dense arrays, and
cycles. Unsupported types raise DataCloneError DOMException.
[clone]: https://html.spec.whatwg.org/multipage/structured-data.html#structured-clone
measure(name, startOrOptions?, endMark?)
Records a PerformanceMeasure between two anchors. The second argument can be:
- omitted /
undefined— span from0tonow(); - a string — name of a previously-recorded mark; span from that mark's
startTimeto eitherendMark(if supplied) ornow(); - a
PerformanceMeasureOptionsdictionary with any two ofstart/end/duration(passing all three raisesTypeError); each may itself be a mark name or a numeric timestamp. The dictionary may also carry a structured-cloneddetail.
Passing both an options dict and a third endMark argument raises TypeError. Referencing a
mark name that does not exist raises SyntaxError DOMException.
Reading the timeline
getEntries() returns every recorded entry sorted by startTime ascending (a fresh array per
call). getEntriesByName(name, type?) and getEntriesByType(type) filter the same set.
Clearing
clearMarks(name?) and clearMeasures(name?) remove matching entries. Passing no name
clears everything of that type. The mark-name registry used by measure(name, ...) is
cleared in lock-step.
PerformanceEntry
Abstract base for PerformanceMark, PerformanceMeasure, and (Node-only)
PerformanceNodeTiming. Not constructible from JavaScript. Exposes:
interface PerformanceEntry {
readonly name: string;
readonly entryType: "mark" | "measure" | "node";
readonly startTime: DOMHighResTimeStamp;
readonly duration: DOMHighResTimeStamp;
toJSON(): { name; entryType; startTime; duration };
}toJSON() writes the four standard attributes; detail is intentionally omitted (mirrors
Node's behaviour).
PerformanceMark
Constructible:
new PerformanceMark(name: string, options?: PerformanceMarkOptions): PerformanceMarkConstructed marks are recorded in the per-realm timeline, so a hand-built mark is visible
through performance.getEntries(). mark.duration is always 0. mark.detail is the
structured-cloned snapshot from options.detail, or null.
PerformanceMeasure
Not constructible from JavaScript — performance.measure(...) is the only producer. Exposes
the inherited entry surface plus detail (structured-cloned snapshot of the
PerformanceMeasureOptions.detail dictionary entry, or null).
PerformanceObserver
new PerformanceObserver(
callback: (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void,
): PerformanceObserver
interface PerformanceObserver {
observe(options: { entryTypes?: string[]; type?: string; buffered?: boolean }): void;
disconnect(): void;
takeRecords(): PerformanceEntry[];
}
PerformanceObserver.supportedEntryTypes: ReadonlyArray<"mark" | "measure" | "node">;Callback delivery is asynchronous — buffered entries fire at the end of the next microtask
checkpoint. Inside the callback, list.getEntries() / list.getEntriesByName /
list.getEntriesByType walk a frozen snapshot.
observe(options) accepts either entryTypes (array of strings) or type (single string),
not both, not neither — passing any other shape raises TypeError. Switching modes between
calls (from entryTypes to type or vice versa) on the same observer also raises TypeError.
buffered: true pre-populates the observer's buffer with entries already on the timeline that
match the requested types — useful for observers attached after the work being observed has
already completed.
disconnect() removes the observer from the realm's dispatch list and drops its buffer.
takeRecords() synchronously drains the current buffer and returns the entries; subsequent
deliveries are unaffected.
PerformanceObserver.supportedEntryTypes is a frozen array of the entry-type strings this
implementation recognises: "mark", "measure", "node". [SameObject]: same array
reference across reads.
PerformanceObserverEntryList
Argument passed to the observer callback. Holds an immutable snapshot of the entries being
delivered. Same getEntries / getEntriesByName / getEntriesByType surface as
Performance; results are filtered against the snapshot, not the realm timeline.
Notes on the implementation
- Time origin is captured once at agent install via
System.currentTimeMillis()for the user-observabletimeOriginandSystem.nanoTime()for the monotonic clock that powersnow(). The two are taken at the same instant so the relationshipnow() = wallclock - timeOriginholds. - Observer dispatch hooks into the realm's microtask checkpoint listener (the same hook the WinterCG
unhandledrejectionflow uses) — there is no separate task queue. A faulty observer callback is contained: it does not block other observers from being notified at the same checkpoint. - The Node-only
PerformanceNodeTimingentry shows up on the same timeline; see the node:perf_hooks page for its full attribute list and timing semantics.