From d5904f4a96ab9e9cf27856191cadb4d2ca91bf81 Mon Sep 17 00:00:00 2001 From: William King Date: Fri, 10 Jul 2015 14:37:05 -0700 Subject: [PATCH] FS-7820 adding a unit test for switch_hash.c with benchmarking example and docs --- tests/unit/Makefile.am | 16 +++-- tests/unit/README | 15 ++++- tests/unit/switch_hash.c | 141 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 7 deletions(-) create mode 100644 tests/unit/switch_hash.c diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am index 7577fa23b9..bf7c56eb1e 100644 --- a/tests/unit/Makefile.am +++ b/tests/unit/Makefile.am @@ -1,9 +1,11 @@ FSLD = $(top_builddir)/libfreeswitch.la $(top_builddir)/libs/apr/libapr-1.la $(top_builddir)/libs/apr-util/libaprutil-1.la +TESTS = +check_PROGRAMS = + if HAVE_TAP - -TESTS = switch_event +TESTS += switch_event check_PROGRAMS = switch_event switch_event_SOURCES = switch_event.c @@ -11,11 +13,13 @@ switch_event_CFLAGS = $(SWITCH_AM_CFLAGS) switch_event_LDADD = $(FSLD) switch_event_LDFLAGS = $(SWITCH_AM_LDFLAGS) -ltap -event_create_SOURCES = event_create.c -event_create_CFLAGS = $(SWITCH_AM_CFLAGS) -event_create_LDADD = $(FSLD) -event_create_LDFLAGS = $(SWITCH_AM_LDFLAGS) -ltap +TESTS += switch_hash +check_PROGRAMS += switch_hash +switch_hash_SOURCES = switch_hash.c +switch_hash_CFLAGS = $(SWITCH_AM_CFLAGS) +switch_hash_LDADD = $(FSLD) +switch_hash_LDFLAGS = $(SWITCH_AM_LDFLAGS) -ltap else check: diff --git a/tests/unit/README b/tests/unit/README index 79d3b9f07b..681d460488 100644 --- a/tests/unit/README +++ b/tests/unit/README @@ -15,4 +15,17 @@ test in a human and machine(regex) parsable format Use libtap from https://github.com/zorgnax/libtap cd /usr/local/src/ git clone https://github.com/zorgnax/libtap.git -make PREFIX=/usr install \ No newline at end of file +make PREFIX=/usr install + + + +To run a benchmark version of a unit test, update the loops count, and +make sure to uncomment the 'BENCHMARK' define line. Then you can run +the benchmark with: + +perf record ./.libs/switch_hash + +Once that is completed you can view the results with: + +perf report + diff --git a/tests/unit/switch_hash.c b/tests/unit/switch_hash.c new file mode 100644 index 0000000000..c3997301d5 --- /dev/null +++ b/tests/unit/switch_hash.c @@ -0,0 +1,141 @@ +#include +#include +#include + +// #define BENCHMARK 1 + +int main () { + + switch_event_t *event = NULL; + switch_bool_t verbose = SWITCH_TRUE; + const char *err = NULL; + switch_time_t start_ts, end_ts; + unsigned long long micro_total = 0; + double micro_per = 0; + double rate_per_sec = 0; + +#ifdef BENCHMARK + switch_time_t small_start_ts, small_end_ts; +#endif + + int rc = 0, loops = 10; + switch_status_t status = SWITCH_STATUS_SUCCESS; + char **index = NULL; + switch_hash_t *hash = NULL; + +#ifndef BENCHMARK + plan(2 + ( 5 * loops)); +#else + plan(2); +#endif + + status = switch_core_init(SCF_MINIMAL, verbose, &err); + + if ( !ok( status == SWITCH_STATUS_SUCCESS, "Initialize FreeSWITCH core\n")) { + bail_out(0, "Bail due to failure to initialize FreeSWITCH[%s]", err); + } + + status = switch_core_hash_init(&hash); + + if ( !ok(status == SWITCH_STATUS_SUCCESS, "Create a new hash")) { + bail_out(0, "Bail due to failure to create hash"); + } + + index = calloc(loops, sizeof(char *)); + for ( int x = 0; x < loops; x++) { + index[x] = switch_mprintf("%d", x); + } + + /* START LOOPS */ + start_ts = switch_time_now(); + + /* Insertion */ +#ifndef BENCHMARK + for ( int x = 0; x < loops; x++) { + status = switch_core_hash_insert(hash, index[x], (void *) index[x]); + ok(status == SWITCH_STATUS_SUCCESS, "Insert into the hash"); + } +#else + small_start_ts = switch_time_now(); + for ( int x = 0; x < loops; x++) { + switch_core_hash_insert(hash, index[x], (void *) index[x]); + } + small_end_ts = switch_time_now(); + + micro_total = small_end_ts - small_start_ts; + micro_per = micro_total / (double) loops; + rate_per_sec = 1000000 / micro_per; + note("switch_hash insert: Total %ldus / %ld loops, %.2f us per loop, %.0f loops per second\n", + micro_total, loops, micro_per, rate_per_sec); +#endif + + + /* Lookup */ +#ifndef BENCHMARK + for ( int x = 0; x < loops; x++) { + char *data = NULL; + data = switch_core_hash_find(hash, index[x]); + ok(data != NULL, "Successful lookup"); + is( index[x], data, "Returned correct data"); + } +#else + small_start_ts = switch_time_now(); + for ( int x = 0; x < loops; x++) { + if ( ! switch_core_hash_find(hash, index[x])) { + fail("Failed to properly locate one of the values"); + } + } + small_end_ts = switch_time_now(); + + micro_total = small_end_ts - small_start_ts; + micro_per = micro_total / (double) loops; + rate_per_sec = 1000000 / micro_per; + note("switch_hash find: Total %ldus / %ld loops, %.2f us per loop, %.0f loops per second\n", + micro_total, loops, micro_per, rate_per_sec); +#endif + + + /* Delete */ +#ifndef BENCHMARK + for ( int x = 0; x < loops; x++) { + char *data = NULL; + data = switch_core_hash_delete(hash, index[x]); + ok(data != NULL, "Create a new hash"); + is( index[x], data, "Returned correct data"); + } +#else + small_start_ts = switch_time_now(); + for ( int x = 0; x < loops; x++) { + if ( !switch_core_hash_delete(hash, index[x])) { + fail("Failed to delete and return the value"); + } + } + small_end_ts = switch_time_now(); + + micro_total = small_end_ts - small_start_ts; + micro_per = micro_total / (double) loops; + rate_per_sec = 1000000 / micro_per; + note("switch_hash delete: Total %ldus / %d loops, %.2f us per loop, %.0f loops per second\n", + micro_total, loops, micro_per, rate_per_sec); +#endif + + + end_ts = switch_time_now(); + /* END LOOPS */ + + switch_core_hash_destroy(&hash); + for ( int x = 0; x < loops; x++) { + free(index[x]); + } + free(index); + + micro_total = end_ts - start_ts; + micro_per = micro_total / (double) loops; + rate_per_sec = 1000000 / micro_per; + note("switch_hash Total %ldus / %d loops, %.2f us per loop, %.0f loops per second\n", + micro_total, loops, micro_per, rate_per_sec); + + switch_core_destroy(); + + done_testing(); +}