diff options
Diffstat (limited to 'benchmark')
-rw-r--r-- | benchmark/.clang-tidy | 3 | ||||
-rw-r--r-- | benchmark/bench.h | 16 | ||||
-rw-r--r-- | benchmark/dict_bench.c | 19 | ||||
-rw-r--r-- | benchmark/meson.build | 11 | ||||
-rw-r--r-- | benchmark/tree_bench.c | 77 |
5 files changed, 64 insertions, 62 deletions
diff --git a/benchmark/.clang-tidy b/benchmark/.clang-tidy index b89626f..6b582c0 100644 --- a/benchmark/.clang-tidy +++ b/benchmark/.clang-tidy @@ -1,4 +1,4 @@ -# Copyright 2020-2022 David Robillard <d@drobilla.net> +# Copyright 2020-2025 David Robillard <d@drobilla.net> # SPDX-License-Identifier: 0BSD OR ISC Checks: > @@ -6,6 +6,7 @@ Checks: > -android-cloexec-fopen, -bugprone-easily-swappable-parameters, -cert-err33-c, + -clang-analyzer-core.NonNullParamChecker, -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling, -llvm-header-guard, -performance-no-int-to-ptr, diff --git a/benchmark/bench.h b/benchmark/bench.h index bcfe077..2a25b11 100644 --- a/benchmark/bench.h +++ b/benchmark/bench.h @@ -1,33 +1,29 @@ -// Copyright 2011-2020 David Robillard <d@drobilla.net> +// Copyright 2011-2024 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC #ifndef BENCH_H #define BENCH_H -#include <time.h> +#include <glib.h> -typedef struct timespec BenchmarkTime; +typedef gint64 BenchmarkTime; static inline double bench_elapsed_s(const BenchmarkTime* start, const BenchmarkTime* end) { - return ((double)(end->tv_sec - start->tv_sec) + - ((double)(end->tv_nsec - start->tv_nsec) * 0.000000001)); + return (double)(*end - *start) * 0.000001; } static inline BenchmarkTime bench_start(void) { - BenchmarkTime start_t; - clock_gettime(CLOCK_REALTIME, &start_t); - return start_t; + return g_get_monotonic_time(); } static inline double bench_end(const BenchmarkTime* start_t) { - BenchmarkTime end_t; - clock_gettime(CLOCK_REALTIME, &end_t); + const BenchmarkTime end_t = g_get_monotonic_time(); return bench_elapsed_s(start_t, &end_t); } diff --git a/benchmark/dict_bench.c b/benchmark/dict_bench.c index 279e6ad..9184fb4 100644 --- a/benchmark/dict_bench.c +++ b/benchmark/dict_bench.c @@ -12,10 +12,10 @@ typedef struct { #define ZIX_HASH_KEY_TYPE ZixChunk #define ZIX_HASH_RECORD_TYPE ZixChunk -#include "zix/attributes.h" -#include "zix/digest.h" -#include "zix/hash.h" -#include "zix/status.h" +#include <zix/attributes.h> +#include <zix/digest.h> +#include <zix/hash.h> +#include <zix/status.h> ZIX_DISABLE_GLIB_WARNINGS #include <glib.h> @@ -27,7 +27,6 @@ ZIX_RESTORE_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <time.h> typedef struct { ZixChunk* chunks; @@ -45,8 +44,7 @@ lcg64(const uint64_t i) return (a * i) + c; } -ZIX_PURE_FUNC -static const ZixChunk* +ZIX_PURE_FUNC static const ZixChunk* identity(const ZixChunk* record) { return record; @@ -93,6 +91,7 @@ read_inputs(FILE* const fd) inputs.chunks = new_chunks; inputs.chunks[inputs.n_chunks].buf = (char*)malloc(buf_len); inputs.chunks[inputs.n_chunks].len = this_str_len; + assert(inputs.chunks[inputs.n_chunks].buf); memcpy(inputs.chunks[inputs.n_chunks].buf, inputs.buf, buf_len); this_str_len = 0; if (++inputs.n_chunks == max_n_strings) { @@ -129,6 +128,8 @@ run(FILE* const fd) FILE* insert_dat = fopen("dict_insert.txt", "w"); FILE* search_dat = fopen("dict_search.txt", "w"); + assert(insert_dat); + assert(search_dat); fprintf(insert_dat, "# n\tGHashTable\tZixHash\n"); fprintf(search_dat, "# n\tGHashTable\tZixHash\n"); @@ -147,7 +148,7 @@ run(FILE* const fd) // Benchmark insertion // GHashTable - struct timespec insert_start = bench_start(); + BenchmarkTime insert_start = bench_start(); for (size_t i = 0; i < n; ++i) { g_hash_table_insert(hash, inputs.chunks[i].buf, inputs.chunks[i].buf); } @@ -165,7 +166,7 @@ run(FILE* const fd) // Benchmark search // GHashTable - struct timespec search_start = bench_start(); + BenchmarkTime search_start = bench_start(); for (size_t i = 0; i < n; ++i) { const size_t index = (size_t)(lcg64(seed + i) % n); char* volatile match = diff --git a/benchmark/meson.build b/benchmark/meson.build index d3b04ea..54cac3d 100644 --- a/benchmark/meson.build +++ b/benchmark/meson.build @@ -15,15 +15,19 @@ glib_dep = dependency( if glib_dep.found() build_benchmarks = true - benchmark_c_args = platform_c_args + benchmark_c_args = extra_c_args + benchmark_c_suppressions = [] if cc.get_id() in ['clang', 'emscripten'] benchmark_c_suppressions = [ + '-Wno-bad-function-cast', + '-Wno-c11-extensions', # Glib '-Wno-reserved-identifier', ] - - benchmark_c_args += cc.get_supported_arguments(benchmark_c_suppressions) + elif cc.get_id() == 'gcc' + benchmark_c_suppressions = ['-Wno-bad-function-cast'] endif + benchmark_c_args += cc.get_supported_arguments(benchmark_c_suppressions) foreach benchmark : benchmarks benchmark( @@ -33,6 +37,7 @@ if glib_dep.found() files('@0@.c'.format(benchmark)), c_args: c_suppressions + benchmark_c_args, dependencies: [zix_dep, glib_dep], + implicit_include_directories: false, include_directories: include_dirs, ), ) diff --git a/benchmark/tree_bench.c b/benchmark/tree_bench.c index b9e230e..849216b 100644 --- a/benchmark/tree_bench.c +++ b/benchmark/tree_bench.c @@ -1,26 +1,24 @@ // Copyright 2011-2020 David Robillard <d@drobilla.net> // SPDX-License-Identifier: ISC +#include "../test/test_data.h" #include "bench.h" #include "warnings.h" -#include "../test/test_data.h" - -#include "zix/attributes.h" -#include "zix/btree.h" -#include "zix/status.h" -#include "zix/tree.h" +#include <zix/attributes.h> +#include <zix/btree.h> +#include <zix/status.h> +#include <zix/tree.h> ZIX_DISABLE_GLIB_WARNINGS #include <glib.h> ZIX_RESTORE_WARNINGS +#include <assert.h> #include <inttypes.h> -#include <stdarg.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> -#include <time.h> #ifndef MIN # define MIN(a, b) (((a) < (b)) ? (a) : (b)) @@ -55,15 +53,11 @@ g_int_cmp(const void* a, const void* b, void* user_data) return int_cmp(a, b, user_data); } -ZIX_LOG_FUNC(1, 2) static int -test_fail(const char* fmt, ...) +test_fail(const char* const prefix, const uintptr_t value) { - va_list args; - va_start(args, fmt); fprintf(stderr, "error: "); - vfprintf(stderr, fmt, args); - va_end(args); + fprintf(stderr, "%s %" PRIuPTR "\n", prefix, value); return EXIT_FAILURE; } @@ -87,32 +81,32 @@ bench_zix_tree(size_t n_elems, ZixTree* t = zix_tree_new(NULL, false, int_cmp, NULL, NULL, NULL); // Insert n_elems elements - struct timespec insert_start = bench_start(); + BenchmarkTime insert_start = bench_start(); for (size_t i = 0; i < n_elems; i++) { r = unique_rand(i); ZixStatus status = zix_tree_insert(t, (void*)r, &ti); if (status) { - return test_fail("Failed to insert %" PRIuPTR "\n", r); + return test_fail("Failed to insert", r); } } fprintf(insert_dat, "\t%lf", bench_end(&insert_start)); // Search for all elements - struct timespec search_start = bench_start(); + BenchmarkTime search_start = bench_start(); for (size_t i = 0; i < n_elems; i++) { r = unique_rand(i); if (zix_tree_find(t, (void*)r, &ti)) { - return test_fail("Failed to find %" PRIuPTR "\n", r); + return test_fail("Failed to find", r); } if ((uintptr_t)zix_tree_get(ti) != r) { - return test_fail("Failed to get %" PRIuPTR "\n", r); + return test_fail("Failed to get", r); } } fprintf(search_dat, "\t%lf", bench_end(&search_start)); // Iterate over all elements - struct timespec iter_start = bench_start(); + BenchmarkTime iter_start = bench_start(); for (ZixTreeIter* iter = zix_tree_begin(t); !zix_tree_iter_is_end(iter); iter = zix_tree_iter_next(iter)) { volatile void* const value = zix_tree_get(iter); @@ -121,16 +115,16 @@ bench_zix_tree(size_t n_elems, fprintf(iter_dat, "\t%lf", bench_end(&iter_start)); // Delete all elements - struct timespec del_start = bench_start(); + BenchmarkTime del_start = bench_start(); for (size_t i = 0; i < n_elems; i++) { r = unique_rand(i); ZixTreeIter* item = NULL; if (zix_tree_find(t, (void*)r, &item)) { - return test_fail("Failed to find %" PRIuPTR " to delete\n", r); + return test_fail("Failed on delete to find", r); } if (zix_tree_remove(t, item)) { - return test_fail("Failed to remove %" PRIuPTR "\n", r); + return test_fail("Failed to remove", r); } } fprintf(del_dat, "\t%lf", bench_end(&del_start)); @@ -154,33 +148,33 @@ bench_zix_btree(size_t n_elems, ZixBTree* t = zix_btree_new(NULL, int_cmp, NULL); // Insert n_elems elements - struct timespec insert_start = bench_start(); + BenchmarkTime insert_start = bench_start(); for (size_t i = 0; i < n_elems; i++) { r = unique_rand(i); ZixStatus status = zix_btree_insert(t, (void*)r); if (status) { - return test_fail("Failed to insert %" PRIuPTR "\n", r); + return test_fail("Failed to insert", r); } } fprintf(insert_dat, "\t%lf", bench_end(&insert_start)); // Search for all elements - struct timespec search_start = bench_start(); + BenchmarkTime search_start = bench_start(); for (size_t i = 0; i < n_elems; i++) { r = unique_rand(i); if (zix_btree_find(t, (void*)r, &ti)) { - return test_fail("Failed to find %" PRIuPTR "\n", r); + return test_fail("Failed to find", r); } if ((uintptr_t)zix_btree_get(ti) != r) { - return test_fail("Failed to get %" PRIuPTR "\n", r); + return test_fail("Failed to get", r); } } fprintf(search_dat, "\t%lf", bench_end(&search_start)); // Iterate over all elements - struct timespec iter_start = bench_start(); - ZixBTreeIter iter = zix_btree_begin(t); + BenchmarkTime iter_start = bench_start(); + ZixBTreeIter iter = zix_btree_begin(t); for (; !zix_btree_iter_is_end(iter); zix_btree_iter_increment(&iter)) { volatile void* const value = zix_btree_get(iter); (void)value; @@ -188,14 +182,14 @@ bench_zix_btree(size_t n_elems, fprintf(iter_dat, "\t%lf", bench_end(&iter_start)); // Delete all elements - struct timespec del_start = bench_start(); + BenchmarkTime del_start = bench_start(); for (size_t i = 0; i < n_elems; i++) { r = unique_rand(i); void* removed = NULL; ZixBTreeIter next = zix_btree_end(t); if (zix_btree_remove(t, (void*)r, &removed, &next)) { - return test_fail("Failed to remove %" PRIuPTR "\n", r); + return test_fail("Failed to remove", r); } } fprintf(del_dat, "\t%lf", bench_end(&del_start)); @@ -218,31 +212,31 @@ bench_glib(size_t n_elems, GSequence* t = g_sequence_new(NULL); // Insert n_elems elements - struct timespec insert_start = bench_start(); + BenchmarkTime insert_start = bench_start(); for (size_t i = 0; i < n_elems; ++i) { r = unique_rand(i); GSequenceIter* iter = g_sequence_insert_sorted(t, (void*)r, g_int_cmp, NULL); if (!iter || g_sequence_iter_is_end(iter)) { - return test_fail("Failed to insert %" PRIuPTR "\n", r); + return test_fail("Failed to insert", r); } } fprintf(insert_dat, "\t%lf", bench_end(&insert_start)); // Search for all elements - struct timespec search_start = bench_start(); + BenchmarkTime search_start = bench_start(); for (size_t i = 0; i < n_elems; ++i) { r = unique_rand(i); GSequenceIter* iter = g_sequence_lookup(t, (void*)r, g_int_cmp, NULL); if (!iter || g_sequence_iter_is_end(iter)) { - return test_fail("Failed to find %" PRIuPTR "\n", r); + return test_fail("Failed to find", r); } } fprintf(search_dat, "\t%lf", bench_end(&search_start)); // Iterate over all elements - struct timespec iter_start = bench_start(); + BenchmarkTime iter_start = bench_start(); for (GSequenceIter* iter = g_sequence_get_begin_iter(t); !g_sequence_iter_is_end(iter); iter = g_sequence_iter_next(iter)) { @@ -251,12 +245,12 @@ bench_glib(size_t n_elems, fprintf(iter_dat, "\t%lf", bench_end(&iter_start)); // Delete all elements - struct timespec del_start = bench_start(); + BenchmarkTime del_start = bench_start(); for (size_t i = 0; i < n_elems; ++i) { r = unique_rand(i); GSequenceIter* iter = g_sequence_lookup(t, (void*)r, g_int_cmp, NULL); if (!iter || g_sequence_iter_is_end(iter)) { - return test_fail("Failed to remove %" PRIuPTR "\n", r); + return test_fail("Failed to remove", r); } g_sequence_remove(iter); } @@ -286,6 +280,11 @@ main(int argc, char** argv) FILE* search_dat = fopen("tree_search.txt", "w"); FILE* iter_dat = fopen("tree_iterate.txt", "w"); FILE* del_dat = fopen("tree_delete.txt", "w"); + assert(insert_dat); + assert(search_dat); + assert(iter_dat); + assert(del_dat); + fprintf(insert_dat, HEADER); fprintf(search_dat, HEADER); fprintf(iter_dat, HEADER); |