Introduction #
This post shows how to measure and visualize the real-time performance of VxWorks, explains why those measurements matter, and walks you through reproducing the tests yourself. You’ll get:
- A short explanation of why real-time performance matters.
- A replicable test kit (VxWorks C test program) to measure:
- Interrupt latency
- Context switch time
- Timer precision
- A Python plotting script to turn console logs into histograms and timing plots.
- Step-by-step instructions to run comparable tests on Linux (with/without PREEMPT-RT) and FreeRTOS.
- Sample/representative results and publication-ready charts for your experiment.
Why real-time performance matters #
- In hard real-time systems, missing a deadline may cause system failure. Key metrics:
- Interrupt latency — time from event to ISR entry.
- Context switch time — time to switch execution between tasks.
- Timer precision — accuracy of periodic tasks.
- A real RTOS (like VxWorks) provides deterministic behaviour with low jitter → essential for avionics, industrial control, robotics, and other safety-critical domains.
Test hardware & software (recommended) #
- Hardware target: modern embedded CPU or x86 target (example: Intel Core i7-class development board).
- VxWorks: VxWorks 7 (timestamp/timer APIs available).
- Host tools: Wind River Workbench (build & console), Python 3 with matplotlib on host PC.
- Optional: logic analyzer / oscilloscope for hardware-accurate interrupt timing.
VxWorks Real-Time Performance Test Kit #
- VxWorks C Test Program (save as performanceTest.c)
This program demonstrates interrupt latency, a semaphore-based context-switch test, and a periodic timer callback for timer precision.
/* performanceTest.c
Compile & link in VxWorks build system. Adapt interrupt vector and
timestamp APIs to your BSP if required.
*/
#include <vxWorks.h>
#include <taskLib.h>
#include <semLib.h>
#include <intLib.h>
#include <sysLib.h>
#include <tickLib.h>
#include <timers.h>
#include <stdio.h>
#include <time.h>
#include <drv/timer/timestampDev.h>
SEM_ID sem1, sem2;
volatile UINT64 irqStartTime, irqEndTime;
volatile BOOL irqTriggered = FALSE;
/* ISR for latency measurement */
void latencyISR(void)
{
irqEndTime = vxTimestamp();
irqTriggered = TRUE;
}
/* Interrupt latency test */
void testInterruptLatency(void)
{
UINT32 freq = sysTimestampFreq();
irqTriggered = FALSE;
/* Replace 0x60 with the vector appropriate to your BSP or use
a hardware timer to trigger an external interrupt. */
intConnect(INUM_TO_IVEC(0x60), (VOIDFUNCPTR)latencyISR, 0);
intEnable(0x60);
irqStartTime = vxTimestamp();
/* Trigger interrupt in a BSP-specific way; sysIntGen shown as example */
sysIntGen(0x60);
while (!irqTriggered) taskDelay(1);
double latency_us = ((double)(irqEndTime - irqStartTime) / freq) * 1e6;
printf("Interrupt Latency: %.2f microseconds\n", latency_us);
}
/* Context switch tasks */
void highPriorityTask(void)
{
while (1)
{
semTake(sem1, WAIT_FOREVER);
UINT64 t1 = vxTimestamp();
semGive(sem2);
double switchTime = ((double)(vxTimestamp() - t1) / sysTimestampFreq()) * 1e6;
printf("Context Switch Time: %.2f microseconds\n", switchTime);
}
}
void lowPriorityTask(void)
{
while (1)
{
semGive(sem1);
semTake(sem2, WAIT_FOREVER);
}
}
/* Timer callback to measure period */
void timerCallback(timer_t timerId, int arg)
{
static UINT64 lastTime = 0;
UINT64 now = vxTimestamp();
if (lastTime != 0)
{
double period_us = ((double)(now - lastTime) / sysTimestampFreq()) * 1e6;
printf("Timer Period: %.2f microseconds\n", period_us);
}
lastTime = now;
}
void testTimerPrecision(void)
{
struct sigevent evp;
timer_t tid;
struct itimerspec ts;
evp.sigev_notify = SIGEV_THREAD;
evp.sigev_value.sival_int = 0;
evp.sigev_notify_function = (void (*)(union sigval))timerCallback;
evp.sigev_notify_attributes = NULL;
timer_create(CLOCK_REALTIME, &evp, &tid);
ts.it_value.tv_sec = 0;
ts.it_value.tv_nsec = 1000000; // 1 ms
ts.it_interval = ts.it_value;
timer_settime(tid, 0, &ts, NULL);
}
/* Entry: run the tests */
void vxworksPerformanceTest(void)
{
if (vxTimestampEnable() != OK)
{
printf("Timestamp not supported on this platform\n");
return;
}
printf("VxWorks Real-Time Performance Test\n");
/* 1) Interrupt latency (single-shot) */
testInterruptLatency();
/* 2) Context switch test */
sem1 = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
sem2 = semBCreate(SEM_Q_PRIORITY, SEM_EMPTY);
taskSpawn("tHigh", 100, 0, 4096, (FUNCPTR)highPriorityTask, 0,0,0,0,0,0,0,0,0,0);
taskSpawn("tLow", 101, 0, 4096, (FUNCPTR)lowPriorityTask, 0,0,0,0,0,0,0,0,0,0);
/* 3) Timer precision: periodic prints */
testTimerPrecision();
}
- Python Plotting Script (plot_vxworks_performance.py)
Copy the VxWorks console output into vxworks_performance.log
. Then run this on your host machine to generate histograms and a timer-accuracy plot.
import re
import matplotlib.pyplot as plt
LOG_FILE = "vxworks_performance.log"
interrupt_latencies = []
context_switch_times = []
timer_periods = []
re_interrupt = re.compile(r"Interrupt Latency:\s*([\d.]+)\s*microseconds")
re_context = re.compile(r"Context Switch Time:\s*([\d.]+)\s*microseconds")
re_timer = re.compile(r"Timer Period:\s*([\d.]+)\s*microseconds")
with open(LOG_FILE, "r") as f:
for line in f:
if m := re_interrupt.search(line):
interrupt_latencies.append(float(m.group(1)))
elif m := re_context.search(line):
context_switch_times.append(float(m.group(1)))
elif m := re_timer.search(line):
timer_periods.append(float(m.group(1)))
plt.figure(figsize=(8, 5))
plt.hist(interrupt_latencies, bins=20)
plt.title("Interrupt Latency Distribution")
plt.xlabel("Latency (microseconds)")
plt.ylabel("Frequency")
plt.grid(True, linestyle="--", alpha=0.6)
plt.savefig("interrupt_latency_histogram.png", dpi=300)
plt.close()
plt.figure(figsize=(8, 5))
plt.hist(context_switch_times, bins=20)
plt.title("Context Switch Time Distribution")
plt.xlabel("Time (microseconds)")
plt.ylabel("Frequency")
plt.grid(True, linestyle="--", alpha=0.6)
plt.savefig("context_switch_histogram.png", dpi=300)
plt.close()
plt.figure(figsize=(8, 5))
plt.plot(timer_periods, marker='o', markersize=3, linewidth=1)
plt.title("Timer Period Accuracy (1 ms Target)")
plt.xlabel("Sample Number")
plt.ylabel("Period (microseconds)")
plt.grid(True, linestyle="--", alpha=0.6)
plt.savefig("timer_period_plot.png", dpi=300)
plt.close()
print("Plots saved.")
Comparing with Linux & FreeRTOS #
Linux (no RT patch)
Install rt-tests
and use cyclictest
:
sudo apt install rt-tests
sudo cyclictest -t1 -p99 -n -i1000 -l10000
- Expect occasional spikes (50–200 µs or larger under heavy load).
Linux (PREEMPT-RT)
Boot a PREEMPT-RT kernel and run cyclictest
again.
- Typical improvement: 10–20 µs ranges, still higher jitter than hard RTOSes.
FreeRTOS
On bare-metal MCUs, reimplement the semaphore / ISR tests:
- Use hardware microsecond timer.
- Use
xSemaphoreTake/xSemaphoreGive
for context-switch timing. - Typical FreeRTOS numbers vary by MCU clock — often in the low microseconds, but more variable under load.
Representative Results
These are representative/sample numbers used in the example plots and table to help readers compare systems. Actual numbers depend heavily on hardware, BSP, and system load.
OS | Interrupt Latency (avg) | Max Jitter | Context Switch Time (avg) |
---|---|---|---|
VxWorks | 1.3 µs | ±0.1 µs | 3.8 µs |
FreeRTOS | 2–5 µs | ±1 µs | 4–8 µs |
Linux (no RT) | 50–200 µs | ±100 µs | 5–20 µs |
Linux RT | 10–20 µs | ±5 µs | 5–10 µs |
Visuals
The two plots I generated for comparison (based on representative/simulated datasets):
-
Interrupt Latency Histogram
-
Latency & Jitter Box Plot
If you’d like datasets that precisely reflect your hardware, run the VxWorks test, save
vxworks_performance.log
, and re-run the Python plot script above.
Tips & Best Practices for Reproducible Results #
- Run tests on an idle system for baseline numbers; then repeat under controlled load to show robustness.
- Use a hardware trigger + logic analyzer for the most accurate interrupt timing.
- Make sure timestamps use a high-resolution hardware timer (vxTimestamp() on VxWorks).
- Document the exact BSP, CPU model, kernel/firmware versions, and compile flags.
Conclusion #
This combined kit (VxWorks C test + Python plotter + comparison guide) gives you everything you need to measure and publish credible real-time performance results. The generated visuals make it easy to show how VxWorks compares to Linux and FreeRTOS in terms of latency and jitter.