Luxar Viewer API Documentation - v2026.9.22
    Preparing search index...

    Main profiler class

    Supports two usage patterns:

    1. Context/ambient pattern (recommended):

      profiler.beginUpdate();
      await profiler.time('Points', async () => {
      await profiler.time('Spatial Query', () => query());
      await profiler.time('GPU Upload', () => upload());
      });
      profiler.endUpdate();
    2. Manual session management:

      const session = profiler.beginUpdate();
      const pointsSession = session.begin('Points');
      // ... do work ...
      pointsSession.end();
      session.end();

    NOTE: Supports concurrent async operations. Each time() call tracks its parent context at call time, so parallel operations work correctly.

    Index
    roots: Map<string, TimingEntry> = ...
    activeSession: RootSession | null = null
    activeSessions: Map<number, UpdateSession> = ...
    nextSessionId: number = 0
    currentSessionContext: UpdateSession | null = null
    updateSeq: number = 0
    passSeq: number = 0
    sortSeq: number = 0
    depthSortCompletionTotal: number = 0
    depthSortCompletions: DepthSortCompletion[] = []
    generation: number = 0
    listeners: Set<() => void> = ...
    • Internal: current generation counter. Read by SessionImpl to gate its end() merge — and by the depth-sort coordinator to gate its recordDepthSortCompletion call — against being abandoned by a reset() that landed mid-flight. NOT a public API.

      Returns number

    • Internal: draw the next depth-sort sequence number. Called by a deferred-seq SessionImpl (a depth-sort pass) at end() so its seq reflects COMPLETION order, not dispatch order (issue #713). NOT a public API.

      Returns number

    • Begin a background LOD-refinement pass. Returns a detached root session that merges into the 'LOD Refinement' persistent tree and does NOT touch the active update session or the ambient context — a refinement pass ending mid-update must never disable the update's own profiling.

      Callers pass the returned session explicitly (pass.begin('GSplats (/p)')) down the load → process → commit chain, mirroring the main update's per-node top-level sessions.

      Returns UpdateSession

    • Begin a depth-sort round-trip (depth-sorting Phase 3). Returns a detached root session that merges into the 'Depth Sort' persistent tree — same isolation contract as beginPass: it never touches the active update session or the ambient context, so a sort resolving mid-update cannot disable the update's own profiling.

      The depth-sort coordinator opens one per SortWorker dispatch, stamps setMetadata({ elements, info, kernelMs, boundaryMs, queueMs, applyMs }) (element count, ordering bytes, and the worker/boundary/queue/apply timing split — the latency numbers are last-write on merge), and ends it when the ordering is APPLIED — i.e. its buffer is flipped in and drawn — NOT merely when the SortWorker RPC resolves (large orderings apply CHUNKED over many later frames; issue #713). The session also ends if the ordering is abandoned/cancelled before it is ever drawn, or if the RPC fails. Because the pass now spans the chunked apply, the info byte tag starts SCHEDULED (sched, at resolve) and is upgraded to uploaded (up) only once the buffer actually reaches the GPU.

      Returns UpdateSession

    • Begin a child timing entry directly under the root Use this for top-level parallel operations (Points, Lines, GSplats)

      Parameters

      • name: string

        Name of this timing entry

      Returns UpdateSession

      Session that should be passed to nested operations

    • Begin a child timing entry of the current innermost session This is the context/ambient pattern - no need to pass session around

      NOTE: For concurrent async operations at the top level, use beginTopLevel() or timeTopLevel() instead to avoid session stack corruption.

      Parameters

      • name: string

        Name of this timing entry

      Returns UpdateSession

      Session

    • Convenience: run a top-level parallel operation with timing Creates a direct child of root, safe for concurrent use with Promise.all

      Type Parameters

      • T

      Parameters

      • name: string

        Name of this timing entry (e.g., 'Points (/path)')

      • fn: (session: UpdateSession) => Promise<T>

        Async function to time

      Returns Promise<T>

      Result of fn()

    • Convenience: run a function with timing Automatically handles begin/end and preserves return value

      NOTE: For top-level parallel operations, use timeTopLevel() instead.

      Type Parameters

      • T

      Parameters

      • name: string

        Name of this timing entry

      • fn: () => T

        Sync or async function to time

      Returns T

      Result of fn()

    • Convenience: run an async function with timing and metadata Allows setting metadata before the operation completes

      Type Parameters

      • T

      Parameters

      • name: string

        Name of this timing entry

      • fn: (session: UpdateSession) => T

        Function that receives session for metadata and returns result

      Returns T

      Result of fn()

    • Mark an operation as skipped (for extend_to_all, etc.) Creates a timing entry with 0 duration and skip reason

      Parameters

      • name: string

        Name of the skipped operation

      • reason: string

        Why it was skipped

      Returns void

    • Record one applied depth-sort completion on the dedicated MONOTONIC stream (issue #711). Increments the total, tags the event with its seq, and pushes it onto the bounded ring (oldest trimmed at DEPTH_SORT_COMPLETION_CAP). Independent of the aggregate 'Depth Sort' root, so N applications between two polls remain N latency events — the exact multi-completion undercount issue #711 found.

      Parameters

      • event: {
            lastMs: number;
            kernelMs: number | null;
            boundaryMs: number | null;
            queueMs: number | null;
            elements: number | null;
        }

      Returns void

    • Snapshot the depth-sort completion stream (issue #711): the monotonic total (authoritative for the count even if some events aged out of the bounded ring) plus a COPY of the currently-buffered events (each tagged with its seq, for latency sampling). The event objects are cloned too, so mutating a returned event cannot corrupt later snapshots.

      Returns { total: number; events: DepthSortCompletion[] }

    • Reset all timing data

      Clears active-session state too: if reset() is called mid-update, any stale RootSession / currentSessionContext / per-id sessions are dropped so that subsequent endUpdate() / timeTopLevel() calls don't try to merge into the freshly rebuilt rootEntry under a name they no longer own.

      Returns void

    • Internal: Merge a completed entry into persistent state Called by SessionImpl.end()

      Parameters

      • entry: TimingEntry
      • parentName: string | undefined
      • rootName: string
      • seq: number

      Returns void

    • Merge a completed session entry's values into a persistent entry.

      • seq OLDER than the persistent entry's → drop (a late merge from a superseded update must not overwrite newer data)
      • seq EQUAL → same update: SUM lastMs, sum numeric metadata, recompute the EMA against the pre-update base (one EMA sample per update)
      • seq NEWER → rollover: snapshot avg as emaBase, start a fresh lastMs, count++ (count = number of updates the op ran in)

      Parameters

      Returns void