docs
Loading...
Searching...
No Matches
Profiler.h
Go to the documentation of this file.
1///
2/// Copyright (C) 2026 Ultralight, Inc. All rights reserved.
3/// A license is required for commercial use. https://ultralig.ht
4///
5#pragma once
7
8#if UL_HAS(PROFILER)
9
10#include <cstdint>
11
12namespace ultralight {
13
14///
15/// User-defined profiling interface.
16///
17/// Implement this class to receive profiling callbacks from the library. The callbacks provide
18/// structured timing data (scopes, events, counters) that can be forwarded to any profiling
19/// backend -- Tracy, Optick, Unreal Insights, the built-in Perfetto trace file writer provided
20/// below (CreateProfilerPerfetto()), or a custom implementation.
21///
22/// @pre Requires the Pro edition or higher.
23///
24/// ## Usage
25///
26/// 1. Subclass `Profiler` and implement all pure virtual methods.
27/// 2. Call `Platform::instance().set_profiler(myProfiler)` before creating the Renderer or App.
28/// 3. Your profiler instance should outlive the Renderer/App.
29///
30/// ## Frame Timing
31///
32/// The library automatically calls `BeginFrame()` and `EndFrame()` around each rendering frame.
33/// Implement these to measure dirty-to-display latency and detect jank.
34///
35/// ## Threading
36///
37/// All methods may be called concurrently from any thread. Implementations must be thread-safe.
38///
39/// @see Platform::set_profiler
40///
42public:
43 virtual ~Profiler();
44
45 ///
46 /// Enter a named profiling scope.
47 ///
48 /// Calls are always balanced (`BeginScope` / `EndScope` pairs). Implementations should maintain
49 /// a per-thread stack of active scopes.
50 ///
51 /// @param name A static string literal identifying the scope (e.g., `"Ultralight.Layout"`).
52 /// The string should be valid for the lifetime of the library.
53 ///
54 virtual void BeginScope(const char* name) = 0;
55
56 ///
57 /// Exit the most recently entered scope on the current thread.
58 ///
59 virtual void EndScope() = 0;
60
61 ///
62 /// Called when a new rendering frame begins.
63 ///
64 /// Called automatically by the library-- users do not call this directly.
65 ///
66 /// @param frame_id Monotonic frame counter.
67 ///
68 virtual void BeginFrame(uint64_t frame_id) {}
69
70 ///
71 /// Called when a rendering frame ends.
72 ///
73 /// Called automatically by the library-- users do not call this directly.
74 ///
75 virtual void EndFrame() {}
76
77 ///
78 /// Record an instant (point-in-time) event on the timeline.
79 ///
80 /// @param name A static string literal identifying the event (e.g., `"View.LoadURL"`).
81 /// @param detail Optional context string (may be `nullptr`).
82 ///
83 virtual void EmitEvent(const char* name, const char* detail) = 0;
84
85 ///
86 /// Record a counter value.
87 ///
88 /// Called periodically with named numeric values (e.g., memory usage, object counts).
89 /// Profiling tools typically render these as line or area charts.
90 ///
91 /// @param name A static string literal identifying the counter (e.g., `"Memory.VRAM"`).
92 /// @param value The current value.
93 ///
94 virtual void EmitCounter(const char* name, int64_t value) = 0;
95
96 ///
97 /// Begin an async event that may span multiple frames.
98 ///
99 /// Unlike scopes, async events can overlap and are not bound to a single call stack.
100 /// Use these for long-running operations like page loads or resource fetches.
101 ///
102 /// @param name A static string literal identifying the event type (e.g., `"View.PageLoad"`).
103 /// @param detail Optional context string (may be `nullptr`).
104 ///
105 /// @return A non-zero event ID that must be passed to `EndEvent()` to close the span.
106 /// Returning 0 is reserved as a "no event" sentinel.
107 ///
108 virtual uint64_t BeginEvent(const char* name, const char* detail) = 0;
109
110 ///
111 /// End a previously started async event.
112 ///
113 /// @param id The event ID returned by `BeginEvent()`.
114 ///
115 virtual void EndEvent(uint64_t id) = 0;
116};
117
118///
119/// Create a Profiler implementation that writes Perfetto binary traces (.perfetto-trace).
120///
121/// The trace file is streamed to disk with bounded memory usage and is crash-safe
122/// (partial traces are always valid and loadable in https://ui.perfetto.dev).
123///
124/// @param path Output file path (e.g., "trace.perfetto-trace").
125///
126/// @return Owned Profiler pointer, or nullptr if unavailable for your platform or edition.
127/// Caller is responsible for deletion via DestroyProfilerPerfetto().
128///
130
131///
132/// Destroy a Profiler created by CreateProfilerPerfetto. Safe to call with nullptr.
133///
135
136} // namespace ultralight
137
138#endif // UL_HAS(PROFILER)
#define UExport
Definition Exports.h:22
User-defined profiling interface.
Definition Profiler.h:41
virtual void BeginFrame(uint64_t frame_id)
Called when a new rendering frame begins.
Definition Profiler.h:68
virtual void BeginScope(const char *name)=0
Enter a named profiling scope.
virtual void EmitEvent(const char *name, const char *detail)=0
Record an instant (point-in-time) event on the timeline.
virtual void EndFrame()
Called when a rendering frame ends.
Definition Profiler.h:75
virtual void EndEvent(uint64_t id)=0
End a previously started async event.
virtual uint64_t BeginEvent(const char *name, const char *detail)=0
Begin an async event that may span multiple frames.
virtual void EndScope()=0
Exit the most recently entered scope on the current thread.
virtual void EmitCounter(const char *name, int64_t value)=0
Record a counter value.
Root namespace for every public Ultralight type, function, and enumeration.
Profiler * CreateProfilerPerfetto(const char *path)
Create a Profiler implementation that writes Perfetto binary traces (.perfetto-trace).
void DestroyProfilerPerfetto(Profiler *profiler)
Destroy a Profiler created by CreateProfilerPerfetto.