For the complete documentation index, see llms.txt. This page is also available as Markdown.

Custom Performance Marks

Drop browser-style performance marks anywhere in your LWC code with startPerformanceMark / endPerformanceMark — fully per-instance and Locker Service-safe.

The high-level helpers (timeBackendCall, timeUserInteraction, trackComponentLifecycle, trackComponentRender) cover the common cases. When you need to time something that doesn't fit those moulds — a chunk of client-side data shaping, an animation, a debounce window, a delay between async steps — reach for raw performance marks.

The API mirrors the browser's performance.mark() pattern:

this.triton.startPerformanceMark('product-search');
// ... do work ...
this.triton.endPerformanceMark('product-search');

startPerformanceMark stores a starting timestamp keyed by mark name and component instance. endPerformanceMark computes the duration, emits a TYPE.PERFORMANCE log entry, and clears the mark.

When to Reach for Marks

Marks are the right tool when:

  • You're measuring purely client-side work that has no backend round trip — e.g. parsing a CSV, computing a derived data structure, an animation timeline.

  • You want to wrap both sides of an async boundary that the higher-level helpers don't model — e.g. starting a timer when a debounce fires, stopping it when the next user event arrives.

  • You want a single duration record without the auto-generated start/complete pair that timeBackendCall produces.

If your work is an Apex call or a user-triggered flow, the higher-level helpers are almost always a better fit — they give you start/complete records and standard error handling for free.

Example: Wrapping a Search Flow

async handleSearch() {
    const searchTerm = this.searchInput.value;

    this.triton.startPerformanceMark('product-search');
    try {
        const results = await this.triton.timeBackendCall(
            'searchProducts',
            () => searchProducts({ searchTerm })
        ).execute();

        this.products = results;
    } finally {
        // Always pair the start with an end — even on failure.
        this.triton.endPerformanceMark('product-search');
    }
}

This pattern is handy when you want a single "user-perceived search latency" record (the mark) plus the more granular backend call timing inside it. The mark captures the whole stretch — including the time between the backend response and the UI being ready — while the backend call captures just the round trip.

You can have multiple marks active at once. Names are independent: startPerformanceMark('search') and startPerformanceMark('hydrate') coexist happily and end independently.

Per-Instance Isolation

Marks are stored per component instance, just like lifecycle and render counts. Two instances of the same component can each have an active product-search mark and neither will interfere with the other.

What Gets Logged

Each endPerformanceMark call emits one log entry:

Field
Value

type

TYPE.PERFORMANCE

summary

Performance: <componentName> - <markName>

details

Duration: <ms>ms

duration

the measured milliseconds

action

the mark name

No log is produced on startPerformanceMark — marks are silent until they're closed. If you call endPerformanceMark for a name that was never started, Triton emits a console warning and skips the log.

Locker Service Compatibility

Mark timing uses the same getCurrentTime() helper described in Component Lifecycle: performance.now() when available, Date.now() otherwise. You get sub-millisecond precision where allowed, and you never need a fallback path in your code.

Best Practices

  • Always pair startPerformanceMark with endPerformanceMark. Wrap the end in finally so an exception in the middle doesn't leave a dangling mark.

  • Use descriptive, hyphenated names. They show up directly in dashboards (action column).

  • Bind first. Custom marks require bindToComponent() — without it you'll just get a console warning and no log.

  • Don't double up. If you're already wrapping with timeBackendCall or timeUserInteraction, you usually don't need a custom mark on top — the helpers already record duration.

Last updated