Main Content

Remove Instrumentation Overheads from Execution Time Measurements

To improve execution-time profiling of generated code that runs on deterministic hardware, you can run processor-in-the-loop (PIL) simulations that automatically filter the overheads associated with code instrumentation. You can use the target hardware to estimate the average overhead value or you can specify the value manually.

Note

By default, the software filters the execution times of AUTOSAR Runtime Environment (RTE) code and functions that run within Simulink®, for example, Function Caller blocks.

Approach for Estimating and Removing Instrumentation Overhead

When you create a target connectivity configuration for PIL simulations, through an rtw.connectivity.Config subclass, you can specify functions that estimate and remove instrumentation overheads from execution-time measurements. At the start of a processor-in-the-loop (PIL) simulation, the software runs a benchmark program a specified number of times and obtains an average value for the instrumentation overheads. The benchmark program estimates the overheads for the timer API and for timer freezing and unfreezing, task, and function instrumentation code.

During the simulation, the software subtracts the average value of instrumentation overheads from the execution-time measurements. The Simulation Data Inspector and the code execution profiling report display the corrected measurement values.

This figure shows how the uncorrected and corrected timer values correspond to invocations of code sections.

The corrected timer value excludes execution time associated with instrumentation code, RTE code, and function code that runs within Simulink.

To estimate and remove instrumentation overheads from execution-time measurements, the rtw.connectivity.Config class provides these functions.

FunctionDescription

activateOverheadFiltering

obj.activateOverheadFiltering (value); activates filtering of instrumentation overheads if value is true. Deactivates overhead filtering if value is false.

isOverheadFilteringActive

obj.isOverheadFilteringActive returns true if instrumentation overhead filtering is activated. Otherwise, returns false.

runOverheadBenchmark

obj.runOverheadBenchmark(value); runs a benchmark program if value is true. Does not run the benchmark program if value is false.

isOverheadBenchmarkExecuted

obj.isOverheadBenchmarkExecuted; returns true if execution of benchmark program is complete. Otherwise, returns false.

setOverheadBenchmarkSteps

obj.setOverheadBenchmarkSteps(steps); specifies number of steps for benchmark program.

getOverheadBenchmarkSteps

steps = obj.getOverheadBenchmarkSteps returns the number of specified steps for the benchmark program.

setOverheads

obj.setOverheads(taskInstrumentationOverhead, functionInstrumentationOverhead, freezingInstrumentation); specifies the overhead values for task, function, and freezing instrumentation respectively.

getOverheads

[taskInstrumentationOverhead, functionInstrumentationOverhead, freezingInstrumentation] = obj.getOverheads; returns overhead values for task, function, and freezing instrumentation respectively.

Configure Removal of Instrumentation Overhead

When you set up target connectivity for processor-in-the-loop (PIL) simulations, configure the removal of the instrumentation overheads through an rtw.connectivity.Config subclass. For example, this code shows how you can run the benchmark program.

classdef overheadConnectivityConfig < rtw.connectivity.Config
  methods
    function this = customConnectivityConfig(componentArgs)
            
      % Create builder
      targetApplicationFramework = ...
        mypil.TargetApplicationFramework(componentArgs);
      builder = rtw.connectivity.MakefileBuilder(componentArgs, ...
        targetApplicationFramework, '');
            
      % Create launcher
      launcher = mypil.Launcher(componentArgs, builder);
            
      % Set up communication       
      hostCommunicator = rtw.connectivity.RtIOStreamHostCommunicator(...
                         componentArgs, ...
                         launcher, ...
                         rtiostreamLibTCPIP);     

      % Call super class constructor to register components
        this@rtw.connectivity.Config(componentArgs,...
                                     builder,...
                                     launcher,...
                                     hostCommunicator);
            
      % Register hardware-specific timer, which enables
      % code execution profiling. This example uses a 
      % timer for the host platform.
      timer = coder.profile.crlHostTimer();
      this.setTimer(timer);

      % Specify removal of profiling instrumentation overheads
      this.activateOverheadFiltering(true);
      this.runOverheadBenchmark(true);
      this.setOverheadBenchmarkSteps(50);

    end
  end
end

Instead of running the benchmark program, you can use setOverheads to provide your values for instrumentation overheads.

    ...

    % Remove instrumentation overhead using manually specified values
    this.activateOverheadFiltering(true);
    this.setOverheads (taskInstrumentationOverhead, ...
      functionInstrumentationOverhead, freezingInstrumentation);

    ...

Retrieve Benchmark Results

When a PIL simulation is complete, you can retrieve benchmark results from the variable that you specify in the Code Generation > Verification > Workspace variable field (CodeExecutionProfileVariable), for example, myExecutionProfile.

benchmarkResults = myExecutionProfile.getOverheadBenchmarkData();

benchmarkResults is a structure that contains code instrumentation overhead values.

>> benchmarkResults
 ans = 
 struct with fields:
 TimestampOverhead: [1×1 struct]
 TaskOverhead: [1×1 struct]
 FunctionOverhead: [1×1 struct]
 FreezingOverhead: [1×1 struct]

>> benchmarkResults.TaskOverhead
 ans = 
 struct with fields:
 Data: [1×100 uint64]
 NumSamples: 100
 Average: 45.2800

See Also

Related Topics