Skip to main content

Measuring VxWorks Execution Time with timex() and Timestamps

·1060 words·5 mins
VxWorks Real-Time Systems Performance Profiling Embedded Systems C Programming Kernel Development
Table of Contents

Measuring VxWorks Execution Time with timex() and Timestamps

Accurately measuring execution time is essential when optimizing real-time applications on VxWorks. The timex() utility provides a convenient way to benchmark functions from the VxWorks shell or application code, while APIs such as sysTimestamp() provide significantly finer timing resolution for detailed profiling.

The appropriate timing mechanism depends on the workload and required precision. System-tick-based APIs are sufficient for coarse measurements, whereas hardware timestamp counters are better suited to short code paths, interrupt service routines, and performance-sensitive kernel code.

๐Ÿ”ง How timex() Measures Execution Time
#

The VxWorks timex() function is provided through the usrLib utility library. It executes a target function, measures the elapsed system ticks, estimates measurement overhead, and reports the resulting execution time.

Measurement workflow
#

The basic process is:

  1. Capture the current system tick count.
  2. Execute the target function.
  3. Capture the ending tick count.
  4. Measure the timing overhead separately.
  5. Subtract the estimated overhead from the measured interval.
  6. Convert the resulting tick count into a time value using the system clock frequency.
  7. Print the measurement to the VxWorks console.

The basic conversion is:

$$ \text{Execution Time (seconds)}
#

\frac{\Delta\text{ticks}}{\text{sysClkRateGet()}} $$

For example, with a 1000 Hz system clock, one tick represents approximately 1 ms. With a 100 Hz clock, the nominal tick interval is approximately 10 ms.

Because the measurement is fundamentally tied to the system tick, timex() is best suited to relatively coarse-grained benchmarking rather than nanosecond-scale profiling.

๐Ÿงฉ timex() API and Calling Convention
#

The API accepts a function pointer followed by up to eight integer arguments:

void timex(
    FUNCPTR function_name,
    int     arg1,
    int     arg2,
    int     arg3,
    int     arg4,
    int     arg5,
    int     arg6,
    int     arg7,
    int     arg8
);

The target function can therefore receive up to eight arguments through the timex() interface. On 32-bit VxWorks targets, integer parameters can also be used to pass pointer-sized values where appropriate.

Unused arguments should be initialized to 0.

For example:

timex((FUNCPTR)myWorkload,
      1000000,
      42,
      0,
      0,
      0,
      0,
      0,
      0);

This invokes:

myWorkload(1000000, 42);

The target function executes in the context of the calling task. When invoked from the VxWorks shell, this is typically the shell task rather than a dedicated benchmarking task.

๐Ÿ“Š Comparing VxWorks Timing Mechanisms
#

Timing Method Resolution Best Use Case Advantages Limitations
timex() System-tick level Quick function benchmarking Simple and shell-friendly Limited by system tick resolution
tickGet() System-tick level Long-duration task timing Lightweight kernel API Coarse for short operations
sysTimestamp() Hardware counter level Fine-grained profiling and ISR timing High-resolution measurement BSP and hardware dependent
clock_gettime() POSIX clock, typically nanosecond API Portable application profiling Standard POSIX interface Requires appropriate POSIX timer support

The reported resolution of sysTimestamp() depends on the underlying BSP and hardware timer. Its API exposes a hardware counter rather than the relatively coarse scheduler tick.

โšก High-Resolution Profiling with sysTimestamp()
#

For short execution paths, sysTimestamp() is generally more useful than timex() because it reads a high-resolution timestamp counter.

A typical measurement sequence is:

startTs = sysTimestamp();

myWorkload(1000000, 42);

endTs = sysTimestamp();

The elapsed interval is then calculated from the timestamp frequency:

$$ \text{Execution Time}
#

\frac{\text{End Timestamp} - \text{Start Timestamp}} {\text{sysTimestampFreq()}} $$

This approach avoids relying on the system scheduler tick and can expose performance differences that would be invisible to tickGet() or timex().

However, the timestamp counter is hardware and BSP dependent. Applications should therefore verify that timestamp support is available before using it as a profiling primitive.

