Profiler¶
The Profiler provides an interface for logging and visualizing data for performance measurements, while the system is running. You can use the module to profile Event Manager events or custom events. The output is provided via RTT and can be visualized in SEGGER SystemView or in a custom Python backend.
Note
Currently, you can register and profile up to 32 event types.
See the Profiler sample for an example on how to use the Profiler.
Configuration¶
Apart from standard configuration parameters, there is one required setting:
CONFIG_PROFILER
Set this option to add the Profiler source code to the application. If you use the Event Manager, you can also set this option by selecting
CONFIG_DESKTOP_EVENT_MANAGER_PROFILER_ENABLED
.
Call profiler_init()
during the application start to initialize the Profiler.
If you set CONFIG_DESKTOP_EVENT_MANAGER_PROFILER_ENABLED
, the Profiler is automatically initialized when you initialize the Event Manager.
Profiling custom events¶
To profile custom events, you must register them using profiler_register_event_type()
.
The following code example shows how to register event types:
static const char *data_names[] = {"value1", "value2"};
static const enum profiler_arg data_types[] = {PROFILER_ARG_U32,
PROFILER_ARG_S32};
no_data_event_id = profiler_register_event_type("no data event", NULL,
NULL, 0);
data_event_id = profiler_register_event_type("data event", data_names,
data_types, 2);
After registering the types, you can send information about event occurrences using the following functions:
profiler_log_start()
- Start logging.profiler_log_encode_u32()
- Add data connected with the event (optional).profiler_log_send()
- Send profiled data.
It is good practice to wrap the calls in one function that you then call to profile event occurrences. The following code example shows a function for profiling an event with data:
static void profile_data_event(uint32_t val1, int32_t val2)
{
struct log_event_buf buf;
profiler_log_start(&buf);
/* Profiling data connected with an event */
profiler_log_encode_u32(&buf, val1);
profiler_log_encode_u32(&buf, val2);
profiler_log_send(&buf, data_event_id);
}
Note
The event ID and the data that is profiled with the event must be consistent with the registered event type. The data for every data field must be provided in the correct order.
Supported backends¶
The Profiler supports different backends to visualize the output data. Currently, the two supported backends are SEGGER SystemView and a custom backend. Both share the same API and communicate with the host using RTT.
SEGGER SystemView¶
Select this backend to register the Profiler as a middleware module for SEGGER SystemView. You can then use a dedicated visualization tool to visualize events.
See the SEGGER SystemView website for more information.
Set CONFIG_PROFILER_SYSVIEW
to enable this backend.
Custom backend¶
Select the custom backend to use dedicated tools written in Python for event visualization, analysis, and calculating statistics.
To save profiling data, the tools use csv files (for event occurrences) and json files (for event descriptions).
The scripts can be found under scripts/profiler/
in the nRF Connect SDK folder structure.
Set CONFIG_PROFILER_NORDIC
to enable this backend.
To use the tools, run the scripts on the command line:
python3 data_collector.py 5 test1
Connects to the device via RTT, receives profiling data, and saves it to files. As command line arguments, provide the time for collecting data (in seconds) and a dataset name.
python3 plot_from_files.py test1
Plots events from the dataset that is provided as the command line argument.
python3 real_time_plot.py test1
Connects to the device via RTT, plots data in real time, and saves the data. As command line arguments, provide a dataset name.
python3 merge_data.py test_p sync_event_p test_c sync_event_c test_merged
Combines data from test_p and test_c datasets into one dataset (test_merged). Provides clock drift compensation based on synchronization events: sync_event_p and sync_event_c. This enables you to observe times between events for the two connected devices. As command line arguments, provide names of events used for synchronization for a Peripheral (sync_event_p) and a Central (sync_event_c), as well as names of datasets for: the Peripheral (test_p), the Central (test_c), and the merge result (test_merged).
Visualization¶
When running plot_from_files.py
or real_time_plot.py
, the profiled events are visualized in a GUI window.
When displaying Event Manager events, submissions are marked as dots. Processing of the events is displayed as rectangles, visualizing the processing time.
Use the start/stop button below the plot to pause or resume real time plot translation. Scroll to zoom in or out. When paused, scrolling zooms to the cursor location. When plotting in real time, scrolling zooms to the right edge of the plot. Use the middle mouse button to mark an event submission or processing for tracking, and to display the event data.
When plotting is paused, you can click and drag with the left mouse button to pan the plot. Click the left or right mouse button to place a vertical line at the cursor location. When two lines are present, the application measures the time between them and displays it.
Shell integration¶
The Profiler is integrated with Zephyr’s Shell module. When the shell is turned on, an additional subcommand set (profiler) is added.
This subcommand set contains the following commands:
- list
Show a list of profiled event types. The letters “E” or “D” indicate if profiling is currently enabled or disabled for a given event type.
- enable or disable
Enable or disable profiling. If called without additional arguments, the command applies to all event types. To enable or disable profiling for specific event types, pass the event type indexes (as displayed by list) as arguments.
API documentation¶
include/profiler.h
subsys/profiler/
-
group
profiler
Profiler.
Defines
-
CONFIG_MAX_NUMBER_OF_CUSTOM_EVENTS
¶ Maximum number of custom events.
Enums
Functions
-
int
profiler_init
(void)¶ Initialize the Profiler.
- Return Value
0
: If the operation was successful.
-
void
profiler_term
(void)¶ Terminate the Profiler.
-
const char *
profiler_get_event_descr
(size_t profiler_event_id)¶ Retrieve the description of an event type.
- Return
Event description.
- Parameters
profiler_event_id
: Event ID.
-
static inline bool
is_profiling_enabled
(size_t profiler_event_id)¶ Check if profiling is enabled for a given event type.
- Return
Logical value indicating if the event type is currently profiled.
- Parameters
profiler_event_id
: Event ID.
-
uint16_t
profiler_register_event_type
(const char *name, const char **args, const enum profiler_arg *arg_types, uint8_t arg_cnt)¶ Register an event type.
- Warning
This function is thread-safe, but not safe to use in interrupts.
- Return
ID assigned to the event type.
- Parameters
name
: Name of the event type.args
: Names of data values sent with the event.arg_types
: Types of data values sent with the event.arg_cnt
: Number of data values sent with the event.
-
void
profiler_log_start
(struct log_event_buf *buf)¶ Initialize a buffer for the data of an event.
- Parameters
buf
: Pointer to the data buffer.
-
void
profiler_log_encode_u32
(struct log_event_buf *buf, uint32_t data)¶ Encode and add data to a buffer.
- Warning
The buffer must be initialized with profiler_log_start before calling this function.
- Parameters
data
: Data to add to the buffer.buf
: Pointer to the data buffer.
-
void
profiler_log_add_mem_address
(struct log_event_buf *buf, const void *mem_address)¶ Encode and add the event’s address in memory to the buffer.
This information is used for event identification.
- Warning
The buffer must be initialized with profiler_log_start before calling this function.
- Parameters
buf
: Pointer to the data buffer.mem_address
: Memory address to encode.
-
void
profiler_log_send
(struct log_event_buf *buf, uint16_t event_type_id)¶ Send data from the buffer to the host.
This function only sends data that is already stored in the buffer. Use profiler_log_encode_u32 or profiler_log_add_mem_address to add data to the buffer.
- Parameters
event_type_id
: Event type ID as assigned to the event type when it is registered.buf
: Pointer to the data buffer.
Variables
-
uint32_t
profiler_enabled_events
¶ Set of flags for enabling/disabling profiling for given event types.
-
uint8_t
profiler_num_events
¶ Number of event types registered in the Profiler.
-
struct
log_event_buf
¶ - #include <profiler.h>
Buffer required for data that is sent with the event.
-