/* * Copyright (C) 2020 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #ifndef HASHTABLE_PROFILER_H_ #define HASHTABLE_PROFILER_H_ #ifdef HASHTABLE_PROFILER #include #include typedef struct hashtable_profile_t hashtable_profile_t; struct hashtable_profile_t { /** * Some stats to profile lookups in the table */ struct { size_t count; size_t probes; size_t longest; } success, failure; /** * Stats on the memory usage of the table */ struct { size_t count; size_t size; } max; /** * Keep track of where the hash table was created */ backtrace_t *backtrace; }; /** * Print and cleanup profiling data */ static inline void profiler_cleanup(hashtable_profile_t *profile, u_int count, u_int size) { if (profile->success.count || profile->failure.count) { fprintf(stderr, "%zu elements [max. %zu], %zu buckets [%zu], %zu " "successful / %zu failed lookups, %.4f [%zu] / %.4f " "[%zu] avg. probes in table created at:", count, profile->max.count, size, profile->max.size, profile->success.count, profile->failure.count, (double)profile->success.probes/profile->success.count, profile->success.longest, (double)profile->failure.probes/profile->failure.count, profile->failure.longest); profile->backtrace->log(profile->backtrace, stderr, TRUE); } profile->backtrace->destroy(profile->backtrace); } /** * Initialize profiling data */ static inline void profiler_init(hashtable_profile_t *profile, int skip) { profile->backtrace = backtrace_create(skip); } #define lookup_start() \ u_int _lookup_probes = 0; #define lookup_probing() \ _lookup_probes++; #define _lookup_done(profile, result) \ (profile)->result.count++; \ (profile)->result.probes += _lookup_probes; \ (profile)->result.longest = max((profile)->result.longest, _lookup_probes); #define lookup_success(profile) _lookup_done(profile, success); #define lookup_failure(profile) _lookup_done(profile, failure); static inline void profile_size(hashtable_profile_t *profile, u_int size) { profile->max.size = max(profile->max.size, size); } static inline void profile_count(hashtable_profile_t *profile, u_int count) { profile->max.count = max(profile->max.count, count); } #else /* !HASHTABLE_PROFILER */ #define hashtable_profile_t struct {} #define profiler_cleanup(...) {} #define profiler_init(...) {} #define lookup_start(...) {} #define lookup_probing(...) {} #define lookup_success(...) {} #define lookup_failure(...) {} #define profile_size(...) {} #define profile_count(...) {} #endif /* HASHTABLE_PROFILER */ #endif /* HASHTABLE_PROFILER_H_ */