mcpField
M
matlab-write-performance-tests

matlab-write-performance-tests

github.com/matlabテスト・品質1.2k78 回インストール1 日前に更新
リポジトリ

matlab-write-performance-tests について

MATLAB 開発者向けに、`matlab.perftest.TestCase` を使った再現性のある性能テスト作成を案内するスキルです。統計的な計測、パラメーター化、回帰確認のための比較を扱います。

主な機能

  1. 01ウォームアップとサンプルによる統計計測
  2. 02計測範囲の設定方法
  3. 03パラメーター化された性能テスト
  4. 04回帰確認のためのベースライン比較

活用シーン

  1. 01入力サイズ別の MATLAB 関数ベンチマーク
  2. 02経時的な性能変化の確認
  3. 03継続的な性能監視の設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/matlab/matlab-agentic-toolkit --skill matlab-write-performance-tests

インストール後、Claude Code で/matlab-write-performance-testsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

manifest.yaml
references/
FeaturePerformanceTest.m
simulink-template.md
tExampleWorkflow.m

詳細

MATLAB パフォーマンステストの作成

matlab.perftest.TestCase フレームワークを使用して、MATLAB コードのパフォーマンステストを作成します。このフレームワークは、自動ウォームアップ、複数のサンプル、外れ値の処理により、統計的に厳密な計測を行います。

使用する場面

  • MATLAB コードの再現性のあるパフォーマンステストを作成したい場合
  • 統計的な信頼性をもって関数をベンチマークしたい場合
  • パフォーマンスのリグレッションを継続的に検出したい場合
  • 継続的なパフォーマンス監視を設定したい場合
  • runperf または matlab.perftest.TestCase の使い方を知りたい場合

使用しない場面

  • その場限りの簡単な計測をしたい場合(代わりに timeit を使用してください。matlab-optimize-performance を参照)
  • 既存のコードを最適化したい場合(matlab-optimize-performance を使用)
  • メモリ使用量を計測したい場合(matlab-optimize-memory を使用)
  • ボトルネックを見つけるためにコードをプロファイルしたい場合(matlab-optimize-performance のステップ 2 を使用)

フレームワーク:matlab.perftest.TestCase

すべてのパフォーマンステストは matlab.perftest.TestCase をサブクラス化し、計測範囲を指定して計測対象を制御します。

基本テンプレート
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
end
パフォーマンステストの実行
% 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);

計測範囲

このフレームワークでは、計測対象を制御する方法が 3 つあります。

1. keepMeasuring — コードの実行が高速(<10ms)な場合に必要

十分なサンプルが集まるまで、コードを自動的に繰り返し実行します。統計的な厳密性を得るには 10ms 未満の処理で必須です。どのような速度でも使用できますが、遅いコードではオーバーヘッドが加わるため、startMeasuring/stopMeasuring を使用する方が適しています。

function testFastFunction(testCase)
    data = testCase.inputData;
    while testCase.keepMeasuring
        result = fastFunction(data);
    end
    testCase.verifyNotEmpty(result);
end
2. startMeasuring/stopMeasuring — 計測範囲を正確に制御する場合

反復の間にセットアップが必要な場合や、特定のコードを計測対象から除外したい場合に使用します。

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]);
end
3. 境界の指定なし — メソッド全体を計測

Test メソッドの本体全体が計測されます。メソッド全体が計測対象となる場合に限って使用してください。

function testSlowFunction(testCase, DataSize) %#ok<INUSD>
    data = testCase.inputData;
    result = slowFunction(data);
    testCase.verifyNotEmpty(result);
end

パラメーター化

入力サイズや設定を変えて計測するには、テストをパラメーター化します。

MethodSetupParameter — セットアップでパラメーターを使用する場合
properties (MethodSetupParameter)
    DataSize = struct('Small', 100, 'Medium', 1000, 'Large', 10000)
end

methods (TestMethodSetup)
    function setupData(testCase, DataSize)
        testCase.inputData = randn(DataSize, 1);
    end
end
TestParameter — パラメーターをテストメソッドだけで使用する場合
properties (TestParameter)
    Algorithm = {'chol', 'lu', 'qr'}
end

methods (Test)
    function testSolve(testCase, Algorithm)
        ...
    end
end

重要な注意点: TestMethodSetup で使用するプロパティに TestParameter を使用しないでください。MATLAB は「Define 'X' as a MethodSetupParameter.」というエラーを返します。セットアップメソッドでパラメーターが必要な場合は、MethodSetupParameter にする必要があります。

両方を組み合わせる — セットアップでサイズを指定し、テストでアルゴリズムを指定
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
end

これにより、9 個のテストポイント(サイズ 3 種類 × アルゴリズム 3 種類)が生成されます。

セットアップを最小限にする — 重要なルール

すべてのセットアップは計測範囲の外で行う必要があります。

セットアップタスク記述する場所
データ生成TestMethodSetup
ファイルの読み込みTestClassSetup
オブジェクトの作成TestMethodSetup または TestClassSetup
パスの操作TestClassSetup
RNG のシード設定TestMethodSetup

セットアップ/ティアダウンを計測範囲に含めないでください。 計測時間が増え、ノイズも加わります。

