Matlab Write Performance Tests
MathWorksOfficialCreated by MathWorks
- Skill
- Tool integration
- Software development
- BSD-2-Clause
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured approach to creating performance tests for MATLAB code. It leverages the matlab.perftest.TestCase framework to ensure measurements are statistically sound, handling warmup, outlier management, and multiple samples. The skill emphasizes isolating the measurement boundary from setup tasks to ensure accuracy and provides patterns for unit, system, and workflow-level benchmarking.
What it does
- Generates MATLAB test classes inheriting from matlab.perftest.TestCase.
- Implements measurement boundaries using keepMeasuring or startMeasuring/stopMeasuring.
- Configures test parameterization for varying data sizes and algorithms.
- Provides templates for unit, system, and application-level workflow benchmarks.
- Includes guidance on reducing noise and ensuring deterministic results via RNG seeding.
- Demonstrates how to compare performance results over time to detect regressions.
When to use it
- When you need to benchmark MATLAB functions with statistical confidence.
- When setting up continuous performance monitoring for your codebase.
- When you need to detect performance regressions across different versions.
- When you need to measure execution time for operations that are faster than 10ms.
Advantages
- Ensures statistical rigor through automatic warmup and outlier handling.
- Prevents measurement noise by enforcing strict separation of setup and execution.
- Supports flexible parameterization for comprehensive performance sweeps.
- Provides clear patterns for isolating specific code segments or entire workflows.
Usage examples
- “Create a performance test for my matrix multiplication function using different matrix sizes.”
- Generates a class using MethodSetupParameter to define matrix sizes and a test method with keepMeasuring to benchmark the multiplication function.
- “How do I measure the load time of a Simulink model separately from its simulation time?”
- Provides a template using startMeasuring and stopMeasuring to isolate the load_system and sim commands into distinct test methods.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/matlab/matlab-write-performance-tests/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip matlab-write-performance-tests.zip -d .agents/skills
Documentation by MathWorks
Writing MATLAB Performance Tests
Write performance tests for MATLAB code using the matlab.perftest.TestCase framework. This framework provides statistically rigorous timing with automatic warmup, multiple samples, and outlier handling.
When to Use
User wants to write repeatable performance tests for their MATLAB code
User needs to benchmark functions with statistical confidence
User wants to detect performance regressions over time
User is setting up continuous performance monitoring
User asks how to use
runperformatlab.perftest.TestCase
When NOT to Use
User wants a quick one-off timing (use
timeitinstead — seematlab-optimize-performance)User wants to optimize existing code (use
matlab-optimize-performance)User wants to measure memory usage (use
matlab-optimize-memory)User wants to profile code to find bottlenecks (use
matlab-optimize-performance, Step 2)
Framework: matlab.perftest.TestCase
All performance tests subclass matlab.perftest.TestCase and use measurement boundaries to control what gets timed.
Basic Template
classdef MyFeaturePerformanceTest < matlab.perftest.TestCase
properties (MethodSetupParameter)
DataSize = struct('Small', 100, 'Medium', 1000, 'Large', 10000)
end
properties
inputData
end
methods (TestMethodSetup)
function setupData(testCase, DataSize)
% ALL setup outside the measurement boundary
testCase.inputData = randn(DataSize, 1);
end
end
methods (Test)
function testMyFunction(testCase)
data = testCase.inputData;
while testCase.keepMeasuring
result = myFunction(data);
end
testCase.verifyNotEmpty(result);
end
end
endRunning Performance Tests
% Run with statistical rigor (automatic sample size)
results = runperf('MyFeaturePerformanceTest');
% View results
disp(results)
% Fixed sample count (faster, less statistical power)
import matlab.perftest.TimeExperiment;
suite = testsuite('MyFeaturePerformanceTest');
experiment = TimeExperiment.withFixedSampleSize(4);
results = run(experiment, suite);Measurement Boundaries
The framework offers three ways to control what gets measured:
1. keepMeasuring — Needed when code is fast (<10ms)
Automatically loops the code until enough samples are collected. Required for sub-10ms operations to achieve statistical rigor; works at any speed but adds overhead for slower code where startMeasuring/stopMeasuring is preferred:
function testFastFunction(testCase)
data = testCase.inputData;
while testCase.keepMeasuring
result = fastFunction(data);
end
testCase.verifyNotEmpty(result);
end2. startMeasuring/stopMeasuring — For precise control
Use when you need setup between iterations or want to exclude specific code:
function testWithBoundaries(testCase)
data = testCase.inputData;
% Pre-computation (NOT measured)
preparedData = preprocess(data);
testCase.startMeasuring();
result = functionUnderTest(preparedData);
testCase.stopMeasuring();
% Verification (NOT measured)
testCase.verifyEqual(size(result), [100 1]);
end3. No boundary — Entire method is measured
The whole Test method body is timed. Use only when the entire method IS the workload:
function testSlowFunction(testCase, DataSize) %#ok<INUSD>
data = testCase.inputData;
result = slowFunction(data);
testCase.verifyNotEmpty(result);
endParameterization
Parameterize tests to measure across different input sizes or configurations.
MethodSetupParameter — When setup uses the parameter
properties (MethodSetupParameter)
DataSize = struct('Small', 100, 'Medium', 1000, 'Large', 10000)
end
methods (TestMethodSetup)
function setupData(testCase, DataSize)
testCase.inputData = randn(DataSize, 1);
end
endTestParameter — When only test methods use the parameter
properties (TestParameter)
Algorithm = {'chol', 'lu', 'qr'}
end
methods (Test)
function testSolve(testCase, Algorithm)
...
end
endCritical gotcha: Do NOT use TestParameter for properties consumed by TestMethodSetup. MATLAB will error with "Define 'X' as a MethodSetupParameter." If your setup method needs the parameter, it must be MethodSetupParameter.
Combining Both — Size in setup, algorithm in test
properties (MethodSetupParameter)
DataSize = struct('Small', 100, 'Medium', 1000, 'Large', 10000)
end
properties (TestParameter)
Algorithm = {'chol', 'lu', 'qr'}
end
methods (TestMethodSetup)
function setupData(testCase, DataSize)
testCase.inputData = randn(DataSize);
end
end
methods (Test)
function testSolve(testCase, Algorithm)
A = testCase.inputData' * testCase.inputData; % SPD matrix
data = A;
while testCase.keepMeasuring
result = decomposition(data, Algorithm);
end
testCase.verifyNotEmpty(result);
end
endThis produces 9 test points (3 sizes × 3 algorithms).
Lean Setup — Critical Rule
ALL setup must be outside the measurement boundary:
| Setup Task | Where to Put It |
|---|---|
| Data generation | TestMethodSetup |
| Loading files | TestClassSetup |
| Creating objects | TestMethodSetup or TestClassSetup |
| Path manipulation | TestClassSetup |
| RNG seeding | TestMethodSetup |
Never include setup/teardown inside the measured region. This inflates timing and adds noise.
Copy properties to local variables before measuring. Don't access testCase.PropertyName inside the measurement boundary — it measures the matlab.perftest.TestCase indexing overhead. Assign to a local variable outside the boundary instead:
% Correct: local variable assigned before measurement
data = testCase.inputData;
while testCase.keepMeasuring
result = myFunction(data);
endmethods (TestMethodSetup)
function setupData(testCase, DataSize)
rng(42, 'twister'); % Deterministic data
testCase.inputData = randn(DataSize, 1);
end
endNoise and Duration
Target Duration
Each test point should take >10ms to execute
If too fast, increase data size or use
keepMeasuringSub-millisecond tests produce unreliable results
Reducing Noise
Use
keepMeasuringfor fast operationsPre-allocate all data in setup
Suppress all output (
'Display', 'off')Avoid file I/O in the measured region
Avoid
drawnow,pause, or GUI operationsSeed RNG in setup for deterministic data
Interpreting Results
results = runperf('MyPerformanceTest');
% Access timing statistics
for i = 1:numel(results)
samples = results(i).Samples.MeasuredTime;
fprintf('%s: median=%.4fs, std=%.4fs, CV=%.1f%%\n', ...
results(i).Name, median(samples), std(samples), ...
100*std(samples)/mean(samples));
endA coefficient of variation (CV) above 10% indicates noisy results — revisit your test setup.
Anti-Patterns
| Anti-Pattern | Why It's Wrong | Fix |
|---|---|---|
| Setup inside measurement | Inflates timing, adds noise | Move to TestMethodSetup |
Sub-1ms test without keepMeasuring | Noise dominates | Use keepMeasuring or increase data size |
tic/toc instead of framework | No statistical rigor, no warmup handling | Use runperf/keepMeasuring |
TestParameter for setup params | Framework error at runtime | Use MethodSetupParameter |
| Single test covering multiple APIs | Can't isolate regressions | Split into focused tests |
| Random data without seeding RNG | Non-deterministic, harder to debug | rng(42, 'twister') in setup |
| Printing/plotting in measured code | Console/graphics I/O adds noise | Suppress all output |
Comparing Results Over Time
Save and compare results to detect regressions:
% Save baseline
baselineResults = runperf('MyPerformanceTest');
save('perfBaseline.mat', 'baselineResults');
% Later: compare against baseline
currentResults = runperf('MyPerformanceTest');
load('perfBaseline.mat');
for i = 1:numel(currentResults)
baseMed = median(baselineResults(i).Samples.MeasuredTime);
currMed = median(currentResults(i).Samples.MeasuredTime);
ratio = currMed / baseMed;
status = "OK";
if ratio > 1.2
status = "REGRESSION";
elseif ratio < 0.8
status = "IMPROVEMENT";
end
fprintf('%s: %.4fs -> %.4fs (%.2fx) %s\n', ...
currentResults(i).Name, baseMed, currMed, ratio, status);
endTest Granularity
When asked to write performance tests, consider which level is appropriate:
| Level | Scope | Parameterized? | Duration Target |
|---|---|---|---|
| Unit | Single operation (e.g., svd, mldivide) | Yes — sweep sizes | >10ms per testpoint |
| System | One function end-to-end | Yes — sweep sizes | >10ms per testpoint |
| Workflow (ALB) | Complete multi-step customer workflow | No — one representative size | 0.5–5s total |
When to use each:
Unit: Function has multiple expensive operations and you need to isolate which one regressed
System: Default choice — measures the function as users call it
Workflow: Validates that unit optimizations translate to real-world speedups; catches cross-function bottlenecks
If unsure, generate system-level tests first, then ask whether unit-level decomposition or workflow-level benchmarks are needed.
Workflow Benchmarks (Application-Level)
For end-to-end workflow benchmarks, the structure differs from unit/system tests:
No parameterization — one representative problem size (that's what unit tests are for)
Realistic data — production-scale inputs, not synthetic
Single test method — the whole workflow is one testpoint
startMeasuring/stopMeasuring— always (neverkeepMeasuring)Setup in
TestClassSetup— load data once, not per methodTarget 0.5–5s — sub-0.5s is noise-dominated; >30s slows iteration
See references/tExampleWorkflow.m for the complete template.
Quality Checklist
Verify after generating each test class:
[ ] Setup is outside the measurement boundary (
TestMethodSetup)[ ] Properties copied to local variables before measuring
[ ] Each test point exceeds 10ms (or uses
keepMeasuringif faster)[ ] RNG seeded for deterministic data
[ ] No console output, plotting, or file I/O in measured region
[ ] Parameterized by data size
[ ] Single API/operation per test method (not bundling multiple)
[ ]
MethodSetupParameterused (notTestParameter) when setup consumes the parameter
Reference Files
references/FeaturePerformanceTest.m— Performance test class template with all measurement patternsreferences/tExampleWorkflow.m— Workflow-level benchmark template (application-level)references/simulink-template.md— Performance test template for Simulink model benchmarks
Copyright 2026 The MathWorks, Inc.
Files
- ATTRIBUTION.mdAdded by AutoGineer1.1 KiB
- LICENSELicence file added by AutoGineer1.4 KiB
- SKILL.md11.4 KiB
- manifest.yaml478 B
- references/FeaturePerformanceTest.m2.3 KiB
- references/simulink-template.md1.5 KiB
- references/tExampleWorkflow.m1.6 KiB
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- MathWorks
- Publisher
- MathWorks (Official)
- Source
- matlab/matlab-agentic-toolkit · skills-catalog/matlab-software-development/matlab-write-performance-tests · commit 2a7f215
- Licence
- BSD 2-Clause License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE.md)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by MathWorks.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download matlab-write-performance-tests.zip