Skip to content

Commit d758edc

Browse files
runplotlytests: report perf timings inline and in a sample summary table
1 parent 55bb4c8 commit d758edc

2 files changed

Lines changed: 79 additions & 0 deletions

File tree

‎plotly/testing/PlotlyPerfTestCase.m‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,31 @@
7777
end
7878
ok = true;
7979
end
80+
function s = sampleStats(tc)
81+
% statistics of the collected samples; NumSamples is 0 when
82+
% nothing was measured
83+
if tc.p_nSamples == 0
84+
s = struct('NumSamples', 0, 'Mean', [], 'Std', [], ...
85+
'Min', [], 'Max', [], 'RelMoE', [], ...
86+
'NumWarmups', tc.p_warmupsDone);
87+
return;
88+
end
89+
x = tc.p_times(1:tc.p_nSamples);
90+
m = mean(x);
91+
sd = std(x);
92+
if m > 0
93+
relMoE = tc.tQuantile(tc.p_nSamples - 1) * sd / (m * sqrt(tc.p_nSamples));
94+
else
95+
relMoE = [];
96+
end
97+
s = struct('NumSamples', tc.p_nSamples, ...
98+
'Mean', m, ...
99+
'Std', sd, ...
100+
'Min', min(x), ...
101+
'Max', max(x), ...
102+
'RelMoE', relMoE, ...
103+
'NumWarmups', tc.p_warmupsDone);
104+
end
80105
end
81106

82107
methods (Access = private)

‎plotly/testing/runplotlytests.m‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ function runplotlytests(varargin)
102102
% including each parameterized case
103103
hasSetup = ismember('setUp', classMeths);
104104
hasTearDown = ismember('tearDown', classMeths);
105+
isPerfClass = isa(tc, 'PlotlyPerfTestCase');
106+
perfRows = {};
105107
nTests = 0;
106108
verdicts = struct('Name', {}, 'Passed', {}, 'VerificationFailures', {}, ...
107109
'Diagnostics', {}, 'ErrorTrace', {}, 'Duration', {}, 'Errored', {});
@@ -230,6 +232,16 @@ function runplotlytests(varargin)
230232
else
231233
fprintf('.');
232234
end
235+
236+
if isPerfClass
237+
st = tc.sampleStats();
238+
if st.NumSamples > 0
239+
fprintf('\n %s: %s mean, %s MoE, n=%d (%d warmups)\n', ...
240+
caseName, fmtTime(st.Mean), fmtMoE(st.RelMoE), ...
241+
st.NumSamples, st.NumWarmups);
242+
perfRows{end+1} = struct('Name', caseName, 'Stats', st); %#ok<AGROW>
243+
end
244+
end
233245
end
234246
end
235247

@@ -242,6 +254,25 @@ function runplotlytests(varargin)
242254
'ErrorTrace', '', 'Duration', 0, 'Errored', true);
243255
end
244256

257+
if ~isempty(perfRows)
258+
maxName = 0;
259+
for r = 1:numel(perfRows)
260+
maxName = max(maxName, length(perfRows{r}.Name));
261+
end
262+
fprintf('\nSample summary:\n');
263+
hdr = sprintf(' %-*s %4s %10s %10s %10s %10s %7s\n', ...
264+
maxName, 'Name', 'n', 'Mean', 'Std', 'Min', 'Max', 'MoE');
265+
fprintf('%s', hdr);
266+
fprintf(' %s\n', repmat('-', 1, numel(hdr) - 1));
267+
for r = 1:numel(perfRows)
268+
st = perfRows{r}.Stats;
269+
fprintf(' %-*s %4d %10s %10s %10s %10s %7s\n', ...
270+
maxName, perfRows{r}.Name, st.NumSamples, ...
271+
fmtSec(st.Mean), fmtSec(st.Std), fmtSec(st.Min), ...
272+
fmtSec(st.Max), fmtMoE(st.RelMoE));
273+
end
274+
end
275+
245276
fprintf('\nDone %s\n', className);
246277
fprintf('__________\n\n');
247278

@@ -542,6 +573,29 @@ function runplotlytests(varargin)
542573
end
543574
end
544575

576+
function s = fmtTime(t)
577+
% auto-scaled time for the inline per-case line
578+
if t < 1
579+
s = sprintf('%.2f ms', t * 1000);
580+
else
581+
s = sprintf('%.3f s', t);
582+
end
583+
end
584+
585+
function s = fmtSec(t)
586+
% fixed seconds for the sample summary columns
587+
s = sprintf('%.6g', t);
588+
end
589+
590+
function s = fmtMoE(r)
591+
% relative margin of error as a percentage
592+
if isempty(r) || ~isfinite(r)
593+
s = 'n/a';
594+
else
595+
s = sprintf('%.1f%%', r * 100);
596+
end
597+
end
598+
545599
function trace = errorTrace(e)
546600
trace = sprintf('''%s''\n%s', e.identifier, e.message);
547601
for si = 1:numel(e.stack)

0 commit comments

Comments
 (0)