Using the Performance service¶
The Performance service continuously measures runtime performance metrics from the Kanzi Engine and stores them as profiler samples. These metrics are exported to the trace file by the Trace service, where they appear as counter tracks in the Perfetto trace viewer. The service provides built-in metrics for frame timing, rendering statistics, resource usage, and scheduling, and you can register custom metrics through the API.
Platform support¶
The Performance service builds from sources on all Kanzi target platforms supported by this release. All built-in metrics are platform-independent.
How the Performance service works¶
The Performance service samples the current values from the Kanzi Engine periodically and stores each measurement in a profiler.
On Kanzi 3.6 there is no MainLoopScheduler; the service drives periodic sampling through the engine message-dispatcher timer (addTimerHandler) and reads render statistics at render time.
Each measurement is stored in a PerformanceInfoProfiler instance that holds a kanzi::AbstractProfiler::Value sample — a float for metrics such as FPS and frame time, or an integer for counts.
The Performance service defines its own profiling category (PROFILING_CATEGORY_PERFORMANCEINFO) which is always enabled at compile time, independent of the build configuration of the Kanzi Engine.
This means performance metrics are included in the trace in all build configurations (Debug, Release, and Profiling).
Built-in metrics¶
The following metrics are measured automatically when the Performance service is enabled:
Frame timing
Frames per second (FPS)
App frames per second (requires Application registration)
Frametime Total (ms) – Last frame duration
Frametime Animation (ms) – Timeline clock duration
Rendering statistics
Batch Count – Draw call batches per frame
Triangle Count – Triangles rendered per frame
TextureSwitch Count – GPU texture binding changes
FramebufferSwitch Count – Framebuffer binding changes
ShaderSwitch Count – Shader program binding changes
Uniforms sent Count – Uniform buffer updates
Resource management
Resource Count – Total loaded resources
Resource CPU Mem – CPU-side memory usage
Resource GPU Mem – GPU-side memory usage
Resource AcquireQueue Size – Pending resource acquisitions
Resource DeployQueue Size – Resources waiting for deployment
Resource LoadQueue Size – Resources in loading queue
Animation and scheduling
Animations Active Count – Currently active timeline playbacks
Animations Total Count – Total timeline playback instances
Timers Count – Active timer subscriptions (Kanzi 3.6.8+)
Tasks Total Count – Total recurring task count (Kanzi 3.6.8+; not available in DLL / shared-library builds, so absent when Kanzi Monitor is loaded as a DLL on Windows
*_DLLor as an.soon Android)
Viewing performance metrics in the trace¶
The performance metrics are primarily consumed through the trace output:
Enable the Performance service (
ServicePerformanceEnabled, enabled by default).Run the application and trigger a trace write. See Using the Profiling Trace service.
Open the trace file in the Perfetto trace viewer. The performance metrics appear as counter tracks.
The perfinfo2 command provides a quick FPS reading from the console.
Trace integration¶
The Performance service registers a collection task with the Trace service. When a trace is written, all performance profiler samples are exported as counter events on the main thread. In the Perfetto trace viewer, each metric appears as a separate counter track showing the value over time.
Adding custom metrics¶
You can register custom performance profilers through the Performance service profiler registry.
A PerformanceInfoProfiler stores a kanzi::AbstractProfiler::Value sample, so a single metric can carry either a float (for example, FPS or a duration) or an integer count. Custom profilers appear alongside the built-in metrics in the trace output.
To create and register a custom profiler:
KanziMonitorModule* module = getKanziMonitorModule(domain);
PerformanceService* perfService = module->getPerformanceService();
// Create a custom profiler.
PerformanceInfoProfilerSharedPtr myProfiler = PerformanceInfoProfiler::create(
"My Custom Metric",
kzProfilingGetCategoryRuntimeReference(PROFILING_CATEGORY_PERFORMANCEINFO),
PROFILING_PERFORMANCEINFO_DEFAULT_BUFFER_SIZE);
// Register it in the Performance service profiler registry.
perfService->getPerformanceInfoProfilerRegistry().registerProfiler(myProfiler);
To sample it periodically, schedule a timer on the engine message dispatcher (Kanzi 3.6 has no MainLoopScheduler) and add a profiler sample from the handler:
kanzi::TimerSubscriptionToken token = addTimerHandler(
domain->getMessageDispatcher(),
kanzi::chrono::milliseconds(500),
KZU_TIMER_MESSAGE_MODE_REPEAT_BATCH,
bind(&MyPlugin::measureMyMetric, this, kanzi::placeholders::_1));
The built-in metrics in src/kpt_service_performance.cpp are the reference implementation for creating profilers, storing float and integer samples, and driving them from a timer.
Reading profiler data¶
You can query the profiler registry to find profilers by name and read their current values:
KanziMonitorModule* module = getKanziMonitorModule(domain);
PerformanceService* perfService = module->getPerformanceService();
auto& registry = perfService->getPerformanceInfoProfilerRegistry();
// Find a profiler by name.
auto it = std::find_if(
registry.beginProfilers(), registry.endProfilers(),
[](AbstractProfilerSharedPtr p) {
return p->getName() == "My Custom Metric";
});
if (it != registry.endProfilers())
{
AbstractProfilerSharedPtr profiler = *it;
// Read aggregate data (for example, average value at field index 5).
string fieldName = profiler->getAggregateDataFieldName(5);
AbstractProfiler::Value value = profiler->getAggregateDataFieldValue(5);
if (AbstractProfiler::getDataType(value) == AbstractProfiler::DataTypeFloat)
{
float floatValue = get<float>(value);
}
}
This is useful for displaying custom metrics on-screen, logging them, or using them to drive application behavior.
Using performance watchers¶
Performance watchers let you attach threshold-based triggers to metrics. When a metric crosses the threshold, the watcher automatically executes a command and then deactivates (one-shot behavior). This prevents repeated triggers while the metric stays beyond the threshold.
The primary use case is automated trace capture: when FPS drops below 30, write a trace file.
Note
Watchers evaluate the latest sampled value of a metric, not a running average.
Adding a watcher¶
Use the watch add command to create a watcher:
watch add <metric> <below|above> <threshold> <command> [args]
For example:
watch add fps below 30 trace
watch add batches above 500 trace
watch add frametime above 33.3 trace
The watcher evaluates the metric every frame. When the condition is met, it executes the command and deactivates. A deactivated watcher shows as [triggered] in the list.
Viewing available metrics¶
Use watch metrics to see all available metric names and their current values:
watch metrics
Alias |
Description |
|---|---|
|
Frames per second |
|
Application frames per second |
|
Frame time total (ms) |
|
Frame time animation (ms) |
|
Draw call batch count |
|
Triangle count |
|
Texture switch count |
|
Framebuffer switch count |
|
Shader switch count |
|
Uniform send count |
|
Total resource count |
|
CPU memory usage (bytes) |
|
GPU memory usage (bytes) |
|
Active animation count |
Managing watchers¶
List all watchers and their status:
watch list
Example output:
#1 fps below 30 -> trace [active]
#2 batches above 500 -> trace [triggered]
Remove a specific watcher by its ID:
watch remove 1
Remove all watchers:
watch clear
Re-arm a triggered watcher so it can fire again:
watch reset 2
Example workflow¶
A typical workflow for capturing a trace when FPS drops:
watch add fps below 30 trace Add the watcher
watch list Verify the watcher status
watch reset 1 Re-arm the watcher after it fires
When a watcher triggers, it logs the event and the command output at Info level.
Available commands¶
Command |
Description |
|---|---|
|
Shows Kanzi Monitor Performance Service information. |
|
Gets and sets the PerformanceInfo level. Usage: |
|
Manages performance watchers. Usage: |
The perfinfo2 command displays the current FPS as measured by the Performance service.
Note
In Monitor 1.9.0, the Command Processor service also registers a built-in perfinfo command that reports the main-loop last frame duration. That command depends on MainLoopScheduler, which Kanzi 3.6 does not provide, so it is not available in this release (see Known issues) — perfinfo2 is the console FPS/frame-time command here. For the application’s own FPS reading and its PerformanceInfo level, use the appfpsinfo command (see Using the Command Processor service).