Тестирование производительности с использованием классов

Этот пример показывает, как создать тест производительности и регрессионный тест на функцию fprintf.

Тест производительности записи

Рассмотрите следующий модуль (регрессия) тест. Можно запустить этот тест как тест производительности с помощью runperf('fprintfTest') вместо runtests('fprintfTest').

classdef fprintfTest < matlab.unittest.TestCase
    properties
        file
        fid
    end
    methods(TestMethodSetup)
        function openFile(testCase)
            testCase.file = tempname;
            testCase.fid = fopen(testCase.file,'w');
            testCase.assertNotEqual(testCase.fid,-1,'IO Problem')
            
            testCase.addTeardown(@delete,testCase.file);
            testCase.addTeardown(@fclose,testCase.fid);
        end
    end
    
    methods(Test)
        function testPrintingToFile(testCase)
            textToWrite = repmat('abcdef',1,5000000);
            fprintf(testCase.fid,'%s',textToWrite);
            testCase.verifyEqual(fileread(testCase.file),textToWrite)
        end
        
        function testBytesToFile(testCase)
            textToWrite = repmat('tests_',1,5000000);
            nbytes = fprintf(testCase.fid,'%s',textToWrite);
            testCase.verifyEqual(nbytes,length(textToWrite))
        end
    end
end

Измеренное время не включает время, чтобы открыть и закрыть файл или утверждение, потому что эти действия происходят в блоке TestMethodSetup, и не в блоке Test. Однако измеренное время включает время, чтобы выполнить верификации. Лучшая практика состоит в том, чтобы измерить более точный контур производительности.

Создайте тест производительности в файле, fprintfTest.m, в вашей текущей рабочей папке. Этот тест подобен регрессионному тесту со следующими модификациями:

  • Тест наследовался matlab.perftest.TestCase вместо matlab.unittest.TestCase.

  • Тест вызывает startMeasuring и методы stopMeasuring, чтобы создать контур вокруг вызова функции fprintf.

classdef fprintfTest < matlab.perftest.TestCase
    properties
        file
        fid
    end
    methods(TestMethodSetup)
        function openFile(testCase)
            testCase.file = tempname;
            testCase.fid = fopen(testCase.file,'w');
            testCase.assertNotEqual(testCase.fid,-1,'IO Problem')
            
            testCase.addTeardown(@delete,testCase.file);
            testCase.addTeardown(@fclose,testCase.fid);
        end
    end
    
    methods(Test)
        function testPrintingToFile(testCase)
            textToWrite = repmat('abcdef',1,5000000);
            
            testCase.startMeasuring();
            fprintf(testCase.fid,'%s',textToWrite);
            testCase.stopMeasuring();
            
            testCase.verifyEqual(fileread(testCase.file),textToWrite)
        end
        
        function testBytesToFile(testCase)
            textToWrite = repmat('tests_',1,5000000);
            
            testCase.startMeasuring();
            nbytes = fprintf(testCase.fid,'%s',textToWrite);
            testCase.stopMeasuring();
            
            testCase.verifyEqual(nbytes,length(textToWrite))
        end
    end
end

Измеренное время для этого теста производительности включает только вызов fprintf, и среда тестирования все еще оценивает проверки.

Выполнение теста производительности

Запустите тест производительности. В зависимости от вашей системы вы можете видеть предупреждения, что среда тестирования производительности запустила тест максимальное количество времен, но не достигла 0,05 относительных пределов погрешности с 0,95 доверительными уровнями.

results = runperf('fprintfTest')
Running fprintfTest
.......... ......
Done fprintfTest
__________

results = 
  1×2 TimeResult array with properties:

    Name
    Valid
    Samples
    TestActivity
Totals:
   2 Valid, 0 Invalid.

  Переменная results 1x2  массив MeasurementResult. Каждый элемент в массиве соответствует одному из тестов, заданных в тестовом файле.

Отображение результатов тестирования

Отобразите результаты измерения для первого теста. Ваши результаты могут отличаться.

results(1)
ans = 
  TimeResult with properties:

            Name: 'fprintfTest/testPrintingToFile'
           Valid: 1
         Samples: [4×7 table]
    TestActivity: [8×12 table]
Totals:
   1 Valid, 0 Invalid.

Как обозначено размером  свойства TestActivity, среда тестирования производительности собрала 14 измерений. Этот номер включает 4 измерения, чтобы нагреть код.  Свойство Samples исключает измерения прогрева.

Отобразите демонстрационные измерения для первого теста.

results(1).Samples
ans =
  4×7 table
                 Name                 MeasuredTime         Timestamp           Host      Platform                Version                            RunIdentifier            
    ______________________________    ____________    ____________________    _______    ________    ________________________________    ____________________________________
    fprintfTest/testPrintingToFile      0.090988      26-Oct-2018 14:09:10    MY-HOSTNAME     win64      9.6.0.979037 (R2019a) Prerelease    84305243-69b9-4104-a50e-459ce687ceb9
    fprintfTest/testPrintingToFile      0.092055      26-Oct-2018 14:09:10    MY-HOSTNAME     win64      9.6.0.979037 (R2019a) Prerelease    84305243-69b9-4104-a50e-459ce687ceb9
    fprintfTest/testPrintingToFile        0.0918      26-Oct-2018 14:09:10    MY-HOSTNAME     win64      9.6.0.979037 (R2019a) Prerelease    84305243-69b9-4104-a50e-459ce687ceb9
    fprintfTest/testPrintingToFile      0.085175      26-Oct-2018 14:09:11    MY-HOSTNAME     win64      9.6.0.979037 (R2019a) Prerelease    84305243-69b9-4104-a50e-459ce

