1 /* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2020, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
8 * \brief Benchmarks for lower level Tor modules.
13 #include "core/or/or.h"
14 #include "core/crypto/onion_tap.h"
15 #include "core/crypto/relay_crypto.h"
17 #include "lib/intmath/weakrng.h"
20 #include <openssl/opensslv.h>
21 #include <openssl/evp.h>
22 #include <openssl/ec.h>
23 #include <openssl/ecdh.h>
24 #include <openssl/obj_mac.h>
25 #endif /* defined(ENABLE_OPENSSL) */
27 #include "core/or/circuitlist.h"
28 #include "app/config/config.h"
29 #include "app/main/subsysmgr.h"
30 #include "lib/crypt_ops/crypto_curve25519.h"
31 #include "lib/crypt_ops/crypto_dh.h"
32 #include "core/crypto/onion_ntor.h"
33 #include "lib/crypt_ops/crypto_ed25519.h"
34 #include "lib/crypt_ops/crypto_rand.h"
35 #include "feature/dircommon/consdiff.h"
36 #include "lib/compress/compress.h"
38 #include "core/or/cell_st.h"
39 #include "core/or/or_circuit_st.h"
41 #include "lib/crypt_ops/digestset.h"
42 #include "lib/crypt_ops/crypto_init.h"
44 #include "feature/dirparse/microdesc_parse.h"
45 #include "feature/nodelist/microdesc.h"
47 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
48 static uint64_t nanostart
;
49 static inline uint64_t
50 timespec_to_nsec(const struct timespec
*ts
)
52 return ((uint64_t)ts
->tv_sec
)*1000000000 + ts
->tv_nsec
;
60 r
= clock_gettime(CLOCK_PROCESS_CPUTIME_ID
, &ts
);
62 nanostart
= timespec_to_nsec(&ts
);
70 r
= clock_gettime(CLOCK_PROCESS_CPUTIME_ID
, &ts
);
72 return timespec_to_nsec(&ts
) - nanostart
;
75 #else /* !(defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)) */
76 static struct timeval tv_start
= { 0, 0 };
80 tor_gettimeofday(&tv_start
);
85 struct timeval now
, out
;
86 tor_gettimeofday(&now
);
87 timersub(&now
, &tv_start
, &out
);
88 return ((uint64_t)out
.tv_sec
)*1000000000 + out
.tv_usec
*1000;
90 #endif /* defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) */
92 #define NANOCOUNT(start,end,iters) \
93 ( ((double)((end)-(start))) / (iters) )
95 #define MICROCOUNT(start,end,iters) \
96 ( NANOCOUNT((start), (end), (iters)) / 1000.0 )
98 /** Run AES performance benchmarks. */
106 const int bytes_per_iter
= (1<<24);
108 char key
[CIPHER_KEY_LEN
];
109 crypto_rand(key
, sizeof(key
));
110 c
= crypto_cipher_new(key
);
112 for (len
= 1; len
<= 8192; len
*= 2) {
113 int iters
= bytes_per_iter
/ len
;
114 b1
= tor_malloc_zero(len
);
115 b2
= tor_malloc_zero(len
);
117 for (i
= 0; i
< iters
; ++i
) {
118 crypto_cipher_encrypt(c
, b1
, b2
, len
);
123 printf("%d bytes: %.2f nsec per byte\n", len
,
124 NANOCOUNT(start
, end
, iters
*len
));
126 crypto_cipher_free(c
);
130 bench_onion_TAP(void)
132 const int iters
= 1<<9;
134 crypto_pk_t
*key
, *key2
;
136 char os
[TAP_ONIONSKIN_CHALLENGE_LEN
];
137 char or[TAP_ONIONSKIN_REPLY_LEN
];
138 crypto_dh_t
*dh_out
= NULL
;
140 key
= crypto_pk_new();
141 key2
= crypto_pk_new();
142 if (crypto_pk_generate_key_with_bits(key
, 1024) < 0)
144 if (crypto_pk_generate_key_with_bits(key2
, 1024) < 0)
149 for (i
= 0; i
< iters
; ++i
) {
150 onion_skin_TAP_create(key
, &dh_out
, os
);
151 crypto_dh_free(dh_out
);
154 printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start
, end
, iters
)/1e3
);
156 onion_skin_TAP_create(key
, &dh_out
, os
);
158 for (i
= 0; i
< iters
; ++i
) {
159 char key_out
[CPATH_KEY_MATERIAL_LEN
];
160 onion_skin_TAP_server_handshake(os
, key
, NULL
, or,
161 key_out
, sizeof(key_out
));
164 printf("Server-side, key guessed right: %f usec\n",
165 NANOCOUNT(start
, end
, iters
)/1e3
);
168 for (i
= 0; i
< iters
; ++i
) {
169 char key_out
[CPATH_KEY_MATERIAL_LEN
];
170 onion_skin_TAP_server_handshake(os
, key2
, key
, or,
171 key_out
, sizeof(key_out
));
174 printf("Server-side, key guessed wrong: %f usec.\n",
175 NANOCOUNT(start
, end
, iters
)/1e3
);
178 for (i
= 0; i
< iters
; ++i
) {
180 char key_out
[CPATH_KEY_MATERIAL_LEN
];
182 dh
= crypto_dh_dup(dh_out
);
183 s
= onion_skin_TAP_client_handshake(dh
, or, key_out
, sizeof(key_out
),
189 printf("Client-side, part 2: %f usec.\n",
190 NANOCOUNT(start
, end
, iters
)/1e3
);
193 crypto_dh_free(dh_out
);
195 crypto_pk_free(key2
);
199 bench_onion_ntor_impl(void)
201 const int iters
= 1<<10;
203 curve25519_keypair_t keypair1
, keypair2
;
205 uint8_t os
[NTOR_ONIONSKIN_LEN
];
206 uint8_t or[NTOR_REPLY_LEN
];
207 ntor_handshake_state_t
*state
= NULL
;
208 uint8_t nodeid
[DIGEST_LEN
];
209 di_digest256_map_t
*keymap
= NULL
;
211 curve25519_secret_key_generate(&keypair1
.seckey
, 0);
212 curve25519_public_key_generate(&keypair1
.pubkey
, &keypair1
.seckey
);
213 curve25519_secret_key_generate(&keypair2
.seckey
, 0);
214 curve25519_public_key_generate(&keypair2
.pubkey
, &keypair2
.seckey
);
215 dimap_add_entry(&keymap
, keypair1
.pubkey
.public_key
, &keypair1
);
216 dimap_add_entry(&keymap
, keypair2
.pubkey
.public_key
, &keypair2
);
217 crypto_rand((char *)nodeid
, sizeof(nodeid
));
221 for (i
= 0; i
< iters
; ++i
) {
222 onion_skin_ntor_create(nodeid
, &keypair1
.pubkey
, &state
, os
);
223 ntor_handshake_state_free(state
);
227 printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start
, end
, iters
)/1e3
);
230 onion_skin_ntor_create(nodeid
, &keypair1
.pubkey
, &state
, os
);
232 for (i
= 0; i
< iters
; ++i
) {
233 uint8_t key_out
[CPATH_KEY_MATERIAL_LEN
];
234 onion_skin_ntor_server_handshake(os
, keymap
, NULL
, nodeid
, or,
235 key_out
, sizeof(key_out
));
238 printf("Server-side: %f usec\n",
239 NANOCOUNT(start
, end
, iters
)/1e3
);
242 for (i
= 0; i
< iters
; ++i
) {
243 uint8_t key_out
[CPATH_KEY_MATERIAL_LEN
];
245 s
= onion_skin_ntor_client_handshake(state
, or, key_out
, sizeof(key_out
),
250 printf("Client-side, part 2: %f usec.\n",
251 NANOCOUNT(start
, end
, iters
)/1e3
);
253 ntor_handshake_state_free(state
);
254 dimap_free(keymap
, NULL
);
258 bench_onion_ntor(void)
262 for (ed
= 0; ed
<= 1; ++ed
) {
263 printf("Ed25519-based basepoint multiply = %s.\n",
264 (ed
== 0) ? "disabled" : "enabled");
265 curve25519_set_impl_params(ed
);
266 bench_onion_ntor_impl();
271 bench_ed25519_impl(void)
274 const int iters
= 1<<12;
276 const uint8_t msg
[] = "but leaving, could not tell what they had heard";
277 ed25519_signature_t sig
;
278 ed25519_keypair_t kp
;
279 curve25519_keypair_t curve_kp
;
280 ed25519_public_key_t pubkey_tmp
;
282 ed25519_secret_key_generate(&kp
.seckey
, 0);
284 for (i
= 0; i
< iters
; ++i
) {
285 ed25519_public_key_generate(&kp
.pubkey
, &kp
.seckey
);
288 printf("Generate public key: %.2f usec\n",
289 MICROCOUNT(start
, end
, iters
));
292 for (i
= 0; i
< iters
; ++i
) {
293 ed25519_sign(&sig
, msg
, sizeof(msg
), &kp
);
296 printf("Sign a short message: %.2f usec\n",
297 MICROCOUNT(start
, end
, iters
));
300 for (i
= 0; i
< iters
; ++i
) {
301 ed25519_checksig(&sig
, msg
, sizeof(msg
), &kp
.pubkey
);
304 printf("Verify signature: %.2f usec\n",
305 MICROCOUNT(start
, end
, iters
));
307 curve25519_keypair_generate(&curve_kp
, 0);
309 for (i
= 0; i
< iters
; ++i
) {
310 ed25519_public_key_from_curve25519_public_key(&pubkey_tmp
,
311 &curve_kp
.pubkey
, 1);
314 printf("Convert public point from curve25519: %.2f usec\n",
315 MICROCOUNT(start
, end
, iters
));
317 curve25519_keypair_generate(&curve_kp
, 0);
319 for (i
= 0; i
< iters
; ++i
) {
320 ed25519_public_blind(&pubkey_tmp
, &kp
.pubkey
, msg
);
323 printf("Blind a public key: %.2f usec\n",
324 MICROCOUNT(start
, end
, iters
));
332 for (donna
= 0; donna
<= 1; ++donna
) {
333 printf("Ed25519-donna = %s.\n",
334 (donna
== 0) ? "disabled" : "enabled");
335 ed25519_set_impl_params(donna
);
336 bench_ed25519_impl();
341 bench_rand_len(int len
)
343 const int N
= 100000;
345 char *buf
= tor_malloc(len
);
349 for (i
= 0; i
< N
; ++i
) {
350 crypto_rand(buf
, len
);
353 printf("crypto_rand(%d): %f nsec.\n", len
, NANOCOUNT(start
,end
,N
));
355 crypto_fast_rng_t
*fr
= crypto_fast_rng_new();
357 for (i
= 0; i
< N
; ++i
) {
358 crypto_fast_rng_getbytes(fr
,(uint8_t*)buf
,len
);
361 printf("crypto_fast_rng_getbytes(%d): %f nsec.\n", len
,
362 NANOCOUNT(start
,end
,N
));
363 crypto_fast_rng_free(fr
);
367 for (i
= 0; i
< N
; ++i
) {
368 crypto_strongest_rand((uint8_t*)buf
, len
);
371 printf("crypto_strongest_rand(%d): %f nsec.\n", len
,
372 NANOCOUNT(start
,end
,N
));
377 tor_init_weak_random(&weak
, 1337);
381 for (i
= 0; i
< N
; ++i
) {
382 t
+= tor_weak_random(&weak
);
385 printf("weak_rand(4): %f nsec.\n", NANOCOUNT(start
,end
,N
));
404 const int iters
= (1<<16);
405 const int max_misalign
= 15;
406 char *b
= tor_malloc(len
+max_misalign
);
409 char key
[CIPHER_KEY_LEN
];
410 crypto_rand(key
, sizeof(key
));
411 c
= crypto_cipher_new(key
);
414 for (misalign
= 0; misalign
<= max_misalign
; ++misalign
) {
416 for (i
= 0; i
< iters
; ++i
) {
417 crypto_cipher_crypt_inplace(c
, b
+misalign
, len
);
420 printf("%d bytes, misaligned by %d: %.2f nsec per byte\n", len
, misalign
,
421 NANOCOUNT(start
, end
, iters
*len
));
424 crypto_cipher_free(c
);
428 /** Run digestmap_t performance benchmarks. */
432 smartlist_t
*sl
= smartlist_new();
433 smartlist_t
*sl2
= smartlist_new();
434 uint64_t start
, end
, pt2
, pt3
, pt4
;
436 const int elts
= 4000;
437 const int fpostests
= 100000;
440 digestmap_t
*dm
= digestmap_new();
441 digestset_t
*ds
= digestset_new(elts
);
443 for (i
= 0; i
< elts
; ++i
) {
445 smartlist_add(sl
, tor_memdup(d
, 20));
447 for (i
= 0; i
< elts
; ++i
) {
449 smartlist_add(sl2
, tor_memdup(d
, 20));
451 //printf("nbits=%d\n", ds->mask+1);
456 for (i
= 0; i
< iters
; ++i
) {
457 SMARTLIST_FOREACH(sl
, const char *, cp
, digestmap_set(dm
, cp
, (void*)1));
460 printf("digestmap_set: %.2f ns per element\n",
461 NANOCOUNT(start
, pt2
, iters
*elts
));
463 for (i
= 0; i
< iters
; ++i
) {
464 SMARTLIST_FOREACH(sl
, const char *, cp
, digestmap_get(dm
, cp
));
465 SMARTLIST_FOREACH(sl2
, const char *, cp
, digestmap_get(dm
, cp
));
468 printf("digestmap_get: %.2f ns per element\n",
469 NANOCOUNT(pt2
, pt3
, iters
*elts
*2));
471 for (i
= 0; i
< iters
; ++i
) {
472 SMARTLIST_FOREACH(sl
, const char *, cp
, digestset_add(ds
, cp
));
475 printf("digestset_add: %.2f ns per element\n",
476 NANOCOUNT(pt3
, pt4
, iters
*elts
));
478 for (i
= 0; i
< iters
; ++i
) {
479 SMARTLIST_FOREACH(sl
, const char *, cp
,
480 n
+= digestset_probably_contains(ds
, cp
));
481 SMARTLIST_FOREACH(sl2
, const char *, cp
,
482 n
+= digestset_probably_contains(ds
, cp
));
485 printf("digestset_probably_contains: %.2f ns per element.\n",
486 NANOCOUNT(pt4
, end
, iters
*elts
*2));
487 /* We need to use this, or else the whole loop gets optimized out. */
488 printf("Hits == %d\n", n
);
490 for (i
= 0; i
< fpostests
; ++i
) {
492 if (digestset_probably_contains(ds
, d
)) ++fp
;
494 printf("False positive rate on digestset: %.2f%%\n",
495 (fp
/(double)fpostests
)*100);
497 digestmap_free(dm
, NULL
);
499 SMARTLIST_FOREACH(sl
, char *, cp
, tor_free(cp
));
500 SMARTLIST_FOREACH(sl2
, char *, cp
, tor_free(cp
));
509 int lens
[] = { 7, 8, 15, 16, 20, 32, 111, 128, -1 };
512 const int N
= 300000;
513 crypto_rand(buf
, sizeof(buf
));
515 for (i
= 0; lens
[i
] > 0; ++i
) {
518 for (j
= 0; j
< N
; ++j
) {
519 siphash24g(buf
, lens
[i
]);
522 printf("siphash24g(%d): %.2f ns per call\n",
523 lens
[i
], NANOCOUNT(start
,end
,N
));
531 char out
[DIGEST512_LEN
];
532 const int lens
[] = { 1, 16, 32, 64, 128, 512, 1024, 2048, -1 };
533 const int N
= 300000;
535 crypto_rand(buf
, sizeof(buf
));
537 for (int alg
= 0; alg
< N_DIGEST_ALGORITHMS
; alg
++) {
538 for (int i
= 0; lens
[i
] > 0; ++i
) {
542 for (int j
= 0; j
< N
; ++j
) {
545 failures
+= crypto_digest(out
, buf
, lens
[i
]) < 0;
548 case DIGEST_SHA3_256
:
549 failures
+= crypto_digest256(out
, buf
, lens
[i
], alg
) < 0;
552 case DIGEST_SHA3_512
:
553 failures
+= crypto_digest512(out
, buf
, lens
[i
], alg
) < 0;
560 printf("%s(%d): %.2f ns per call\n",
561 crypto_digest_algorithm_get_name(alg
),
562 lens
[i
], NANOCOUNT(start
,end
,N
));
564 printf("ERROR: crypto_digest failed %d times.\n", failures
);
572 const int iters
= 1<<16;
575 /* benchmarks for cell ops at relay. */
576 or_circuit_t
*or_circ
= tor_malloc_zero(sizeof(or_circuit_t
));
577 cell_t
*cell
= tor_malloc(sizeof(cell_t
));
581 crypto_rand((char*)cell
->payload
, sizeof(cell
->payload
));
583 /* Mock-up or_circuit_t */
584 or_circ
->base_
.magic
= OR_CIRCUIT_MAGIC
;
585 or_circ
->base_
.purpose
= CIRCUIT_PURPOSE_OR
;
587 /* Initialize crypto */
588 char key1
[CIPHER_KEY_LEN
], key2
[CIPHER_KEY_LEN
];
589 crypto_rand(key1
, sizeof(key1
));
590 crypto_rand(key2
, sizeof(key2
));
591 or_circ
->crypto
.f_crypto
= crypto_cipher_new(key1
);
592 or_circ
->crypto
.b_crypto
= crypto_cipher_new(key2
);
593 or_circ
->crypto
.f_digest
= crypto_digest_new();
594 or_circ
->crypto
.b_digest
= crypto_digest_new();
598 for (outbound
= 0; outbound
<= 1; ++outbound
) {
599 cell_direction_t d
= outbound
? CELL_DIRECTION_OUT
: CELL_DIRECTION_IN
;
601 for (i
= 0; i
< iters
; ++i
) {
603 crypt_path_t
*layer_hint
= NULL
;
604 relay_decrypt_cell(TO_CIRCUIT(or_circ
), cell
, d
,
605 &layer_hint
, &recognized
);
608 printf("%sbound cells: %.2f ns per cell. (%.2f ns per byte of payload)\n",
609 outbound
?"Out":" In",
610 NANOCOUNT(start
,end
,iters
),
611 NANOCOUNT(start
,end
,iters
*CELL_PAYLOAD_SIZE
));
614 relay_crypto_clear(&or_circ
->crypto
);
622 const int iters
= 1<<10;
628 for (i
= 0; i
< iters
; ++i
) {
629 char dh_pubkey_a
[DH1024_KEY_LEN
], dh_pubkey_b
[DH1024_KEY_LEN
];
630 char secret_a
[DH1024_KEY_LEN
], secret_b
[DH1024_KEY_LEN
];
631 ssize_t slen_a
, slen_b
;
632 crypto_dh_t
*dh_a
= crypto_dh_new(DH_TYPE_TLS
);
633 crypto_dh_t
*dh_b
= crypto_dh_new(DH_TYPE_TLS
);
634 crypto_dh_generate_public(dh_a
);
635 crypto_dh_generate_public(dh_b
);
636 crypto_dh_get_public(dh_a
, dh_pubkey_a
, sizeof(dh_pubkey_a
));
637 crypto_dh_get_public(dh_b
, dh_pubkey_b
, sizeof(dh_pubkey_b
));
638 slen_a
= crypto_dh_compute_secret(LOG_NOTICE
,
639 dh_a
, dh_pubkey_b
, sizeof(dh_pubkey_b
),
640 secret_a
, sizeof(secret_a
));
641 slen_b
= crypto_dh_compute_secret(LOG_NOTICE
,
642 dh_b
, dh_pubkey_a
, sizeof(dh_pubkey_a
),
643 secret_b
, sizeof(secret_b
));
644 tor_assert(slen_a
== slen_b
);
645 tor_assert(fast_memeq(secret_a
, secret_b
, slen_a
));
646 crypto_dh_free(dh_a
);
647 crypto_dh_free(dh_b
);
650 printf("Complete DH handshakes (1024 bit, public and private ops):\n"
651 " %f millisec each.\n", NANOCOUNT(start
, end
, iters
)/1e6
);
654 #ifdef ENABLE_OPENSSL
656 bench_ecdh_impl(int nid
, const char *name
)
658 const int iters
= 1<<10;
664 for (i
= 0; i
< iters
; ++i
) {
665 char secret_a
[DH1024_KEY_LEN
], secret_b
[DH1024_KEY_LEN
];
666 ssize_t slen_a
, slen_b
;
667 EC_KEY
*dh_a
= EC_KEY_new_by_curve_name(nid
);
668 EC_KEY
*dh_b
= EC_KEY_new_by_curve_name(nid
);
669 if (!dh_a
|| !dh_b
) {
670 puts("Skipping. (No implementation?)");
674 EC_KEY_generate_key(dh_a
);
675 EC_KEY_generate_key(dh_b
);
676 slen_a
= ECDH_compute_key(secret_a
, DH1024_KEY_LEN
,
677 EC_KEY_get0_public_key(dh_b
), dh_a
,
679 slen_b
= ECDH_compute_key(secret_b
, DH1024_KEY_LEN
,
680 EC_KEY_get0_public_key(dh_a
), dh_b
,
683 tor_assert(slen_a
== slen_b
);
684 tor_assert(fast_memeq(secret_a
, secret_b
, slen_a
));
689 printf("Complete ECDH %s handshakes (2 public and 2 private ops):\n"
690 " %f millisec each.\n", name
, NANOCOUNT(start
, end
, iters
)/1e6
);
694 bench_ecdh_p256(void)
696 bench_ecdh_impl(NID_X9_62_prime256v1
, "P-256");
700 bench_ecdh_p224(void)
702 bench_ecdh_impl(NID_secp224r1
, "P-224");
704 #endif /* defined(ENABLE_OPENSSL) */
710 const int N
= 100000;
711 // selected arbitrarily
712 const char md_text
[] =
713 "@last-listed 2018-12-14 18:14:14\n"
715 "-----BEGIN RSA PUBLIC KEY-----\n"
716 "MIGJAoGBAMHkZeXNDX/49JqM2BVLmh1Fnb5iMVnatvZZTLJyedqDLkbXZ1WKP5oh\n"
717 "7ec14dj/k3ntpwHD4s2o3Lb6nfagWbug4+F/rNJ7JuFru/PSyOvDyHGNAuegOXph\n"
718 "3gTGjdDpv/yPoiadGebbVe8E7n6hO+XxM2W/4dqheKimF0/s9B7HAgMBAAE=\n"
719 "-----END RSA PUBLIC KEY-----\n"
720 "ntor-onion-key QgF/EjqlNG1wRHLIop/nCekEH+ETGZSgYOhu26eiTF4=\n"
721 "family $00E9A86E7733240E60D8435A7BBD634A23894098 "
722 "$329BD7545DEEEBBDC8C4285F243916F248972102 "
723 "$69E06EBB2573A4F89330BDF8BC869794A3E10E4D "
724 "$DCA2A3FAE50B3729DAA15BC95FB21AF03389818B\n"
725 "p accept 53,80,443,5222-5223,25565\n"
726 "id ed25519 BzffzY99z6Q8KltcFlUTLWjNTBU7yKK+uQhyi1Ivb3A\n";
730 for (int i
= 0; i
< N
; ++i
) {
731 smartlist_t
*s
= microdescs_parse_from_string(md_text
, NULL
, 1,
732 SAVED_IN_CACHE
, NULL
);
733 SMARTLIST_FOREACH(s
, microdesc_t
*, md
, microdesc_free(md
));
738 printf("Microdesc parse: %f nsec\n", NANOCOUNT(start
, end
, N
));
741 typedef void (*bench_fn
)(void);
743 typedef struct benchmark_t
{
749 #define ENT(s) { #s , bench_##s, 0 }
751 static struct benchmark_t benchmarks
[] = {
765 #ifdef ENABLE_OPENSSL
775 find_benchmark(const char *name
)
778 for (b
= benchmarks
; b
->name
; ++b
) {
779 if (!strcmp(name
, b
->name
)) {
786 /** Main entry point for benchmark code: parse the command line, and run
787 * some benchmarks. */
789 main(int argc
, const char **argv
)
792 int list
=0, n_enabled
=0;
794 or_options_t
*options
;
796 subsystems_init_upto(SUBSYS_LEVEL_LIBS
);
797 flush_log_messages_from_startup();
801 if (argc
== 4 && !strcmp(argv
[1], "diff")) {
803 char *f1
= read_file_to_str(argv
[2], RFTS_BIN
, NULL
);
804 char *f2
= read_file_to_str(argv
[3], RFTS_BIN
, NULL
);
809 size_t f1len
= strlen(f1
);
810 size_t f2len
= strlen(f2
);
811 for (i
= 0; i
< N
; ++i
) {
812 char *diff
= consensus_diff_generate(f1
, f1len
, f2
, f2len
);
815 char *diff
= consensus_diff_generate(f1
, f1len
, f2
, f2len
);
823 for (i
= 1; i
< argc
; ++i
) {
824 if (!strcmp(argv
[i
], "--list")) {
827 benchmark_t
*benchmark
= find_benchmark(argv
[i
]);
830 benchmark
->enabled
= 1;
832 printf("No such benchmark as %s\n", argv
[i
]);
839 if (crypto_global_init(0, NULL
, NULL
) < 0) {
840 printf("Couldn't seed RNG; exiting.\n");
844 init_protocol_warning_severity_level();
845 options
= options_new();
846 options
->command
= CMD_RUN_UNITTESTS
;
847 options
->DataDirectory
= tor_strdup("");
848 options
->KeyDirectory
= tor_strdup("");
849 options
->CacheDirectory
= tor_strdup("");
850 options_init(options
);
851 if (set_options(options
, &errmsg
) < 0) {
852 printf("Failed to set initial options: %s\n", errmsg
);
857 for (benchmark_t
*b
= benchmarks
; b
->name
; ++b
) {
858 if (b
->enabled
|| n_enabled
== 0) {
859 printf("===== %s =====\n", b
->name
);