Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add simple benchmarking #74

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions clar.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ struct clar_error {
struct clar_error *next;
};

struct clar_timing {
const char *test;
const char *suite;

double elapsed;

struct clar_timing *next;
};

static struct {
int argc;
char **argv;
Expand All @@ -124,9 +133,16 @@ static struct {
int exit_on_error;
int report_suite_names;

int report_benchmarks;
double timing_start;
double timing_end;

struct clar_error *errors;
struct clar_error *last_error;

struct clar_timing *timings;
struct clar_timing *last_timing;

void (*local_cleanup)(void *);
void *local_cleanup_payload;

Expand Down Expand Up @@ -156,6 +172,7 @@ struct clar_suite {
static void clar_print_init(int test_count, int suite_count, const char *suite_names);
static void clar_print_shutdown(int test_count, int suite_count, int error_count);
static void clar_print_error(int num, const struct clar_error *error);
static void clar_print_timing(const struct clar_timing *timing);
static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status failed);
static void clar_print_onsuite(const char *suite_name, int suite_index);
static void clar_print_onabort(const char *msg, ...);
Expand All @@ -164,6 +181,12 @@ static void clar_print_onabort(const char *msg, ...);
static void clar_unsandbox(void);
static int clar_sandbox(void);

/* From time.h */
/**
* Return the time from a monotonic timer.
*/
static double clar_timer(void);

/* Load the declarations for the test suite */
#include "clar.suite"

Expand Down Expand Up @@ -203,13 +226,31 @@ clar_report_errors(void)
_clar.errors = _clar.last_error = NULL;
}

static void
clar_report_timings(void)
{
struct clar_timing *timing, *next;

timing = _clar.timings;

while (timing != NULL) {
next = timing->next;
clar_print_timing(timing);
free(timing);
timing = next;
}

}

static void
clar_run_test(
const struct clar_func *test,
const struct clar_func *initialize,
const struct clar_func *cleanup)
{
_clar.test_status = CL_TEST_OK;
_clar.timing_start = 0.0;
_clar.timing_end = 0.0;
_clar.trampoline_enabled = 1;

CL_TRACE(CL_TRACE__TEST__BEGIN);
Expand All @@ -219,7 +260,9 @@ clar_run_test(
initialize->ptr();

CL_TRACE(CL_TRACE__TEST__RUN_BEGIN);
_clar.timing_start = clar_timer();
test->ptr();
_clar.timing_end = clar_timer();
CL_TRACE(CL_TRACE__TEST__RUN_END);
}

Expand All @@ -246,6 +289,8 @@ clar_run_test(
}
}

static void clar_store_timing(void);

static void
clar_run_suite(const struct clar_suite *suite, const char *filter)
{
Expand Down Expand Up @@ -287,6 +332,8 @@ clar_run_suite(const struct clar_suite *suite, const char *filter)

if (_clar.exit_on_error && _clar.total_errors)
return;

clar_store_timing();
}

_clar.active_test = NULL;
Expand All @@ -305,6 +352,7 @@ clar_usage(const char *arg)
printf(" -q \tOnly report tests that had an error\n");
printf(" -Q \tQuit as soon as a test fails\n");
printf(" -l \tPrint suite names\n");
printf(" -b \tReport test benchmarks\n");
exit(-1);
}

Expand Down Expand Up @@ -356,13 +404,22 @@ clar_parse_args(int argc, char **argv)
}
}

if (_clar.report_benchmarks) {
puts("");
clar_report_timings();
}

if (!found) {
clar_print_onabort("No suite matching '%s' found.\n", argument);
exit(-1);
}
break;
}

case 'b':
_clar.report_benchmarks = 1;
break;

case 'q':
_clar.report_errors_only = 1;
break;
Expand Down Expand Up @@ -418,6 +475,11 @@ clar_test_run()
size_t i;
for (i = 0; i < _clar_suite_count; ++i)
clar_run_suite(&_clar_suites[i], NULL);

if (_clar.report_benchmarks) {
puts("");
clar_report_timings();
}
}

return _clar.total_errors;
Expand Down Expand Up @@ -447,6 +509,29 @@ clar_test(int argc, char **argv)
return errors;
}

static void clar_store_timing(void)
{
struct clar_timing *timing;

/* Failed tests jump over the timing code */
if (_clar.timing_end == 0)
return;

timing = calloc(1, sizeof(struct clar_timing));

if (_clar.timings == NULL)
_clar.timings = timing;

if (_clar.last_timing != NULL)
_clar.last_timing->next = timing;

_clar.last_timing = timing;

timing->elapsed = _clar.timing_end - _clar.timing_start;
timing->test = _clar.active_test;
timing->suite = _clar.active_suite;
}

