Skip to content

Commit 9ae1f43

Browse files
committed
in benchmark mode run iteratively
In benchmark mode, when the number of runs was not explicitly specified in the test itself, run a reasonably number of iterations. We do this by measuring one run of the test, then using that data to determine how many iterations we should run to fit within 3 seconds. (With a minimum number of iterations to ensure that we get some data, and a maximum number to deal with poor precision for fast test runs.) The 3 second number, and 10 iteration minimum, were chosen by consulting the hyperfine defaults.
1 parent 54751ad commit 9ae1f43

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

clar.c

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
typedef struct stat STAT_T;
8888
#endif
8989

90+
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
9091
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
9192

9293
#include "clar.h"
@@ -329,18 +330,10 @@ clar_run_test(
329330
const struct clar_func *initialize,
330331
const struct clar_func *cleanup)
331332
{
332-
int runs, i;
333-
334-
runs = (test->runs > 0) ? test->runs : 1;
335-
336-
_clar.last_report->times = (runs > 1) ?
337-
calloc(runs, sizeof(double)) :
338-
&_clar.last_report->time_mean;
339-
340-
if (!_clar.last_report->times)
341-
clar_abort("Failed to allocate report times.\n");
333+
int runs = test->runs, i = 0;
342334

343335
_clar.last_report->start = time(NULL);
336+
_clar.last_report->times = &_clar.last_report->time_mean;
344337

345338
CL_TRACE(CL_TRACE__TEST__BEGIN);
346339

@@ -356,16 +349,36 @@ clar_run_test(
356349

357350
CL_TRACE(CL_TRACE__TEST__RUN_BEGIN);
358351

359-
for (i = 0; i < runs; i++) {
352+
do {
360353
struct clar_counter start, end;
354+
double elapsed;
361355

362356
clar_counter_now(&start);
363357
test->ptr();
364358
clar_counter_now(&end);
365359

360+
elapsed = clar_counter_diff(&start, &end);
361+
362+
/*
363+
* unless the number of runs was explicitly given
364+
* in benchmark mode, use the first run as a sample
365+
* to determine how many runs we should attempt
366+
*/
367+
if (_clar.test_mode == CL_TEST_BENCHMARK && !runs) {
368+
runs = MAX(CLAR_BENCHMARK_RUN_MIN, (CLAR_BENCHMARK_RUN_TIME / elapsed));
369+
runs = MIN(CLAR_BENCHMARK_RUN_MAX, runs);
370+
}
371+
372+
if (i == 0 && runs > 1) {
373+
_clar.last_report->times = calloc(runs, sizeof(double));
374+
375+
if (_clar.last_report->times == NULL)
376+
clar_abort("Failed to allocate report times.\n");
377+
}
378+
366379
_clar.last_report->runs++;
367-
_clar.last_report->times[i] = clar_counter_diff(&start, &end);
368-
}
380+
_clar.last_report->times[i] = elapsed;
381+
} while(++i < runs);
369382

370383
CL_TRACE(CL_TRACE__TEST__RUN_END);
371384
}

clar.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@
1818
# define CLAR_MAX_PATH PATH_MAX
1919
#endif
2020

21+
/*
22+
* In benchmark mode, by default, clar will run the test repeatedly for
23+
* approximately `CLAR_BENCHMARK_RUN_TIME` seconds, and at least
24+
* `CLAR_BENCHMARK_RUN_MIN` iterations.
25+
*/
26+
27+
#define CLAR_BENCHMARK_RUN_TIME 3.0
28+
#define CLAR_BENCHMARK_RUN_MIN 10
29+
#define CLAR_BENCHMARK_RUN_MAX 30000000
30+
2131
#ifndef CLAR_SELFTEST
2232
# define CLAR_CURRENT_FILE __FILE__
2333
# define CLAR_CURRENT_LINE __LINE__

0 commit comments

Comments
 (0)