๐Ÿงช Complete C Timing Example
#

The following example compares the convenience of timex() with a higher-resolution sysTimestamp() measurement:

#include <vxWorks.h>
#include <stdio.h>
#include <usrLib.h>
#include <sysLib.h>
#include <timestampLib.h>

/* Workload to benchmark */
void myWorkload(int loopCount, int value)
{
    volatile int i;

    for (i = 0; i < loopCount; i++) {
        value = (value * 3) ^ i;
    }
}

/* Demonstrate multiple timing mechanisms */
void testTiming(void)
{
    UINT32 startTs;
    UINT32 endTs;
    UINT32 freq;
    double timeInSeconds;

    printf("=== Method 1: timex() ===\n");

    /*
     * Execute:
     *     myWorkload(1000000, 42)
     */
    timex((FUNCPTR)myWorkload,
          1000000,
          42,
          0,
          0,
          0,
          0,
          0,
          0);

    printf("\n=== Method 2: sysTimestamp() ===\n");

    if (sysTimestampConnect(NULL, 0) == OK &&
        sysTimestampEnable() == OK) {

        freq = sysTimestampFreq();

        startTs = sysTimestamp();

        myWorkload(1000000, 42);

        endTs = sysTimestamp();

        timeInSeconds =
            (double)(endTs - startTs) / (double)freq;

        printf("Elapsed Time: %.6f seconds "
               "(%u ticks @ %u Hz)\n",
               timeInSeconds,
               (endTs - startTs),
               freq);
    }
    else {
        printf("Hardware timestamp timer is not "
               "supported by this BSP.\n");
    }
}

The two measurements serve different purposes. timex() provides a convenient baseline that can be invoked directly from the shell, while sysTimestamp() allows the same workload to be measured using the platform’s higher-resolution timestamp facility.

๐Ÿง  Practical Profiling Considerations
#

Timing a function in isolation does not necessarily represent its production execution time. VxWorks task scheduling, cache state, interrupts, branch prediction, memory contention, and compiler optimization can all affect the result.

Repeat measurements for short workloads
#

If the target function completes in only a few microseconds, measurement overhead can become significant relative to the workload itself. Repeating the operation many times and measuring the aggregate interval can produce a more stable result.

Control compiler optimization
#

A benchmark can be distorted if the compiler removes or transforms the workload. The example uses a volatile loop variable to make the loop’s observable behavior harder to eliminate, but production benchmarks should still be inspected at the generated-code level when compiler optimization matters.

Account for cache state
#

The first invocation may include instruction-cache and data-cache misses that subsequent invocations avoid. For meaningful steady-state measurements, separate cold-cache and warm-cache tests rather than treating them as equivalent.

Consider interrupt and scheduling interference
#

VxWorks is a real-time operating system, but normal execution can still be interrupted by ISRs and higher-priority tasks. For latency-sensitive benchmarks, measure multiple iterations and inspect the distribution rather than relying only on a single result.

๐ŸŽฏ Choosing the Right Timing API
#

Use timex() when the primary requirement is quick and convenient function benchmarking, especially from the VxWorks shell.

Use tickGet() when measuring relatively long-running operations where system-tick precision is sufficient.

Use sysTimestamp() when measuring short execution paths, driver routines, ISR-related code, or microarchitectural performance and the BSP provides a suitable hardware timestamp source.

Use clock_gettime() when POSIX portability and application-level timing are more important than direct access to platform-specific timestamp hardware.

For serious performance analysis, combining coarse system-level measurements with high-resolution timestamp profiling provides a more complete view of VxWorks application behavior.

Related

How to Measure CPU Usage in VxWorks with spyLib
·1554 words·8 mins
VxWorks CPU Usage SpyLib Embedded Systems Real-Time OS C Programming System Monitoring Performance Analysis
Building a VxWorks Telnet Client: Protocol, NVT Negotiation, and C Implementation
·1664 words·8 mins
VxWorks Telnet TCP NVT C Programming Embedded Systems Networking Real-Time OS
VxWorks: Check File System Capacity and Free Space
·1365 words·7 mins
VxWorks VxWorks File System DosFS HRFS Statfs Embedded Systems C Programming RTOS