emmtrix
Performance
Estimator (ePE)
Know Your Code’s Runtime – Without Running It
Static analysis for fast, detailed performance insights.
Performance estimation was never easier. With emmtrix Performance Estimator (ePE), developers can gain fast and accurate insights into the runtime behavior of their C code — without ever executing it. Unlike traditional simulation or hardware-based measurements, ePE applies static timing analysis early in the development process — and can be used at any later stage as well and typically delivers results up to six months ahead of a standard automotive HIL setup. The analysis runs within minutes on the developer’s PC or can be integrated into a continuous integration (CI) system. The determined execution times are fully deterministic, offering consistent and reproducible results — a major advantage over measurement-based approaches, which can be influenced by non-deterministic runtime effects. This enables automated, project-accompanying performance tracking, allows for continuous monitoring of timing budgets, and makes it easy to evaluate runnables or SWCs even before full system integration.
A standout feature of ePE is its seamless integration with code generated by TargetLink or Embedded Coder. Thanks to its static approach, ePE can assess even the smallest code fragments without measurement overhead. This enables precise timing insights down to the Simulink block level, empowering function developers with detailed understanding of their model’s performance — even in early development phases.
Understanding Our Static Performance Estimation
Static performance estimation is a method for predicting the runtime behavior of software without executing it. This technique analyzes the program’s structure and instructions to estimate how long it will take to execute on a given processor.
Our method relies on a fundamental principle: for each code block, we determine its execution frequency and multiply this frequency by the block’s execution cost. The execution frequency is statically inferred from the control-flow structure of the code—for example, loops, conditional branches, and function calls. This allows us to approximate how often a block is executed during a typical run without requiring any runtime measurements. The execution cost of each block is either estimated by summing the costs of corresponding C statements at source level or, alternatively, by modeling the processor pipeline based on the assembly code generated by the target compiler.
To provide a comprehensive view of a program’s timing behavior, our approach calculates the minimum, maximum, and average execution time. For the average case, conditional constructs such as if
statements are initially evaluated using a default 50% branch probability. This default can be overridden by the user to reflect more accurate, domain-specific knowledge. In the minimum and maximum cases, the tool evaluates the control paths that lead to the shortest or longest execution times, respectively. This multi-perspective analysis helps identify best- and worst-case scenarios and offers deeper insights into runtime variability under different input conditions.
However, the static determination of execution frequencies—without executing the program—is a general and well-known challenge in software performance analysis. To address this, we offer a set of complementary techniques that work together to improve estimation accuracy while minimizing manual effort:
- Constant propagation across functions: Variable values are inferred and propagated throughout the codebase, including across function boundaries. This enables the tool to resolve value-dependent control flows—such as loop bounds and conditions within
if
statements—using known or inferred constants. By understanding variable values across the program, the execution frequencies of code blocks can be determined more accurately. - User-provided configuration data lets users specify concrete values or value ranges for function parameters and global variables. These configurations help model application-specific scenarios more realistically and refine the estimation of loop iterations and control-flow decisions. Such data can be extracted from machine-readable exchange formats, such as JSON, A2L (ASAM MCD-2 MC), or DCM (ASAM MCD-2 DCM) files, allowing seamless integration into existing development workflows.
- Manual specification is available as an option for users to directly define control-flow probabilities and loop bounds where automation alone is insufficient. This provides full control for critical sections of code.
- Analysis of ‘unknowns’ comes into play when values cannot be resolved statically. Constructs marked as unknowns are analyzed for their impact on the overall average execution time. This sensitivity analysis helps users prioritize which values to annotate, so that even minimal input can lead to a significant gain in accuracy.
- Use of host-level profiling data: When available, empirical execution data collected from host-based profiling can be used to inform or override statically inferred execution frequencies.
These techniques form a cohesive strategy that allows developers to efficiently refine timing estimations—whether by leveraging automation, applying targeted annotations, or responding to feedback from the analysis itself.
By applying this frequency-cost multiplication for all blocks in a program, we can aggregate the results to estimate the total runtime. This approach supports a fine-grained understanding of performance hotspots and facilitates early feedback for developers.
Processor Pipeline:
Instruction Fetch
FETCH
Instruction Decode
DECODE
Shift + ALU
EXECUTE
Memory Access
MEMORY
Register Write
WRITE
Features
- Automatic generation of reports and visualization for more detailed information
- Confidence levels for classification of results
- Easy to integrate into the development workflow
- Fast evaluation for different target platforms
- Static performance estimation based on C code or assembly code
- Integration of simulators or hardware profiling into your workflow
Your Benefits
- Performance estimation early in the development process
- Continuous monitoring of performance changes during the development
- Comparison of performance for different or heterogeneous target platforms
- Detailed information to better understand the timing behavior of your application
- Detect high-runners or critical parts of you software application
- Estimate the core utilization to optimize runnable/task to core mappings
Intuitive Visualization
Figure 1: Visualization of the Performance Estimation
The result of the performance estimation can be visualized using our interactive and zoomable hierarchical program view. The X-axis represents the time, therefore the width of each block depends on the actual duration. On the Y-axis, the control structure of the program can be seen. Additional levels are added for structures like function calls, loops or conditions.
Figure 2: Analyzing Assembler Code
To enhance our static performance estimation solution, the emmtrix tools take applied compiler optimizations into consideration by analyzing assembler code. Together with a model of the processor pipeline, the actual timing behavior of the program on the selected hardware can be predicted with significantly higher accuracy. The advanced mapping between C and assembler code is accessed directly from the GUI and can be used for further inspection.
Some Supported Platforms
emmtrix Performance Estimator has already a wide range of supported target platforms ranging from general-purpose processors (e.g. ARM Cortex-A series or X86) to special-purpose microcontrollers (e.g. Infineon Aurix family). In general, the performance estimation can be easily adapted and customized to provide basic supoprt for new processor architectures. More complex and accurate hardware models with respect to the processor pipeline can be supported on demand.
Support
For more information on emmtrix Performance Estimator or to request a demo, a chat or a meeting use our contact form or get directly in touch. We’re looking forward to hearing from you!