Вычисление статистики для единичного тестового элемента

Отобразитесь среднее значение измерило время для первого теста. Чтобы исключить данные, собранные в выполнениях прогрева, используйте значения в поле Samples.

sampleTimes = results(1).Samples.MeasuredTime;
meanTest = mean(sampleTimes)
meanTest =
    0.0900

Вычисление статистики для всех тестовых элементов

Определите среднее время для всех тестовых элементов. Тест fprintfTest включает два различных метода. Сравните время для каждого метода (тестовый элемент).

Поскольку среда тестирования производительности возвращает таблицу Samples для каждого тестового элемента, конкатенируйте все эти таблицы в одну таблицу. Затем сгруппируйте строки тестовым элементом Name и вычислите средний MeasuredTime для каждой группы.

fullTable = vertcat(results.Samples);
summaryStats = varfun(@mean,fullTable,...
    'InputVariables','MeasuredTime','GroupingVariables','Name')
summaryStats =
  2×3 table
                 Name                 GroupCount    mean_MeasuredTime
    ______________________________    __________    _________________
    fprintfTest/testPrintingToFile        4             0.090004     
    fprintfTest/testBytesToFile           4              0.08558     

Оба метода тестирования пишут тот же объем данных в файл. Поэтому часть различия между средними значениями приписана вызыванию функции fprintf с выходным аргументом.

Изменение статистических целей и повторно выполненные тесты

Измените статистические цели, заданные функцией runperf путем построения и выполнения эксперимента времени. Создайте эксперимент времени с измерениями, которые достигают демонстрационного среднего значения с 3%-м относительным пределом погрешности на 97%-м доверительном уровне. Соберите восемь измерений прогрева и до 32 демонстрационных измерений.

Создайте явный тестовый набор.

suite = testsuite('fprintfTest');

Создайте эксперимент времени с переменным количеством демонстрационных измерений и запустите тесты.

import matlab.perftest.TimeExperiment
experiment = TimeExperiment.limitingSamplingError('NumWarmups',8,...
    'MaxSamples', 32, 'RelativeMarginOfError',0.03, 'ConfidenceLevel', 0.97);
resultsTE = run(experiment,suite);
Running fprintfTest
.......... .......... .........
Done fprintfTest
__________

В этом примере вывод среда тестирования производительности не может достигнуть более строгих статистических целей с конкретным количеством максимальных выборок. Ваши результаты могут отличаться.

Вычислите статистику для всех тестовых элементов.

fullTableTE = vertcat(resultsTE.Samples);
summaryStatsTE = varfun(@mean,fullTableTE,...
    'InputVariables','MeasuredTime','GroupingVariables','Name')
summaryStatsTE =
  2×3 table
                 Name                 GroupCount    mean_MeasuredTime
    ______________________________    __________    _________________
    fprintfTest/testPrintingToFile        7              0.08887     
    fprintfTest/testBytesToFile           6              0.08836     

Увеличьте максимальное число выборок к 100 и повторно выполните эксперимент времени.

experiment = TimeExperiment.limitingSamplingError('NumWarmups',2,...
    'RelativeMarginOfError',0.03,'ConfidenceLevel',0.97,'MaxSamples',100);
resultsTE = run(experiment,suite);
Running fprintfTest
.......... ....
Done fprintfTest
__________

Вычислите статистику для всех тестовых элементов.

fullTableTE = vertcat(resultsTE.Samples);
summaryStatsTE = varfun(@mean,fullTableTE,...
    'InputVariables','MeasuredTime','GroupingVariables','Name')
summaryStatsTE =
  2×3 table
                 Name                 GroupCount    mean_MeasuredTime
    ______________________________    __________    _________________
    fprintfTest/testPrintingToFile        6             0.088188     
    fprintfTest/testBytesToFile           4             0.092162     

Среда тестирования достигает статистических целей для обоих тестов приблизительно в 50 выборках.

Мера в первый раз стоимость

Запустите новый сеанс MATLAB®. Новый сеанс гарантирует, что MATLAB не запустил код, содержавшийся в ваших тестах.

Измерьте новую стоимость своего кода путем создания и выполнения фиксированного эксперимента времени с нулевыми измерениями прогрева и одним демонстрационным измерением.

Создайте явный тестовый набор. Поскольку вы измеряете новую стоимость функции, запустите один тест. Чтобы запустить несколько тестов, сохраните результаты и запустите новый сеанс работы с MATLAB между тестами.

suite = testsuite('fprintfTest/testPrintingToFile');

Создайте и запустите эксперимент времени.

import matlab.perftest.TimeExperiment
experiment = TimeExperiment.withFixedSampleSize(1);
results = run(experiment,suite);
Running fprintfTest
.
Done fprintfTest
__________

Отобразите результаты. Наблюдайте, что таблица TestActivity гарантирует, что нет никаких выборок прогрева.

fullTable = results.TestActivity
fullTable =
  1×12 table
                 Name                 Passed    Failed    Incomplete    MeasuredTime    Objective         Timestamp           Host      Platform                Version                            TestResult                          RunIdentifier            
    ______________________________    ______    ______    __________    ____________    _________    ____________________    _______    ________    ________________________________    ________________________________    ____________________________________
    fprintfTest/testPrintingToFile    true      false       false         0.09189        sample      26-Oct-2018 14:18:46    MY-HOSTNAME     win64      9.6.0.979037 (R2019a) Prerelease    [1x1 matlab.unittest.TestResult]    36d0b490-d2cc-4c8c-bac7-395b5976d638

Среда тестирования производительности собирает одну выборку для каждого теста.

Смотрите также

| | | | |