Loading .gitignore +2 −0 Changes for .gitignore: 2 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -144,6 +144,8 @@ # /src/test /src/test/Makefile /src/test/Makefile.in /src/test/bench /src/test/bench.exe /src/test/test /src/test/test-child /src/test/test.exe Loading changes/bench 0 → 100644 +6 −0 Changes for changes/bench: 6 added lines, 0 removed lines. Original line number Diff line number Diff line o Testing - The long-disabled benchmark tests are now split into their own ./src/test/bench binary. - The benchmarks can now use more accurate timers than gettimeofday when such are available. configure.in +2 −3 Changes for configure.in: 2 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -276,6 +276,7 @@ AC_SEARCH_LIBS(socket, [socket]) AC_SEARCH_LIBS(gethostbyname, [nsl]) AC_SEARCH_LIBS(dlopen, [dl]) AC_SEARCH_LIBS(inet_aton, [resolv]) AC_SEARCH_LIBS([clock_gettime], [rt], [have_rt=yes]) if test "$enable_threads" = "yes"; then AC_SEARCH_LIBS(pthread_create, [pthread]) Loading @@ -288,6 +289,7 @@ dnl exports strlcpy without defining it in a header. AC_CHECK_FUNCS( accept4 \ clock_gettime \ flock \ ftime \ getaddrinfo \ Loading Loading @@ -363,9 +365,6 @@ dnl On Gnu/Linux or any place we require it, we'll add librt to the Libevent dnl linking for static builds. STATIC_LIBEVENT_FLAGS="" if test "$enable_static_libevent" = "yes"; then dnl Determine if we have clock_gettime in librt AC_SEARCH_LIBS([clock_gettime], [rt], [have_rt=yes]) if test "$have_rt" = yes; then STATIC_LIBEVENT_FLAGS=" -lrt " fi Loading src/test/Makefile.am +11 −1 Changes for src/test/Makefile.am: 11 added lines, 1 removed line. Original line number Diff line number Diff line TESTS = test noinst_PROGRAMS = test test-child noinst_PROGRAMS = test test-child bench AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ -DLOCALSTATEDIR="\"$(localstatedir)\"" \ Loading @@ -23,6 +23,9 @@ test_SOURCES = \ test_util.c \ tinytest.c bench_SOURCES = \ bench.c test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ Loading @@ -30,6 +33,13 @@ test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ bench_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ ../common/libor-event.a \ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ noinst_HEADERS = \ tinytest.h \ tinytest_macros.h \ Loading src/test/bench.c 0 → 100644 +254 −0 Changes for src/test/bench.c: 254 added lines, 0 removed lines. Original line number Diff line number Diff line /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. * Copyright (c) 2007-2011, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /* Ordinarily defined in tor_main.c; this bit is just here to provide one * since we're not linking to tor_main.c */ const char tor_git_revision[] = ""; /** * \file bench.c * \brief Benchmarks for lower level Tor modules. **/ #include "orconfig.h" #include "or.h" #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) static uint64_t nanostart; static inline uint64_t timespec_to_nsec(const struct timespec *ts) { return ((uint64_t)ts->tv_sec)*1000000000 + ts->tv_nsec; } static void reset_perftime(void) { struct timespec ts; int r; r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); tor_assert(r == 0); nanostart = timespec_to_nsec(&ts); } static uint64_t perftime(void) { struct timespec ts; int r; r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); tor_assert(r == 0); return timespec_to_nsec(&ts) - nanostart; } #else static struct timeval tv_start = { 0, 0 }; static void reset_perftime(void) { tor_gettimeofday(&tv_start); } static uint64_t perftime(void) { struct timeval now, out; tor_gettimeofday(&now); timersub(&now, &tv_start, &out); return ((uint64_t)out.tv_sec)*1000000000 + out.tv_usec*1000; } #endif /** Run AES performance benchmarks. */ static void bench_aes(void) { int len, i; char *b1, *b2; crypto_cipher_env_t *c; uint64_t start, end; const int bytes_per_iter = (1<<24); reset_perftime(); c = crypto_new_cipher_env(); crypto_cipher_generate_key(c); crypto_cipher_encrypt_init_cipher(c); for (len = 1; len <= 8192; len *= 2) { int iters = bytes_per_iter / len; b1 = tor_malloc_zero(len); b2 = tor_malloc_zero(len); start = perftime(); for (i = 0; i < iters; ++i) { crypto_cipher_encrypt(c, b1, b2, len); } end = perftime(); tor_free(b1); tor_free(b2); printf("%d bytes: %.2f nsec per byte\n", len, ((double)(end-start))/(iters*len)); } crypto_free_cipher_env(c); } static void bench_cell_aes(void) { uint64_t start, end; const int len = 509; const int iters = (1<<16); const int max_misalign = 15; char *b = tor_malloc(len+max_misalign); crypto_cipher_env_t *c; int i, misalign; c = crypto_new_cipher_env(); crypto_cipher_generate_key(c); crypto_cipher_encrypt_init_cipher(c); reset_perftime(); for (misalign = 0; misalign <= max_misalign; ++misalign) { start = perftime(); for (i = 0; i < iters; ++i) { crypto_cipher_crypt_inplace(c, b+misalign, len); } end = perftime(); printf("%d bytes, misaligned by %d: %.2f nsec per byte\n", len, misalign, ((double)(end-start))/(iters*len)); } crypto_free_cipher_env(c); tor_free(b); } /** Run digestmap_t performance benchmarks. */ static void bench_dmap(void) { smartlist_t *sl = smartlist_create(); smartlist_t *sl2 = smartlist_create(); struct timeval start, end, pt2, pt3, pt4; const int iters = 10000; const int elts = 4000; const int fpostests = 1000000; char d[20]; int i,n=0, fp = 0; digestmap_t *dm = digestmap_new(); digestset_t *ds = digestset_new(elts); for (i = 0; i < elts; ++i) { crypto_rand(d, 20); smartlist_add(sl, tor_memdup(d, 20)); } for (i = 0; i < elts; ++i) { crypto_rand(d, 20); smartlist_add(sl2, tor_memdup(d, 20)); } printf("nbits=%d\n", ds->mask+1); tor_gettimeofday(&start); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, digestmap_set(dm, cp, (void*)1)); } tor_gettimeofday(&pt2); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, digestmap_get(dm, cp)); SMARTLIST_FOREACH(sl2, const char *, cp, digestmap_get(dm, cp)); } tor_gettimeofday(&pt3); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, digestset_add(ds, cp)); } tor_gettimeofday(&pt4); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp)); SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp)); } tor_gettimeofday(&end); for (i = 0; i < fpostests; ++i) { crypto_rand(d, 20); if (digestset_isin(ds, d)) ++fp; } printf("%ld\n",(unsigned long)tv_udiff(&start, &pt2)); printf("%ld\n",(unsigned long)tv_udiff(&pt2, &pt3)); printf("%ld\n",(unsigned long)tv_udiff(&pt3, &pt4)); printf("%ld\n",(unsigned long)tv_udiff(&pt4, &end)); printf("-- %d\n", n); printf("++ %f\n", fp/(double)fpostests); digestmap_free(dm, NULL); digestset_free(ds); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); smartlist_free(sl); smartlist_free(sl2); } typedef void (*bench_fn)(void); typedef struct benchmark_t { const char *name; bench_fn fn; int enabled; } benchmark_t; #define ENT(s) { #s , bench_##s, 0 } static struct benchmark_t benchmarks[] = { ENT(dmap), ENT(aes), ENT(cell_aes), {NULL,NULL,0} }; static benchmark_t * find_benchmark(const char *name) { benchmark_t *b; for (b = benchmarks; b->name; ++b) { if (!strcmp(name, b->name)) { return b; } } return NULL; } /** Main entry point for benchmark code: parse the command line, and run * some benchmarks. */ int main(int argc, const char **argv) { int i; int list=0, n_enabled=0; benchmark_t *b; tor_threads_init(); for (i = 1; i < argc; ++i) { if (!strcmp(argv[i], "--list")) { list = 1; } else { benchmark_t *b = find_benchmark(argv[i]); ++n_enabled; if (b) { b->enabled = 1; } else { printf("No such benchmark as %s\n", argv[i]); } } } reset_perftime(); for (b = benchmarks; b->name; ++b) { if (b->enabled || n_enabled == 0) { printf("===== %s =====\n", b->name); if (!list) b->fn(); } } return 0; } Loading
.gitignore +2 −0 Changes for .gitignore: 2 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -144,6 +144,8 @@ # /src/test /src/test/Makefile /src/test/Makefile.in /src/test/bench /src/test/bench.exe /src/test/test /src/test/test-child /src/test/test.exe Loading
changes/bench 0 → 100644 +6 −0 Changes for changes/bench: 6 added lines, 0 removed lines. Original line number Diff line number Diff line o Testing - The long-disabled benchmark tests are now split into their own ./src/test/bench binary. - The benchmarks can now use more accurate timers than gettimeofday when such are available.
configure.in +2 −3 Changes for configure.in: 2 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -276,6 +276,7 @@ AC_SEARCH_LIBS(socket, [socket]) AC_SEARCH_LIBS(gethostbyname, [nsl]) AC_SEARCH_LIBS(dlopen, [dl]) AC_SEARCH_LIBS(inet_aton, [resolv]) AC_SEARCH_LIBS([clock_gettime], [rt], [have_rt=yes]) if test "$enable_threads" = "yes"; then AC_SEARCH_LIBS(pthread_create, [pthread]) Loading @@ -288,6 +289,7 @@ dnl exports strlcpy without defining it in a header. AC_CHECK_FUNCS( accept4 \ clock_gettime \ flock \ ftime \ getaddrinfo \ Loading Loading @@ -363,9 +365,6 @@ dnl On Gnu/Linux or any place we require it, we'll add librt to the Libevent dnl linking for static builds. STATIC_LIBEVENT_FLAGS="" if test "$enable_static_libevent" = "yes"; then dnl Determine if we have clock_gettime in librt AC_SEARCH_LIBS([clock_gettime], [rt], [have_rt=yes]) if test "$have_rt" = yes; then STATIC_LIBEVENT_FLAGS=" -lrt " fi Loading
src/test/Makefile.am +11 −1 Changes for src/test/Makefile.am: 11 added lines, 1 removed line. Original line number Diff line number Diff line TESTS = test noinst_PROGRAMS = test test-child noinst_PROGRAMS = test test-child bench AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ -DLOCALSTATEDIR="\"$(localstatedir)\"" \ Loading @@ -23,6 +23,9 @@ test_SOURCES = \ test_util.c \ tinytest.c bench_SOURCES = \ bench.c test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ Loading @@ -30,6 +33,13 @@ test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ bench_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ ../common/libor-event.a \ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ noinst_HEADERS = \ tinytest.h \ tinytest_macros.h \ Loading
src/test/bench.c 0 → 100644 +254 −0 Changes for src/test/bench.c: 254 added lines, 0 removed lines. Original line number Diff line number Diff line /* Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. * Copyright (c) 2007-2011, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /* Ordinarily defined in tor_main.c; this bit is just here to provide one * since we're not linking to tor_main.c */ const char tor_git_revision[] = ""; /** * \file bench.c * \brief Benchmarks for lower level Tor modules. **/ #include "orconfig.h" #include "or.h" #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) static uint64_t nanostart; static inline uint64_t timespec_to_nsec(const struct timespec *ts) { return ((uint64_t)ts->tv_sec)*1000000000 + ts->tv_nsec; } static void reset_perftime(void) { struct timespec ts; int r; r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); tor_assert(r == 0); nanostart = timespec_to_nsec(&ts); } static uint64_t perftime(void) { struct timespec ts; int r; r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); tor_assert(r == 0); return timespec_to_nsec(&ts) - nanostart; } #else static struct timeval tv_start = { 0, 0 }; static void reset_perftime(void) { tor_gettimeofday(&tv_start); } static uint64_t perftime(void) { struct timeval now, out; tor_gettimeofday(&now); timersub(&now, &tv_start, &out); return ((uint64_t)out.tv_sec)*1000000000 + out.tv_usec*1000; } #endif /** Run AES performance benchmarks. */ static void bench_aes(void) { int len, i; char *b1, *b2; crypto_cipher_env_t *c; uint64_t start, end; const int bytes_per_iter = (1<<24); reset_perftime(); c = crypto_new_cipher_env(); crypto_cipher_generate_key(c); crypto_cipher_encrypt_init_cipher(c); for (len = 1; len <= 8192; len *= 2) { int iters = bytes_per_iter / len; b1 = tor_malloc_zero(len); b2 = tor_malloc_zero(len); start = perftime(); for (i = 0; i < iters; ++i) { crypto_cipher_encrypt(c, b1, b2, len); } end = perftime(); tor_free(b1); tor_free(b2); printf("%d bytes: %.2f nsec per byte\n", len, ((double)(end-start))/(iters*len)); } crypto_free_cipher_env(c); } static void bench_cell_aes(void) { uint64_t start, end; const int len = 509; const int iters = (1<<16); const int max_misalign = 15; char *b = tor_malloc(len+max_misalign); crypto_cipher_env_t *c; int i, misalign; c = crypto_new_cipher_env(); crypto_cipher_generate_key(c); crypto_cipher_encrypt_init_cipher(c); reset_perftime(); for (misalign = 0; misalign <= max_misalign; ++misalign) { start = perftime(); for (i = 0; i < iters; ++i) { crypto_cipher_crypt_inplace(c, b+misalign, len); } end = perftime(); printf("%d bytes, misaligned by %d: %.2f nsec per byte\n", len, misalign, ((double)(end-start))/(iters*len)); } crypto_free_cipher_env(c); tor_free(b); } /** Run digestmap_t performance benchmarks. */ static void bench_dmap(void) { smartlist_t *sl = smartlist_create(); smartlist_t *sl2 = smartlist_create(); struct timeval start, end, pt2, pt3, pt4; const int iters = 10000; const int elts = 4000; const int fpostests = 1000000; char d[20]; int i,n=0, fp = 0; digestmap_t *dm = digestmap_new(); digestset_t *ds = digestset_new(elts); for (i = 0; i < elts; ++i) { crypto_rand(d, 20); smartlist_add(sl, tor_memdup(d, 20)); } for (i = 0; i < elts; ++i) { crypto_rand(d, 20); smartlist_add(sl2, tor_memdup(d, 20)); } printf("nbits=%d\n", ds->mask+1); tor_gettimeofday(&start); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, digestmap_set(dm, cp, (void*)1)); } tor_gettimeofday(&pt2); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, digestmap_get(dm, cp)); SMARTLIST_FOREACH(sl2, const char *, cp, digestmap_get(dm, cp)); } tor_gettimeofday(&pt3); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, digestset_add(ds, cp)); } tor_gettimeofday(&pt4); for (i = 0; i < iters; ++i) { SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp)); SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp)); } tor_gettimeofday(&end); for (i = 0; i < fpostests; ++i) { crypto_rand(d, 20); if (digestset_isin(ds, d)) ++fp; } printf("%ld\n",(unsigned long)tv_udiff(&start, &pt2)); printf("%ld\n",(unsigned long)tv_udiff(&pt2, &pt3)); printf("%ld\n",(unsigned long)tv_udiff(&pt3, &pt4)); printf("%ld\n",(unsigned long)tv_udiff(&pt4, &end)); printf("-- %d\n", n); printf("++ %f\n", fp/(double)fpostests); digestmap_free(dm, NULL); digestset_free(ds); SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); smartlist_free(sl); smartlist_free(sl2); } typedef void (*bench_fn)(void); typedef struct benchmark_t { const char *name; bench_fn fn; int enabled; } benchmark_t; #define ENT(s) { #s , bench_##s, 0 } static struct benchmark_t benchmarks[] = { ENT(dmap), ENT(aes), ENT(cell_aes), {NULL,NULL,0} }; static benchmark_t * find_benchmark(const char *name) { benchmark_t *b; for (b = benchmarks; b->name; ++b) { if (!strcmp(name, b->name)) { return b; } } return NULL; } /** Main entry point for benchmark code: parse the command line, and run * some benchmarks. */ int main(int argc, const char **argv) { int i; int list=0, n_enabled=0; benchmark_t *b; tor_threads_init(); for (i = 1; i < argc; ++i) { if (!strcmp(argv[i], "--list")) { list = 1; } else { benchmark_t *b = find_benchmark(argv[i]); ++n_enabled; if (b) { b->enabled = 1; } else { printf("No such benchmark as %s\n", argv[i]); } } } reset_perftime(); for (b = benchmarks; b->name; ++b) { if (b->enabled || n_enabled == 0) { printf("===== %s =====\n", b->name); if (!list) b->fn(); } } return 0; }