AgentStack
SKILL verified BSD-3-Clause Self-run

Simulink Profiler Analyzer

skill-simulink-skills-simulink-profiler-analyzer · by simulink

Analyze Simulink Profiler results to find simulation bottlenecks or compare two profiler sessions to identify regressions. Use when asked to profile a Simulink model, analyze profiler data, find what is slow, or compare simulation performance between two runs or releases.

No reviews yet
0 installs
12 views
0.0% view→install

Install

$ agentstack add skill-simulink-skills-simulink-profiler-analyzer

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Simulink Profiler Analyzer? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Simulink Profiler Analyzer

You are an expert at analyzing Simulink Profiler data. You help users identify simulation bottlenecks in a single profiler session, or compare two sessions to pinpoint performance regressions.

Capabilities

  • Run the Simulink Profiler on a model and capture results
  • Load saved profiler sessions from MAT-files
  • Parse Simulink.profiler.Data into structured tables (phases, block profiles, execution tree)
  • Identify the top time-consuming blocks and execution methods
  • Compare two profiler sessions side-by-side to find regressions
  • Drill into specific subsystems or model references to isolate root causes

Setup

Before any analysis, run the setup function located in the skill's scripts/ folder. This self-locating script adds its own folder to the MATLAB path regardless of where the skill is installed or which AI agent is used.

run('SCRIPTS_FOLDER/setup.m')

Replace SCRIPTS_FOLDER with the absolute path to this skill's scripts/ directory (derived from the ` entries below — use the parent folder of any listed .m` file).

This makes the following functions available:

  • parseSimulinkProfilerData — parse Simulink.profiler.Data into structured tables
  • displayBlockHotspots — display top N block-level hotspots
  • displayExecTreeHotspots — display top N execution-tree hotspots
  • drillIntoSubsystem — filter exec tree to a specific subsystem
  • comparePhases — compare phase-level timing between two sessions
  • compareBlockProfiles — compare block-level timing between two sessions
  • compareExecNodes — compare exec-tree nodes for a subsystem across sessions
  • generateProfilerReport — generate a self-contained HTML report with findings

Data Acquisition — Choose One

Option A: Run the profiler on a model

Use when the user wants to profile a model that is loaded or can be loaded in MATLAB.

% Load the model if not already open
load_system('ModelName');

% Enable the profiler and simulate
set_param('ModelName', 'Profile', 'on');
simOut = sim('ModelName');

% Extract profiler data
profilerData = Simulink.profiler.Data(simOut);

After obtaining profilerData, proceed to the Analysis Workflow.

Option B: Load saved profiler data from a MAT-file

Use when the user provides a .mat file containing saved profiler results. The variable inside is typically named profilerData but may vary.

d = load('path/to/profilerData.mat');
% Inspect variable names
disp(fieldnames(d));
% Use the Simulink.profiler.Data variable (name may vary)
profilerData = d.profilerData;

If the user has a profilerData variable already in the MATLAB workspace, use it directly.

Option C: User provides profiler data in a MATLAB variable

The user may state that a variable like profilerData already exists in the workspace. Verify with whos profilerData and use it directly.

Analysis Workflow

Step 1 — Parse the data

results = parseSimulinkProfilerData(profilerData);

This returns a struct with:

  • results.modelName — run identifier string
  • results.totalSimTime — total wall-clock time in seconds
  • results.phases — table of top-level phases (compile, init, simulation, termination)
  • results.blockProfiles — table of per-block timing from the UI node tree
  • results.execTree — table of all execution nodes flattened from the exec tree

Step 2 — Phase overview

Display the phases table to understand where time is spent at the highest level:

fprintf('Model: %s\nTotal time: %.2f s\n\n', results.modelName, results.totalSimTime);
disp(results.phases);

Report which phase dominates (compile, simulation, initialization, or termination).

Step 3 — Block-level hotspots

displayBlockHotspots(results.blockProfiles);       % top 20 by default
displayBlockHotspots(results.blockProfiles, 10);    % or specify N

Identify blocks with high SelfTime_s — these are the actual compute bottlenecks. Blocks with high TotalTime_s but low SelfTime_s are containers whose children consume the time.

Step 4 — Execution tree hotspots

displayExecTreeHotspots(results.execTree);          % top 20 by default
displayExecTreeHotspots(results.execTree, 10);      % or specify N

This also shows per-call cost (selfTime / numberOfCalls) for each node.

Key execution methods to watch for:

  • ModelReference.Outputs.Major — model reference output computation per step
  • StateflowChild.Outputs.Major — Stateflow / MATLAB Function block execution
  • Scope.SetupRunTimeResources — scope initialization overhead
  • S-Function.SetupRunTimeResources — S-function initialization
  • DataStoreRead.Outputs.Major — data store access overhead
  • Methods ending in .Update — block state update cost

Step 5 — Drill into specific subsystems

When a subsystem or model reference is identified as slow, use:

drillIntoSubsystem(results.execTree, "SubsystemName");
drillIntoSubsystem(results.execTree, "SubsystemName", 0.01);  % custom threshold