計測前にプロパティをローカル変数にコピーしてください。 計測範囲内で testCase.PropertyName にアクセスしないでください。matlab.perftest.TestCase のインデックス処理のオーバーヘッドまで計測されます。代わりに、計測範囲の外でローカル変数に代入してください。

% Correct: local variable assigned before measurement
data = testCase.inputData;
while testCase.keepMeasuring
    result = myFunction(data);
end
methods (TestMethodSetup)
    function setupData(testCase, DataSize)
        rng(42, 'twister');  % Deterministic data
        testCase.inputData = randn(DataSize, 1);
    end
end

ノイズと実行時間

目標実行時間
  • 各テストポイントの実行時間は >10ms にしてください
  • 短すぎる場合は、データサイズを増やすか keepMeasuring を使用してください
  • 1 ミリ秒未満のテストでは、信頼性の低い結果になります
ノイズの低減
  • 高速な処理には keepMeasuring を使用する
  • セットアップですべてのデータを事前割り当てする
  • すべての出力を抑制する('Display', 'off')
  • 計測範囲内でのファイル I/O を避ける
  • drawnow、pause、GUI 操作を避ける
  • セットアップで RNG にシードを設定し、決定的なデータを生成する
結果の解釈
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));
end

変動係数(CV)が 10% を超える場合、結果にノイズが多いことを示しています。テストのセットアップを見直してください。

アンチパターン

アンチパターン問題点対処方法
測定中にセットアップを行う計測時間が増加し、ノイズが加わりますTestMethodSetup に移動します
keepMeasuring を使わない 1 ミリ秒未満のテストノイズの影響が支配的になりますkeepMeasuring を使うか、データサイズを大きくします
フレームワークの代わりに tic/toc を使う統計的な厳密さがなく、ウォームアップも処理されませんrunperf/keepMeasuring を使います
セットアップ用パラメーターに TestParameter を使う実行時にフレームワークエラーが発生しますMethodSetupParameter を使います
複数の API を単一のテストで扱う回帰を切り分けられません対象を絞ったテストに分割します
RNG のシードを設定せずにランダムデータを使う結果が非決定的になり、デバッグが難しくなりますセットアップで rng(42, 'twister') を使います
測定対象のコード内で出力/プロットを行うコンソール/グラフィックスの I/O がノイズになりますすべての出力を抑制します

結果の経時比較

回帰を検出できるように、結果を保存して比較します。

% 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);
end

テストの粒度

パフォーマンステストの作成を求められた場合は、適切なレベルを検討します。

レベル対象範囲パラメーター化目標所要時間
ユニット単一の操作(例:svd、mldivide)はい — サイズを変えて実行テストポイントあたり 10 ms 超
システム単一の関数を最初から最後まではい — サイズを変えて実行テストポイントあたり 10 ms 超
ワークフロー(ALB)顧客の複数ステップからなるワークフロー全体いいえ — 代表的なサイズを 1 つ合計 0.5~5 秒

各レベルの使い分け:

  • ユニット:関数に負荷の高い操作が複数あり、どの操作で回帰が発生したかを特定する必要がある場合
  • システム:デフォルトの選択肢です。ユーザーが関数を呼び出す方法で測定します
  • ワークフロー:ユニットレベルの最適化が実際の速度向上につながることを検証し、関数間のボトルネックを検出します

判断に迷う場合は、まずシステムレベルのテストを作成し、次にユニットレベルへの分解やワークフローレベルのベンチマークが必要かどうかを確認します。

ワークフローベンチマーク(アプリケーションレベル)

エンドツーエンドのワークフローベンチマークでは、ユニット/システムテストとは構成が異なります。

  • パラメーター化しません — 代表的な問題サイズを 1 つ使います(これはユニットテストの役割です)
  • 現実的なデータ — 合成データではなく、本番環境規模の入力を使います
  • 単一のテストメソッド — ワークフロー全体を 1 つのテストポイントにします
  • startMeasuring/stopMeasuring — 常に使います(keepMeasuring は使いません)
  • TestClassSetup でセットアップ — データはメソッドごとではなく、一度だけ読み込みます
  • 目標は 0.5~5 秒 — 0.5 秒未満ではノイズの影響が支配的になり、30 秒を超えると反復が遅くなります

完全なテンプレートについては、references/tExampleWorkflow.m を参照してください。

品質チェックリスト

各テストクラスの生成後に確認します。

  • セットアップが測定範囲の外にある(TestMethodSetup)
  • 測定前にプロパティをローカル変数にコピーしている
  • 各テストポイントが 10 ms を超える(それより短い場合は keepMeasuring を使う)
  • 再現可能なデータを使うために RNG のシードを設定している
  • 測定範囲内でコンソール出力、プロット、ファイル I/O を行っていない
  • データサイズでパラメーター化している
  • 各テストメソッドが単一の API/操作を対象としている(複数をまとめていない)
  • セットアップでパラメーターを使用する場合は、TestParameter ではなく MethodSetupParameter を使っている

参考ファイル

  • references/FeaturePerformanceTest.m — あらゆる測定パターンを含むパフォーマンステストクラスのテンプレート
  • references/tExampleWorkflow.m — ワークフローレベルのベンチマークテンプレート(アプリケーションレベル)
  • references/simulink-template.md — Simulink モデルのベンチマーク用パフォーマンステストテンプレート

Copyright 2026 The MathWorks, Inc.

コメント