Back to index

tor  0.2.3.18-rc
bench.c
Go to the documentation of this file.
00001 /* Copyright (c) 2001-2004, Roger Dingledine.
00002  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
00003  * Copyright (c) 2007-2012, The Tor Project, Inc. */
00004 /* See LICENSE for licensing information */
00005 
00006 /* Ordinarily defined in tor_main.c; this bit is just here to provide one
00007  * since we're not linking to tor_main.c */
00008 const char tor_git_revision[] = "";
00009 
00015 #include "orconfig.h"
00016 
00017 #define RELAY_PRIVATE
00018 
00019 #include "or.h"
00020 #include "relay.h"
00021 
00022 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
00023 static uint64_t nanostart;
00024 static inline uint64_t
00025 timespec_to_nsec(const struct timespec *ts)
00026 {
00027   return ((uint64_t)ts->tv_sec)*1000000000 + ts->tv_nsec;
00028 }
00029 
00030 static void
00031 reset_perftime(void)
00032 {
00033   struct timespec ts;
00034   int r;
00035   r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
00036   tor_assert(r == 0);
00037   nanostart = timespec_to_nsec(&ts);
00038 }
00039 
00040 static uint64_t
00041 perftime(void)
00042 {
00043   struct timespec ts;
00044   int r;
00045   r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
00046   tor_assert(r == 0);
00047   return timespec_to_nsec(&ts) - nanostart;
00048 }
00049 
00050 #else
00051 static struct timeval tv_start = { 0, 0 };
00052 static void
00053 reset_perftime(void)
00054 {
00055   tor_gettimeofday(&tv_start);
00056 }
00057 static uint64_t
00058 perftime(void)
00059 {
00060   struct timeval now, out;
00061   tor_gettimeofday(&now);
00062   timersub(&now, &tv_start, &out);
00063   return ((uint64_t)out.tv_sec)*1000000000 + out.tv_usec*1000;
00064 }
00065 #endif
00066 
00067 #define NANOCOUNT(start,end,iters) \
00068   ( ((double)((end)-(start))) / (iters) )
00069 
00071 static void
00072 bench_aes(void)
00073 {
00074   int len, i;
00075   char *b1, *b2;
00076   crypto_cipher_t *c;
00077   uint64_t start, end;
00078   const int bytes_per_iter = (1<<24);
00079   reset_perftime();
00080   c = crypto_cipher_new(NULL);
00081 
00082   for (len = 1; len <= 8192; len *= 2) {
00083     int iters = bytes_per_iter / len;
00084     b1 = tor_malloc_zero(len);
00085     b2 = tor_malloc_zero(len);
00086     start = perftime();
00087     for (i = 0; i < iters; ++i) {
00088       crypto_cipher_encrypt(c, b1, b2, len);
00089     }
00090     end = perftime();
00091     tor_free(b1);
00092     tor_free(b2);
00093     printf("%d bytes: %.2f nsec per byte\n", len,
00094            NANOCOUNT(start, end, iters*len));
00095   }
00096   crypto_cipher_free(c);
00097 }
00098 
00099 static void
00100 bench_cell_aes(void)
00101 {
00102   uint64_t start, end;
00103   const int len = 509;
00104   const int iters = (1<<16);
00105   const int max_misalign = 15;
00106   char *b = tor_malloc(len+max_misalign);
00107   crypto_cipher_t *c;
00108   int i, misalign;
00109 
00110   c = crypto_cipher_new(NULL);
00111 
00112   reset_perftime();
00113   for (misalign = 0; misalign <= max_misalign; ++misalign) {
00114     start = perftime();
00115     for (i = 0; i < iters; ++i) {
00116       crypto_cipher_crypt_inplace(c, b+misalign, len);
00117     }
00118     end = perftime();
00119     printf("%d bytes, misaligned by %d: %.2f nsec per byte\n", len, misalign,
00120            NANOCOUNT(start, end, iters*len));
00121   }
00122 
00123   crypto_cipher_free(c);
00124   tor_free(b);
00125 }
00126 
00128 static void
00129 bench_dmap(void)
00130 {
00131   smartlist_t *sl = smartlist_new();
00132   smartlist_t *sl2 = smartlist_new();
00133   uint64_t start, end, pt2, pt3, pt4;
00134   int iters = 8192;
00135   const int elts = 4000;
00136   const int fpostests = 100000;
00137   char d[20];
00138   int i,n=0, fp = 0;
00139   digestmap_t *dm = digestmap_new();
00140   digestset_t *ds = digestset_new(elts);
00141 
00142   for (i = 0; i < elts; ++i) {
00143     crypto_rand(d, 20);
00144     smartlist_add(sl, tor_memdup(d, 20));
00145   }
00146   for (i = 0; i < elts; ++i) {
00147     crypto_rand(d, 20);
00148     smartlist_add(sl2, tor_memdup(d, 20));
00149   }
00150   printf("nbits=%d\n", ds->mask+1);
00151 
00152   reset_perftime();
00153 
00154   start = perftime();
00155   for (i = 0; i < iters; ++i) {
00156     SMARTLIST_FOREACH(sl, const char *, cp, digestmap_set(dm, cp, (void*)1));
00157   }
00158   pt2 = perftime();
00159   printf("digestmap_set: %.2f ns per element\n",
00160          NANOCOUNT(start, pt2, iters*elts));
00161 
00162   for (i = 0; i < iters; ++i) {
00163     SMARTLIST_FOREACH(sl, const char *, cp, digestmap_get(dm, cp));
00164     SMARTLIST_FOREACH(sl2, const char *, cp, digestmap_get(dm, cp));
00165   }
00166   pt3 = perftime();
00167   printf("digestmap_get: %.2f ns per element\n",
00168          NANOCOUNT(pt2, pt3, iters*elts*2));
00169 
00170   for (i = 0; i < iters; ++i) {
00171     SMARTLIST_FOREACH(sl, const char *, cp, digestset_add(ds, cp));
00172   }
00173   pt4 = perftime();
00174   printf("digestset_add: %.2f ns per element\n",
00175          NANOCOUNT(pt3, pt4, iters*elts));
00176 
00177   for (i = 0; i < iters; ++i) {
00178     SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp));
00179     SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp));
00180   }
00181   end = perftime();
00182   printf("digestset_isin: %.2f ns per element.\n",
00183          NANOCOUNT(pt4, end, iters*elts*2));
00184   /* We need to use this, or else the whole loop gets optimized out. */
00185   printf("Hits == %d\n", n);
00186 
00187   for (i = 0; i < fpostests; ++i) {
00188     crypto_rand(d, 20);
00189     if (digestset_isin(ds, d)) ++fp;
00190   }
00191   printf("False positive rate on digestset: %.2f%%\n",
00192          (fp/(double)fpostests)*100);
00193 
00194   digestmap_free(dm, NULL);
00195   digestset_free(ds);
00196   SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp));
00197   SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp));
00198   smartlist_free(sl);
00199   smartlist_free(sl2);
00200 }
00201 
00202 static void
00203 bench_cell_ops(void)
00204 {
00205   const int iters = 1<<16;
00206   int i;
00207 
00208   /* benchmarks for cell ops at relay. */
00209   or_circuit_t *or_circ = tor_malloc_zero(sizeof(or_circuit_t));
00210   cell_t *cell = tor_malloc(sizeof(cell_t));
00211   int outbound;
00212   uint64_t start, end;
00213 
00214   crypto_rand((char*)cell->payload, sizeof(cell->payload));
00215 
00216   /* Mock-up or_circuit_t */
00217   or_circ->_base.magic = OR_CIRCUIT_MAGIC;
00218   or_circ->_base.purpose = CIRCUIT_PURPOSE_OR;
00219 
00220   /* Initialize crypto */
00221   or_circ->p_crypto = crypto_cipher_new(NULL);
00222   or_circ->n_crypto = crypto_cipher_new(NULL);
00223   or_circ->p_digest = crypto_digest_new();
00224   or_circ->n_digest = crypto_digest_new();
00225 
00226   reset_perftime();
00227 
00228   for (outbound = 0; outbound <= 1; ++outbound) {
00229     cell_direction_t d = outbound ? CELL_DIRECTION_OUT : CELL_DIRECTION_IN;
00230     start = perftime();
00231     for (i = 0; i < iters; ++i) {
00232       char recognized = 0;
00233       crypt_path_t *layer_hint = NULL;
00234       relay_crypt(TO_CIRCUIT(or_circ), cell, d, &layer_hint, &recognized);
00235     }
00236     end = perftime();
00237     printf("%sbound cells: %.2f ns per cell. (%.2f ns per byte of payload)\n",
00238            outbound?"Out":" In",
00239            NANOCOUNT(start,end,iters),
00240            NANOCOUNT(start,end,iters*CELL_PAYLOAD_SIZE));
00241   }
00242 
00243   crypto_digest_free(or_circ->p_digest);
00244   crypto_digest_free(or_circ->n_digest);
00245   crypto_cipher_free(or_circ->p_crypto);
00246   crypto_cipher_free(or_circ->n_crypto);
00247   tor_free(or_circ);
00248   tor_free(cell);
00249 }
00250 
00251 typedef void (*bench_fn)(void);
00252 
00253 typedef struct benchmark_t {
00254   const char *name;
00255   bench_fn fn;
00256   int enabled;
00257 } benchmark_t;
00258 
00259 #define ENT(s) { #s , bench_##s, 0 }
00260 
00261 static struct benchmark_t benchmarks[] = {
00262   ENT(dmap),
00263   ENT(aes),
00264   ENT(cell_aes),
00265   ENT(cell_ops),
00266   {NULL,NULL,0}
00267 };
00268 
00269 static benchmark_t *
00270 find_benchmark(const char *name)
00271 {
00272   benchmark_t *b;
00273   for (b = benchmarks; b->name; ++b) {
00274     if (!strcmp(name, b->name)) {
00275       return b;
00276     }
00277   }
00278   return NULL;
00279 }
00280 
00283 int
00284 main(int argc, const char **argv)
00285 {
00286   int i;
00287   int list=0, n_enabled=0;
00288   benchmark_t *b;
00289 
00290   tor_threads_init();
00291 
00292   for (i = 1; i < argc; ++i) {
00293     if (!strcmp(argv[i], "--list")) {
00294       list = 1;
00295     } else {
00296       benchmark_t *b = find_benchmark(argv[i]);
00297       ++n_enabled;
00298       if (b) {
00299         b->enabled = 1;
00300       } else {
00301         printf("No such benchmark as %s\n", argv[i]);
00302       }
00303     }
00304   }
00305 
00306   reset_perftime();
00307 
00308   crypto_seed_rng(1);
00309 
00310   for (b = benchmarks; b->name; ++b) {
00311     if (b->enabled || n_enabled == 0) {
00312       printf("===== %s =====\n", b->name);
00313       if (!list)
00314         b->fn();
00315     }
00316   }
00317 
00318   return 0;
00319 }
00320