Part VII: Profiling

This chapter covers the kernel’s timing characteristics. Unlike the Part VI: Memory Footprint figures, which are fixed at build time, these have to be measured on the target — they depend on the exact hardware and build.

Note

Every timing figure depends on the CPU core, clock frequency, compiler and optimisation level, and the cache / flash wait-state configuration. Record those conditions next to any measurement; a cycle count without them is not comparable.

Enabling instrumentation

Build with QRT_CFG_PERF_ENABLE to have the kernel measure its own worst-case execution time (WCET). It records the longest time taken by each system call, by a context switch and by the SysTimer handler, and the longest it holds interrupts off. Each measured operation adds a small, fixed cost, so leave the option disabled in production builds.

Measurement needs a CPU cycle counter. Every supported core has one, except Cortex-M0+ and Cortex-M23 have none.

Reading the results

Read the figures with qrt_perf_read(), which writes a plain-text report into a buffer you supply:

#include "qrt.h"

char buf[1024];

qrt_perf_read(buf, sizeof(buf));
fputs(buf, stdout);

Each line is a name and its worst-case cycle count. The exercised system calls come first, then context_switch, irq_mask and systimer. For example:

sem_wait         1234
mutex_lock        456
kernel_boot      8901
context_switch    312
irq_mask           48
systimer          176

The report is truncated to fit the buffer and is always NULL-terminated; qrt_perf_read() returns the number of bytes written.

Note

Halting the core in a debugger while instrumentation is enabled does not corrupt the reported worst-case figures.

Worst-case figures

Measured on an ARM Cortex-M3 at 64 MHz. The system-call and context-switch figures are not skewed by an interrupt landing mid-call.

Three kernel-wide figures accompany the per-call system-call times:

  • context_switch — saving the outgoing thread’s context and restoring the next.

  • irq_mask — the longest the kernel keeps interrupts disabled; nothing can be serviced in that window, so it bounds the kernel’s contribution to interrupt latency.

  • systimer — the longest run of the SysTimer handler, which runs at the highest priority and so holds off every lower-priority interrupt while it executes, adding to their latency.

Figure

Cycles

Time

context_switch

—

—

irq_mask

—

—

systimer

—

—