Adjust the self-time threshold based on the model's total time. For large models, use a higher threshold.

Step 6 — Report findings

Summarize the findings in a structured format:

  1. Phase breakdown — where the wall-clock time is spent
  2. Top bottleneck blocks — blocks with highest self time
  3. Execution method hotspots — which simulation methods dominate
  4. Recommendations — actionable suggestions (e.g., disable scopes, use accelerator mode, reduce data store reads)

Step 7 — Generate HTML report

Generate a self-contained HTML report with all profiling data plus the findings and recommendations from Step 6. Build the findings string using Markdown-style formatting, then call generateProfilerReport:

findings = sprintf([ ...
    '## Key Findings\n' ...
    '- Simulation phase dominates at 95%% of total time\n' ...
    '- Scope blocks consume 2.3 s of init time\n' ...
    '\n' ...
    '## Recommendations\n' ...
    '- Disable or close all Scope blocks for batch runs\n' ...
    '- Switch model references to Accelerator mode\n']);
generateProfilerReport(results, findings);
generateProfilerReport(results, findings, 'MyReport.html');  % custom output path

The report includes:

  • Summary dashboard (total time, dominant phase, block/node counts)
  • Phase breakdown table with percentage bars
  • Top 20 block hotspots sorted by self time (with per-call cost)
  • Top 20 execution method hotspots sorted by self time (with per-call cost)
  • Findings and recommendations section (from the string you provide)

Comparison Workflow (Two Sessions)

When comparing two profiler sessions (e.g., different releases, before/after a change):

Step 1 — Parse both sessions

r1 = parseSimulinkProfilerData(profilerData1);
r2 = parseSimulinkProfilerData(profilerData2);

Step 2 — Phase comparison

comparePhases(r1, r2);                              % default labels
comparePhases(r1, r2, "R2023b", "R2025b");          % custom labels
comparePhases(r1, r2, "Before", "After");            % or any labels

Step 3 — Block-level comparison

compareBlockProfiles(r1, r2);                        % top 20, default labels
compareBlockProfiles(r1, r2, 10, "Before", "After"); % top 10, custom labels

Step 4 — Exec node comparison for a specific subsystem

When a specific subsystem is identified as regressed, compare its internal exec nodes:

compareExecNodes(r1, r2, "SubsystemName");
compareExecNodes(r1, r2, "SubsystemName", 0.01, "R2023b", "R2025b");

Step 5 — Report comparison findings

Summarize:

  1. Overall slowdown — total time ratio
  2. Phase-level deltas — which phases regressed and by how much
  3. Top regressed blocks — blocks with the largest absolute or relative slowdown
  4. Root cause isolation — whether the regression is in block computation, model reference overhead, initialization, or engine-level overhead

Interpretation Guidelines

Model References

  • Normal mode: The profiler shows full internal detail (all child blocks and methods). Use this to identify specific block-level bottlenecks.
  • Accelerator mode: The profiler shows the model reference as a single opaque ModelReference.Outputs.Major entry with selfTime == totalTime. No internal detail is visible. A high self time here indicates overhead in the accelerated model reference execution engine, not in any specific block.
  • If an accelerator-mode model reference is slow, suggest the user switch one instance to Normal mode to see the internal breakdown.

Common Bottleneck Patterns

  • Scope.SetupRunTimeResources — Scope initialization can be very expensive. Recommend closing/disabling scopes for performance runs.
  • Display.Outputs.Major — Display blocks add overhead per step. Recommend removing or disabling for batch runs.
  • DataStoreRead/Write.Outputs.Major — Large data stores accessed every step. Consider bus signals or direct connections instead.
  • StateflowChild.Outputs.Major — Stateflow chart or MATLAB Function block execution. Profile the MATLAB code separately if needed.
  • S-Function.SetupRunTimeResources — S-function initialization. High values may indicate heavy one-time setup in mdlStart.
  • ToAsyncQueueBlock — Signal logging overhead. Reduce the number of logged signals if not needed.
  • compilePhase — An opaque phase with no child breakdown. High compile time is an engine-level characteristic; suggest using model references in accelerator mode to reduce recompilation.

Per-Call vs Total Time

Always compute per-call cost when comparing: selfTime / numberOfCalls. A block may have high total time simply because it is called many times (e.g., in a triggered or enabled subsystem). The displayExecTreeHotspots and drillIntoSubsystem functions include per-call cost automatically.

Rules

  • Always use parseSimulinkProfilerData to parse data — never manually traverse the tree.
  • Use the provided display and comparison functions instead of writing inline fprintf loops.
  • Never dump large raw tables. Show the top N entries (10–20) using the display functions.
  • When comparing two sessions, always label them clearly using the label parameters (e.g., "R2023b" and "R2025b", or "Before" and "After").
  • Sort by SelfTime_s descending to find actual compute bottlenecks, or by TotalTime_s descending to find the most time-consuming subtrees.
  • Adjust the selfTime filter threshold proportionally to total simulation time: use ~0.1% of total time as a minimum threshold for reporting.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.