From 4eca708d8e693438d4e643dff7283f3cfb79d360 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Mon, 27 Mar 2023 10:02:38 +0200 Subject: Benchmark multiple cycles --- ' | 27 ++++ source/kit_test/bench.c | 311 ++++++++++++++++++++++++-------------- source/kit_test/bench.h | 85 +++++++---- source/kit_test/test.c | 94 ++++++------ source/kit_test/test.h | 2 +- source/test/unittests/foo.bench.c | 20 ++- 6 files changed, 346 insertions(+), 193 deletions(-) create mode 100644 ' diff --git a/' b/' new file mode 100644 index 0000000..438897f --- /dev/null +++ b/' @@ -0,0 +1,27 @@ +#define KIT_TEST_FILE foo +#include "../../kit_test/bench.h" + +struct test_foo_ { + double f; +}; + +BENCHMARK("foo") { + BENCHMARK_REPEAT(800); + + BENCHMARK_BEGIN; + { + int x = 0; + struct test_foo_ f = { 0. }; + + for (int i = 0; i < 100000; i++) { + x += (1 << 1); + x ^= i; + f.f += 0.1; + } + DO_NOT_OPTIMIZE(x); + DO_NOT_OPTIMIZE(f); + } + BENCHMARK_END; +} + +BENCHMARK("bar") { } diff --git a/source/kit_test/bench.c b/source/kit_test/bench.c index b7de35f..1dc2736 100644 --- a/source/kit_test/bench.c +++ b/source/kit_test/bench.c @@ -10,35 +10,51 @@ kit_benchs_list_t kit_benchs_list = { 0 }; +static void bench_set_repeats_limit(int i, int repeats_limit) { + if (kit_benchs_list.v[i].ready) + return; + if (kit_benchs_list.v[i].cycles_size >= KIT_BENCH_MAX_CYCLES) + return; + kit_benchs_list.v[i].cycles[kit_benchs_list.v[i].cycles_size] = + repeats_limit; + kit_benchs_list.v[i].cycles_size++; +} + +static int bench_loop(int i) { + if (!kit_benchs_list.v[i].ready) + return 0; + return kit_benchs_list.v[i].repeats < + kit_benchs_list.v[i].cycles[kit_benchs_list.v[i].cycle]; +} + static void bench_begin(int i) { - int const n = kit_benchs_list.benchs[i].repeats++; + int const n = kit_benchs_list.v[i].repeats++; - if (n >= KIT_BENCH_REPEATS) + if (n >= KIT_BENCH_MAX_REPEATS) return; struct timespec tv; timespec_get(&tv, TIME_UTC); - kit_benchs_list.benchs[i].sec[n] = (int64_t) tv.tv_sec; - kit_benchs_list.benchs[i].nsec[n] = (int64_t) tv.tv_nsec; + kit_benchs_list.v[i].sec[n] = (int64_t) tv.tv_sec; + kit_benchs_list.v[i].nsec[n] = (int64_t) tv.tv_nsec; } static void bench_end(int i) { - int const n = kit_benchs_list.benchs[i].repeats - 1; + int const n = kit_benchs_list.v[i].repeats - 1; - if (n < 0 || n >= KIT_BENCH_REPEATS) + if (n < 0 || n >= KIT_BENCH_MAX_REPEATS) return; struct timespec tv; timespec_get(&tv, TIME_UTC); int64_t const sec = ((int64_t) tv.tv_sec) - - kit_benchs_list.benchs[i].sec[n]; + kit_benchs_list.v[i].sec[n]; int64_t const nsec = ((int64_t) tv.tv_nsec) - - kit_benchs_list.benchs[i].nsec[n]; + kit_benchs_list.v[i].nsec[n]; - kit_benchs_list.benchs[i].duration_nsec[n] = sec * 1000000000 + - nsec; + kit_benchs_list.v[i].duration_nsec[n] = sec * 1000000000 + nsec; } enum { white, blue, light, yellow, red, green }; @@ -56,10 +72,13 @@ void kit_bench_register(char const *name, char const *file, kit_bench_run_fn fn) { int n = kit_benchs_list.size++; if (n < KIT_BENCHS_SIZE_LIMIT) { - kit_benchs_list.benchs[n].bench_fn = fn; - kit_benchs_list.benchs[n].bench_name = name; - kit_benchs_list.benchs[n].bench_file = file; - kit_benchs_list.benchs[n].repeats = 0; + kit_benchmark_t *const bench = kit_benchs_list.v + n; + + bench->bench_fn = fn; + bench->bench_name = name; + bench->bench_file = file; + bench->cycles_size = 0; + bench->ready = 0; } } @@ -85,7 +104,8 @@ static void setup_signals() { int i; for (i = 0; i < sizeof signums / sizeof *signums; i++) { -#if defined(_WIN32) && !(defined __CYGWIN__) +#if (defined(_WIN32) && !defined(__CYGWIN__)) || \ + !defined(_POSIX_C_SOURCE) signal(signums[i], handle_signal); #else struct sigaction action; @@ -101,11 +121,12 @@ static int run_bench(volatile int i) { int signum = setjmp(kit_bench_restore_execution); if (signum != 0) { - kit_benchs_list.benchs[i].signal = signum; + kit_benchs_list.v[i].signal = signum; return 0; } - kit_benchs_list.benchs[i].bench_fn(i, bench_begin, bench_end); + kit_benchs_list.v[i].bench_fn(i, bench_set_repeats_limit, + bench_loop, bench_begin, bench_end); return 1; } @@ -115,6 +136,12 @@ int compare_64_(void const *x_, void const *y_) { return *x - *y; } +int compare_32_(void const *x_, void const *y_) { + int const *x = (int const *) x_; + int const *y = (int const *) y_; + return *x - *y; +} + int kit_run_benchmarks(int argc, char **argv) { int success_count = 0; int status = 0; @@ -122,13 +149,11 @@ int kit_run_benchmarks(int argc, char **argv) { int line_width = 20; int carriage_return = 1; - int i, j; - char const *specific_bench = NULL; setup_signals(); - for (i = 0; i < argc; i++) + for (int i = 0; i < argc; i++) if (strcmp("--no-term-color", argv[i]) == 0) no_color = 1; else if (strcmp("--no-carriage-return", argv[i]) == 0) @@ -149,41 +174,40 @@ int kit_run_benchmarks(int argc, char **argv) { ptrdiff_t file_root = -1; int benchs_total = 0; - for (i = 0; i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; - i++) { + for (int i = 0; + i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) { if (specific_bench != NULL && - strstr(kit_benchs_list.benchs[i].bench_name, - specific_bench) == NULL) + strstr(kit_benchs_list.v[i].bench_name, specific_bench) == + NULL) continue; benchs_total++; - int const l = 2 + - (int) strlen(kit_benchs_list.benchs[i].bench_name); + int const l = 2 + (int) strlen(kit_benchs_list.v[i].bench_name); if (line_width < l) line_width = l; } if (benchs_total > 0) { - char const *const s = kit_benchs_list.benchs[0].bench_file; + char const *const s = kit_benchs_list.v[0].bench_file; + + for (int j = 1; + j < kit_benchs_list.size && j < KIT_BENCHS_SIZE_LIMIT; j++) { + kit_benchmark_t *const bench = kit_benchs_list.v + j; - for (j = 1; j < kit_benchs_list.size && j < KIT_BENCHS_SIZE_LIMIT; - j++) { if (specific_bench != NULL && - strstr(kit_benchs_list.benchs[j].bench_name, - specific_bench) == NULL) + strstr(bench->bench_name, specific_bench) == NULL) continue; - if (strcmp(s, kit_benchs_list.benchs[j].bench_file) == 0) + if (strcmp(s, bench->bench_file) == 0) continue; int k = 0; - for (; s[k] != '\0' && - kit_benchs_list.benchs[j].bench_file[k] != '\0' && - s[k] == kit_benchs_list.benchs[j].bench_file[k]; + for (; s[k] != '\0' && bench->bench_file[k] != '\0' && + s[k] == bench->bench_file[k]; k++) { } if (file_root == -1 || file_root > k) file_root = k; } if (file_root == -1) { - for (i = 0; s[i] != '\0'; i++) + for (int i = 0; s[i] != '\0'; i++) if (s[i] == '/' || s[i] == '\\') file_root = i + 1; } @@ -207,91 +231,150 @@ int kit_run_benchmarks(int argc, char **argv) { no_color || print_color(light); printf(" in nanoseconds\n\n"); - for (i = 0; i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; - i++) { + /* Prepare cycles. + */ + + for (int i = 0; + i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) { + kit_benchmark_t *const bench = kit_benchs_list.v + i; + if (specific_bench != NULL && - strstr(kit_benchs_list.benchs[i].bench_name, - specific_bench) == NULL) + strstr(bench->bench_name, specific_bench) == NULL) continue; - if (file == NULL || - strcmp(file, kit_benchs_list.benchs[i].bench_file) != 0) { - if (file != NULL) - printf("\n"); - file = kit_benchs_list.benchs[i].bench_file; - no_color || print_color(blue); - printf("* "); - no_color || print_color(white); - printf("%s\n", file + file_root); + + run_bench(i); + + if (bench->cycles_size == 0) { + bench->cycles_size = 2; + bench->cycles[0] = KIT_BENCH_REPEATS_DEFAULT_1; + bench->cycles[1] = KIT_BENCH_REPEATS_DEFAULT_2; } - !carriage_return || no_color || print_color(yellow); - carriage_return || no_color || print_color(light); - printf("` %s ", kit_benchs_list.benchs[i].bench_name); - !carriage_return || printf("\r"); - fflush(stdout); - - int bench_status = run_bench(i); - - if (kit_benchs_list.benchs[i].repeats > KIT_BENCH_REPEATS) - bench_status = 0; - - !carriage_return || no_color || print_color(light); - !carriage_return || - printf("` %s ", kit_benchs_list.benchs[i].bench_name); - - int const l = (int) strlen(kit_benchs_list.benchs[i].bench_name); - printf("%*c", line_width - l, ' '); - - if (kit_benchs_list.benchs[i].repeats <= 0) { - no_color || print_color(yellow); - printf(" 0 runs\n"); - success_count++; - } else if (bench_status == 0) { - no_color || print_color(red); - printf(" FAIL\n"); - status = 1; - } else { - int const repeats = kit_benchs_list.benchs[i].repeats; - - qsort(kit_benchs_list.benchs[i].duration_nsec, repeats, - sizeof *kit_benchs_list.benchs[i].duration_nsec, - compare_64_); - - int64_t const average = - kit_benchs_list.benchs[i].duration_nsec[repeats / 2]; - int64_t const floor = - kit_benchs_list.benchs[i].duration_nsec[repeats / 20]; - int64_t const roof = - kit_benchs_list.benchs[i] - .duration_nsec[repeats - repeats / 20 - 1]; - - no_color || print_color(white); - printf("%-8lld", (long long) floor); - no_color || print_color(light); - printf("| "); - no_color || print_color(white); - printf("%-8lld", (long long) average); - no_color || print_color(light); - printf("| "); - no_color || print_color(white); - printf("%-8lld", (long long) roof); - no_color || print_color(light); - printf(" %d runs\n", repeats); - success_count++; + qsort(bench->cycles, bench->cycles_size, sizeof *bench->cycles, + compare_32_); + + kit_benchs_list.v[i].ready = 1; + } + + /* Run cycles. + */ + + for (int cycle = 0; cycle < KIT_BENCH_MAX_CYCLES; cycle++) { + /* Prepare cycle. + */ + + int cycles_done = 1; + + for (int i = 0; + i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) { + kit_benchmark_t *const bench = kit_benchs_list.v + i; + + if (specific_bench != NULL && + strstr(bench->bench_name, specific_bench) == NULL) + continue; + if (cycle >= bench->cycles_size) + continue; + + bench->repeats = 0; + bench->cycle = cycle; + cycles_done = 0; + } + + if (cycles_done) + break; + + /* Run benchmarks. + */ + + for (int i = 0; + i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) { + kit_benchmark_t *const bench = kit_benchs_list.v + i; + + if (specific_bench != NULL && + strstr(bench->bench_name, specific_bench) == NULL) + continue; + if (cycle >= bench->cycles_size) + continue; + + if (file == NULL || strcmp(file, bench->bench_file) != 0) { + if (file != NULL) + printf("\n"); + file = bench->bench_file; + no_color || print_color(blue); + printf("* "); + no_color || print_color(white); + printf("%s\n", file + file_root); + } + + !carriage_return || no_color || print_color(yellow); + carriage_return || no_color || print_color(light); + printf("` %s ", bench->bench_name); + !carriage_return || printf("\r"); + fflush(stdout); + + int bench_status = run_bench(i); + + if (bench->repeats > KIT_BENCH_MAX_REPEATS) + bench_status = 0; + + !carriage_return || no_color || print_color(light); + !carriage_return || printf("` %s ", bench->bench_name); + + int const l = (int) strlen(bench->bench_name); + printf("%*c", line_width - l, ' '); + + if (bench->repeats <= 0) { + no_color || print_color(yellow); + printf(" 0 runs\n"); + success_count++; + } else if (bench_status == 0) { + no_color || print_color(red); + printf(" FAIL\n"); + status = 1; + } else { + int const repeats = bench->repeats; + + memcpy(bench->duration_sorted_nsec, bench->duration_nsec, + repeats * sizeof *bench->duration_sorted_nsec); + qsort(bench->duration_sorted_nsec, repeats, + sizeof *bench->duration_sorted_nsec, compare_64_); + + int64_t const average = + bench->duration_sorted_nsec[repeats / 2]; + int64_t const floor = + bench->duration_sorted_nsec[repeats / 20]; + int64_t const roof = + bench->duration_sorted_nsec[repeats - repeats / 20 - 1]; + + no_color || print_color(white); + printf("%-8lld", (long long) floor); + no_color || print_color(light); + printf("| "); + no_color || print_color(white); + printf("%-8lld", (long long) average); + no_color || print_color(light); + printf("| "); + no_color || print_color(white); + printf("%-8lld", (long long) roof); + no_color || print_color(light); + printf(" %d runs\n", repeats); + success_count++; + } } } printf("\n"); if (status != 0) { - for (i = 0; i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; - i++) { + for (int i = 0; + i < kit_benchs_list.size && i < KIT_BENCHS_SIZE_LIMIT; i++) { + kit_benchmark_t *const bench = kit_benchs_list.v + i; + if (specific_bench != NULL && - strstr(kit_benchs_list.benchs[i].bench_name, - specific_bench) == NULL) + strstr(bench->bench_name, specific_bench) == NULL) continue; - if (kit_benchs_list.benchs[i].signal != 0) { - int signum = kit_benchs_list.benchs[i].signal; + if (bench->signal != 0) { + int signum = bench->signal; if (signum >= 0 && signum < sizeof signames / sizeof *signames && signames[signum] != NULL) { @@ -299,24 +382,22 @@ int kit_run_benchmarks(int argc, char **argv) { printf("Signal \"%s\" (%d) for \"", signames[signum], signum); no_color || print_color(white); - printf("%s", kit_benchs_list.benchs[i].bench_name); + printf("%s", bench->bench_name); no_color || print_color(light); printf("\" in \""); no_color || print_color(white); - printf("%s", - kit_benchs_list.benchs[i].bench_file + file_root); + printf("%s", bench->bench_file + file_root); no_color || print_color(light); printf("\"!.\n"); } else { no_color || print_color(light); printf("Unknown signal (%d) for \"", signum); no_color || print_color(white); - printf("%s", kit_benchs_list.benchs[i].bench_name); + printf("%s", bench->bench_name); no_color || print_color(light); printf("\" in \""); no_color || print_color(white); - printf("%s", - kit_benchs_list.benchs[i].bench_file + file_root); + printf("%s", bench->bench_file + file_root); no_color || print_color(light); printf("\"!.\n"); } diff --git a/source/kit_test/bench.h b/source/kit_test/bench.h index 6c701bb..ba3e0f5 100644 --- a/source/kit_test/bench.h +++ b/source/kit_test/bench.h @@ -8,38 +8,62 @@ extern "C" { #include "test.h" #include -#ifndef KIT_BENCH_FILE -# define KIT_BENCH_FILE kit_bench +#ifndef KIT_TEST_FILE +# define KIT_TEST_FILE kit_bench #endif #ifndef KIT_BENCHS_SIZE_LIMIT # define KIT_BENCHS_SIZE_LIMIT 0x1000 #endif -#ifndef KIT_BENCH_REPEATS -# define KIT_BENCH_REPEATS 400 +#ifndef KIT_BENCH_MAX_REPEATS +# define KIT_BENCH_MAX_REPEATS 4000 #endif +#ifndef KIT_BENCH_MAX_CYCLES +# define KIT_BENCH_MAX_CYCLES 40 +#endif + +#ifndef KIT_BENCH_REPEATS_DEFAULT_1 +# define KIT_BENCH_REPEATS_DEFAULT_1 40 +#endif + +#ifndef KIT_BENCH_REPEATS_DEFAULT_2 +# define KIT_BENCH_REPEATS_DEFAULT_2 400 +#endif + +typedef void (*kit_bench_set_repeats_limit_fn)(int bench_index, + int repeats_limit); +typedef int (*kit_bench_loop_fn)(int bench_index); typedef void (*kit_bench_begin_fn)(int bench_index); typedef void (*kit_bench_end_fn)(int bench_index); + typedef void (*kit_bench_run_fn)( - int kit_bench_index_, kit_bench_begin_fn kit_bench_begin_fn_, - kit_bench_end_fn kit_bench_end_fn_); + int kit_bench_index_, + kit_bench_set_repeats_limit_fn kit_bench_set_repeats_limit_, + kit_bench_loop_fn kit_bench_loop_, + kit_bench_begin_fn kit_bench_begin_, + kit_bench_end_fn kit_bench_end_); typedef struct { char const *bench_name; char const *bench_file; kit_bench_run_fn bench_fn; - int64_t sec[KIT_BENCH_REPEATS]; - int32_t nsec[KIT_BENCH_REPEATS]; - int64_t duration_nsec[KIT_BENCH_REPEATS]; + int64_t sec[KIT_BENCH_MAX_REPEATS]; + int32_t nsec[KIT_BENCH_MAX_REPEATS]; + int64_t duration_nsec[KIT_BENCH_MAX_REPEATS]; + int64_t duration_sorted_nsec[KIT_BENCH_MAX_REPEATS]; int repeats; + int cycles_size; + int cycles[KIT_BENCH_MAX_CYCLES]; + int cycle; int signal; + int ready; } kit_benchmark_t; typedef struct { int size; - kit_benchmark_t benchs[KIT_BENCHS_SIZE_LIMIT]; + kit_benchmark_t v[KIT_BENCHS_SIZE_LIMIT]; } kit_benchs_list_t; extern kit_benchs_list_t kit_benchs_list; @@ -49,28 +73,34 @@ void kit_bench_register(char const *name, char const *file, #define KIT_BENCHMARK(name) \ static void KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, \ - KIT_BENCH_FILE)( \ - int, kit_bench_begin_fn, kit_bench_end_fn); \ + KIT_TEST_FILE)( \ + int, kit_bench_set_repeats_limit_fn, kit_bench_loop_fn, \ + kit_bench_begin_fn, kit_bench_end_fn); \ KIT_TEST_ON_START_( \ - KIT_TEST_CONCAT3_(kit_benchmark_, __LINE__, KIT_BENCH_FILE)) { \ - kit_bench_register(name, __FILE__, \ - KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, \ - KIT_BENCH_FILE)); \ + KIT_TEST_CONCAT3_(kit_benchmark_, __LINE__, KIT_TEST_FILE)) { \ + kit_bench_register( \ + name, __FILE__, \ + KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, KIT_TEST_FILE)); \ } \ static void KIT_TEST_CONCAT3_(kit_bench_run_, __LINE__, \ - KIT_BENCH_FILE)( \ - int kit_bench_index_, kit_bench_begin_fn kit_bench_begin_fn_, \ - kit_bench_end_fn kit_bench_end_fn_) - -#define KIT_BENCHMARK_BEGIN \ - for (int kit_bench_repeat_ = 0; \ - kit_bench_repeat_ < KIT_BENCH_REPEATS; kit_bench_repeat_++) { \ - kit_bench_begin_fn_(kit_bench_index_); \ + KIT_TEST_FILE)( \ + int kit_bench_index_, \ + kit_bench_set_repeats_limit_fn kit_bench_set_repeats_limit_, \ + kit_bench_loop_fn kit_bench_loop_, \ + kit_bench_begin_fn kit_bench_begin_, \ + kit_bench_end_fn kit_bench_end_) + +#define KIT_BENCHMARK_REPEAT(repeats_limit_) \ + kit_bench_set_repeats_limit_(kit_bench_index_, repeats_limit_) + +#define KIT_BENCHMARK_BEGIN \ + while (kit_bench_loop_(kit_bench_index_)) { \ + kit_bench_begin_(kit_bench_index_); \ { -#define KIT_BENCHMARK_END \ - } \ - kit_bench_end_fn_(kit_bench_index_); \ +#define KIT_BENCHMARK_END \ + } \ + kit_bench_end_(kit_bench_index_); \ } /* FIXME @@ -85,6 +115,7 @@ int kit_run_benchmarks(int argc, char **argv); #ifndef KIT_DISABLE_SHORT_NAMES # define BENCHMARK KIT_BENCHMARK +# define BENCHMARK_REPEAT KIT_BENCHMARK_REPEAT # define BENCHMARK_BEGIN KIT_BENCHMARK_BEGIN # define BENCHMARK_END KIT_BENCHMARK_END # define DO_NOT_OPTIMIZE KIT_DO_NOT_OPTIMIZE diff --git a/source/kit_test/test.c b/source/kit_test/test.c index 3d3e180..6603d65 100644 --- a/source/kit_test/test.c +++ b/source/kit_test/test.c @@ -10,13 +10,13 @@ kit_tests_list_t kit_tests_list = { 0 }; static void report(int i, int line, int ok) { - int const n = kit_tests_list.tests[i].assertions++; + int const n = kit_tests_list.v[i].assertions++; if (n >= KIT_TEST_ASSERTIONS_LIMIT) return; - kit_tests_list.tests[i].line[n] = line; - kit_tests_list.tests[i].status[n] = ok; + kit_tests_list.v[i].line[n] = line; + kit_tests_list.v[i].status[n] = ok; } static long long ns_to_ms(long long ns) { @@ -42,10 +42,10 @@ void kit_test_register(char const *name, char const *file, kit_test_run_fn fn) { int n = kit_tests_list.size++; if (n < KIT_TESTS_SIZE_LIMIT) { - kit_tests_list.tests[n].test_fn = fn; - kit_tests_list.tests[n].test_name = name; - kit_tests_list.tests[n].test_file = file; - kit_tests_list.tests[n].assertions = 0; + kit_tests_list.v[n].test_fn = fn; + kit_tests_list.v[n].test_name = name; + kit_tests_list.v[n].test_file = file; + kit_tests_list.v[n].assertions = 0; } } @@ -71,7 +71,8 @@ static void setup_signals() { int i; for (i = 0; i < sizeof signums / sizeof *signums; i++) { -#if defined(_WIN32) && !(defined __CYGWIN__) +#if (defined(_WIN32) && !defined(__CYGWIN__)) || \ + !defined(_POSIX_C_SOURCE) signal(signums[i], handle_signal); #else struct sigaction action; @@ -87,11 +88,11 @@ static int run_test(volatile int i) { int signum = setjmp(kit_test_restore_execution); if (signum != 0) { - kit_tests_list.tests[i].signal = signum; + kit_tests_list.v[i].signal = signum; return 0; } - kit_tests_list.tests[i].test_fn(i, report); + kit_tests_list.v[i].test_fn(i, report); return 1; } @@ -139,30 +140,29 @@ int kit_run_tests(int argc, char **argv) { for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT; i++) { if (specific_test != NULL && - strstr(kit_tests_list.tests[i].test_name, specific_test) == - NULL) + strstr(kit_tests_list.v[i].test_name, specific_test) == NULL) continue; tests_total++; - int const l = 2 + (int) strlen(kit_tests_list.tests[i].test_name); + int const l = 2 + (int) strlen(kit_tests_list.v[i].test_name); if (line_width < l) line_width = l; } if (tests_total > 0) { - char const *const s = kit_tests_list.tests[0].test_file; + char const *const s = kit_tests_list.v[0].test_file; for (j = 1; j < kit_tests_list.size && j < KIT_TESTS_SIZE_LIMIT; j++) { if (specific_test != NULL && - strstr(kit_tests_list.tests[j].test_name, specific_test) == + strstr(kit_tests_list.v[j].test_name, specific_test) == NULL) continue; - if (strcmp(s, kit_tests_list.tests[j].test_file) == 0) + if (strcmp(s, kit_tests_list.v[j].test_file) == 0) continue; int k = 0; - for (; s[k] != '\0' && - kit_tests_list.tests[j].test_file[k] != '\0' && - s[k] == kit_tests_list.tests[j].test_file[k]; + for (; + s[k] != '\0' && kit_tests_list.v[j].test_file[k] != '\0' && + s[k] == kit_tests_list.v[j].test_file[k]; k++) { } if (file_root == -1 || file_root > k) file_root = k; @@ -178,14 +178,13 @@ int kit_run_tests(int argc, char **argv) { for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT; i++) { if (specific_test != NULL && - strstr(kit_tests_list.tests[i].test_name, specific_test) == - NULL) + strstr(kit_tests_list.v[i].test_name, specific_test) == NULL) continue; if (file == NULL || - strcmp(file, kit_tests_list.tests[i].test_file) != 0) { + strcmp(file, kit_tests_list.v[i].test_file) != 0) { if (file != NULL) quiet || printf("\n"); - file = kit_tests_list.tests[i].test_file; + file = kit_tests_list.v[i].test_file; no_color || print_color(blue); quiet || printf("* "); no_color || print_color(white); @@ -194,7 +193,7 @@ int kit_run_tests(int argc, char **argv) { !carriage_return || no_color || print_color(yellow); carriage_return || no_color || print_color(light); - quiet || printf("` %s ", kit_tests_list.tests[i].test_name); + quiet || printf("` %s ", kit_tests_list.v[i].test_name); !carriage_return || quiet || printf("\r"); quiet || fflush(stdout); @@ -207,23 +206,22 @@ int kit_run_tests(int argc, char **argv) { int duration = (int) (ns_to_ms(end.tv_nsec - begin.tv_nsec) + sec_to_ms(end.tv_sec - begin.tv_sec)); - for (j = 0; j < kit_tests_list.tests[i].assertions; j++) - if (kit_tests_list.tests[i].status[j] == 0) { + for (j = 0; j < kit_tests_list.v[i].assertions; j++) + if (kit_tests_list.v[i].status[j] == 0) { fail_assertion_count++; test_status = 0; } - if (kit_tests_list.tests[i].assertions > - KIT_TEST_ASSERTIONS_LIMIT) + if (kit_tests_list.v[i].assertions > KIT_TEST_ASSERTIONS_LIMIT) test_status = 0; - total_assertion_count += kit_tests_list.tests[i].assertions; + total_assertion_count += kit_tests_list.v[i].assertions; !carriage_return || no_color || print_color(light); !carriage_return || quiet || - printf("` %s ", kit_tests_list.tests[i].test_name); + printf("` %s ", kit_tests_list.v[i].test_name); - int const l = (int) strlen(kit_tests_list.tests[i].test_name); + int const l = (int) strlen(kit_tests_list.v[i].test_name); quiet || printf("%*c", line_width - l, ' '); if (test_status == 0) { @@ -256,11 +254,11 @@ int kit_run_tests(int argc, char **argv) { for (i = 0; i < kit_tests_list.size && i < KIT_TESTS_SIZE_LIMIT; i++) { if (specific_test != NULL && - strstr(kit_tests_list.tests[i].test_name, specific_test) == + strstr(kit_tests_list.v[i].test_name, specific_test) == NULL) continue; - if (kit_tests_list.tests[i].signal != 0) { - int signum = kit_tests_list.tests[i].signal; + if (kit_tests_list.v[i].signal != 0) { + int signum = kit_tests_list.v[i].signal; if (signum >= 0 && signum < sizeof signames / sizeof *signames && signames[signum] != NULL) { @@ -268,52 +266,52 @@ int kit_run_tests(int argc, char **argv) { quiet || printf("Signal \"%s\" (%d) for \"", signames[signum], signum); no_color || print_color(white); - quiet || printf("%s", kit_tests_list.tests[i].test_name); + quiet || printf("%s", kit_tests_list.v[i].test_name); no_color || print_color(light); quiet || printf("\" in \""); no_color || print_color(white); - quiet || printf("%s", kit_tests_list.tests[i].test_file + - file_root); + quiet || + printf("%s", kit_tests_list.v[i].test_file + file_root); no_color || print_color(light); quiet || printf("\"!.\n"); } else { no_color || print_color(light); quiet || printf("Unknown signal (%d) for \"", signum); no_color || print_color(white); - quiet || printf("%s", kit_tests_list.tests[i].test_name); + quiet || printf("%s", kit_tests_list.v[i].test_name); no_color || print_color(light); quiet || printf("\" in \""); no_color || print_color(white); - quiet || printf("%s", kit_tests_list.tests[i].test_file + - file_root); + quiet || + printf("%s", kit_tests_list.v[i].test_file + file_root); no_color || print_color(light); quiet || printf("\"!.\n"); } } - if (kit_tests_list.tests[i].assertions > + if (kit_tests_list.v[i].assertions > KIT_TEST_ASSERTIONS_LIMIT) { no_color || print_color(light); quiet || printf("Too many assertions for \""); no_color || print_color(white); - quiet || printf("%s", kit_tests_list.tests[i].test_name); + quiet || printf("%s", kit_tests_list.v[i].test_name); no_color || print_color(light); quiet || printf("\" in \""); no_color || print_color(white); - quiet || printf("%s", kit_tests_list.tests[i].test_file + - file_root); + quiet || + printf("%s", kit_tests_list.v[i].test_file + file_root); no_color || print_color(light); quiet || printf("\"!.\n"); } else - for (j = 0; j < kit_tests_list.tests[i].assertions; j++) - if (!kit_tests_list.tests[i].status[j]) { + for (j = 0; j < kit_tests_list.v[i].assertions; j++) + if (!kit_tests_list.v[i].status[j]) { no_color || print_color(light); quiet || printf("Assertion on line "); no_color || print_color(white); - quiet || printf("%d", kit_tests_list.tests[i].line[j]); + quiet || printf("%d", kit_tests_list.v[i].line[j]); no_color || print_color(light); quiet || printf(" in \""); no_color || print_color(white); - quiet || printf("%s", kit_tests_list.tests[i].test_file + + quiet || printf("%s", kit_tests_list.v[i].test_file + file_root); no_color || print_color(light); quiet || printf("\" failed.\n"); diff --git a/source/kit_test/test.h b/source/kit_test/test.h index 39c28e7..44aae09 100644 --- a/source/kit_test/test.h +++ b/source/kit_test/test.h @@ -35,7 +35,7 @@ typedef struct { typedef struct { int size; - kit_test_case_t tests[KIT_TESTS_SIZE_LIMIT]; + kit_test_case_t v[KIT_TESTS_SIZE_LIMIT]; } kit_tests_list_t; extern kit_tests_list_t kit_tests_list; diff --git a/source/test/unittests/foo.bench.c b/source/test/unittests/foo.bench.c index a3d5c18..ac1e0b5 100644 --- a/source/test/unittests/foo.bench.c +++ b/source/test/unittests/foo.bench.c @@ -1,4 +1,4 @@ -#define KIT_BENCH_FILE foo +#define KIT_TEST_FILE foo #include "../../kit_test/bench.h" struct test_foo_ { @@ -6,8 +6,15 @@ struct test_foo_ { }; BENCHMARK("foo") { + + /* Benchmark setup. + */ + BENCHMARK_BEGIN; { + /* Measured code snippet. + */ + int x = 0; struct test_foo_ f = { 0. }; @@ -16,10 +23,19 @@ BENCHMARK("foo") { x ^= i; f.f += 0.1; } + DO_NOT_OPTIMIZE(x); DO_NOT_OPTIMIZE(f); } BENCHMARK_END; } -BENCHMARK("bar") { } +BENCHMARK("bar") { + BENCHMARK_REPEAT(10); + BENCHMARK_REPEAT(100); + + BENCHMARK_BEGIN; + BENCHMARK_END; +} + +BENCHMARK("empty") { } -- cgit v1.2.3