static void abort_test(void)
{
if (!_clar.trampoline_enabled) {
Expand All @@ -460,6 +545,11 @@ static void abort_test(void)
longjmp(_clar.trampoline, -1);
}

void clar__reset_timer(void)
{
_clar.timing_start = clar_timer();
}

void clar__skip(void)
{
_clar.test_status = CL_TEST_SKIP;
Expand Down Expand Up @@ -640,3 +730,4 @@ void cl_set_cleanup(void (*cleanup)(void *), void *opaque)
#include "clar/fixtures.h"
#include "clar/fs.h"
#include "clar/print.h"
#include "clar/time.h"
7 changes: 7 additions & 0 deletions clar.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ void cl_fixture_cleanup(const char *fixture_name);

#define cl_skip() clar__skip()

/**
* Timer-related functions
*/
#define cl_reset_timer() clar__reset_timer()

/**
* Typed assertion macros
*/
Expand All @@ -133,6 +138,8 @@ void cl_fixture_cleanup(const char *fixture_name);

#define cl_assert_equal_p(p1,p2) clar__assert_equal(__FILE__,__LINE__,"Pointer mismatch: " #p1 " != " #p2, 1, "%p", (p1), (p2))

void clar__reset_timer(void);

void clar__skip(void);

void clar__fail(
Expand Down
6 changes: 6 additions & 0 deletions clar/print.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ static void clar_print_error(int num, const struct clar_error *error)
fflush(stdout);
}

static void clar_print_timing(const struct clar_timing *timing)
{
printf("Benchmark %s::%s %f\n", timing->suite, timing->test, timing->elapsed);
fflush(stdout);
}

static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status status)
{
(void)test_name;
Expand Down
71 changes: 71 additions & 0 deletions clar/time.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#ifdef GIT_WIN32

double clar_timer(void)
{
/* We need the initial tick count to detect if the tick
* count has rolled over. */
static DWORD initial_tick_count = 0;

/* GetTickCount returns the number of milliseconds that have
* elapsed since the system was started. */
DWORD count = GetTickCount();

if(initial_tick_count == 0) {
initial_tick_count = count;
} else if (count < initial_tick_count) {
/* The tick count has rolled over - adjust for it. */
count = (0xFFFFFFFF - initial_tick_count) + count;
}

return (double count / (double 1000));
}

#elif __APPLE__

#include <mach/mach_time.h>

double clar_timer(void)
{
uint64_t time = mach_absolute_time();
static double scaling_factor = 0;

if (scaling_factor == 0) {
mach_timebase_info_data_t info;
(void)mach_timebase_info(&info);
scaling_factor = (double)info.numer / (double)info.denom;
}

return (double)time * scaling_factor / 1.0E9;
}

#elif defined(AMIGA)

#include <proto/timer.h>

double clar_timer(void)
{
struct TimeVal tv;
ITimer->GetUpTime(&tv);
return (doubletv.Seconds + (doubletv.Microseconds / 1.0E6));
}

#else

#include <sys/time.h>

double clar_timer(void)
{
struct timespec tp;

if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
return (double tp.tv_sec + (double tp.tv_nsec / 1.0E9));
} else {
/* Fall back to using gettimeofday */
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
return (doubletv.tv_sec + (doubletv.tv_usec / 1.0E6));
}
}

#endif
1 change: 1 addition & 0 deletions test/clar_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@

/* Your custom shared includes / defines here */
extern int global_test_counter;
extern int global_is_bench;

#endif
2 changes: 1 addition & 1 deletion test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int main(int argc, char *argv[])
ret = clar_test(argc, argv);

/* Your custom cleanup here */
cl_assert_equal_i(8, global_test_counter);
cl_assert_equal_i(11, global_test_counter);

return ret;
}
30 changes: 30 additions & 0 deletions test/sample.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,33 @@ void test_sample__ptr(void)
cl_assert_equal_p(actual, actual); /* pointers to same object */
cl_assert_equal_p(&actual, actual);
}

void test_sample__bench_loop(void)
{
int i;

for (i = 0; i < 1000000; i++) {
}
}

void test_sample__bench_loop2(void)
{
int i;

for (i = 0; i < 1000000; i++) {
int dummy = i*1000;
dummy = dummy;
}
}

void test_sample__bench_reset_timer(void)
{
int i;

for (i = 0; i < 100000000; i++) {
int dummy = i*1000;
dummy = dummy;
}

cl_reset_timer();
}