Skip to main content

Measuring Real Time Performance With VxWorks

·1035 words·5 mins
VxWorks Real Time Performance
Table of Contents

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
#

  1. 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();
}
  1. 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

    Interrupt Latency Histogram

  • Latency & Jitter Box Plot

    Latency & Jitter Boxplot

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.

Related

Design and Implementation of VxWorks NandFlash Boot on S3C2440
·876 words·5 mins
VxWorks S3C2440 ARM9
CAN Programming Under VxWorks
·642 words·4 mins
CAN VxWorks
The Development History of VxWorks
·493 words·3 mins
VxWorks Development History