]> git.codecow.com Git - Monocypher.git/commitdiff
Restored the speed benchmark
authorLoup Vaillant <loup@loup-vaillant.fr>
Tue, 19 Sep 2017 22:16:25 +0000 (00:16 +0200)
committerLoup Vaillant <loup@loup-vaillant.fr>
Tue, 19 Sep 2017 22:16:25 +0000 (00:16 +0200)
The benchmark now gives absolute speeds instead of comparisons against
other libraries.  This is more useful that way: the important
information is whether Monocypher is fast *enough*.  This also
increases portability, so end users can actually run the benchmark
themselves.

Besides, we can always add Libsodium and TweetNaCl benchmarks later.

dist/makefile
dist/tests/speed.c

index 0902d19568e339d988d7c306436e97b58f906e2f..dff652588a0eaa9045e17b80d0a21b1d06903e5e 100644 (file)
@@ -21,16 +21,22 @@ CC=gcc -std=gnu99 # speed tests don't work with -std=cxx, they need the POSIX ex
 #TODO maybe just use the environment variable?
 CFLAGS= -pedantic -Wall -Wextra -O3 -march=native -g
 
-.PHONY: all clean install test
+.PHONY: all clean install test speed
 
 all: lib/libmonocypher.a lib/libmonocypher.so
 
+clean:
+       rm -rf lib/
+       rm -f  *.out
+
+# TODO
+# install:
+
 test: test.out
        ./test.out
 
-clean:
-       rm -rf lib/
-       rm -f  test.out
+speed: speed.out
+       ./speed.out
 
 # Monocypher libraries
 lib/libmonocypher.a: lib/monocypher.o
@@ -42,17 +48,16 @@ lib/%.o: src/%.c src/%.h
        @mkdir -p $(@D)
        $(CC) $(CFLAGS) -I src -fPIC -c -o $@ $<
 
-# Test libraries
+# Test & speed libraries
 lib/utils.o: tests/utils.c tests/utils.h
-       @mkdir -p $(@D)
-       $(CC) $(CFLAGS) -I src -fPIC -c -o $@ $<
-lib/test.o: tests/test.c tests/utils.h    \
-                         tests/vectors.h  \
-                         src/monocypher.h \
-                         src/sha512.h
+lib/test.o : tests/test.c  tests/utils.h src/monocypher.h src/sha512.h tests/vectors.h
+lib/speed.o: tests/speed.c tests/utils.h src/monocypher.h src/sha512.h
+lib/utils.o lib/test.o lib/speed.o:
        @mkdir -p $(@D)
        $(CC) $(CFLAGS) -I src -fPIC -c -o $@ $<
 
-# test executable
-test.out: lib/test.o lib/monocypher.o lib/sha512.o lib/utils.o
+# test & speed executables
+test.out : lib/test.o  lib/monocypher.o lib/sha512.o lib/utils.o
+speed.out: lib/speed.o lib/monocypher.o lib/sha512.o lib/utils.o
+test.out speed.out:
        $(CC) $(CFLAGS) -I src -o $@ $^
index 63bb3f81ae7df64119a543c070cd9e6fbb88eb23..3ce663b890a841332290bb4cbca96ff42fe49911 100644 (file)
@@ -9,25 +9,41 @@
 typedef struct timespec timespec;
 
 // TODO: provide a user defined buffer size
-#define SIZE (1024 * 1024)
+#define KILOBYTE 1024
+#define MEGABYTE (1024 * KILOBYTE)
+#define SIZE     MEGABYTE
+#define DIVIDER  (MEGABYTE / SIZE)
 
-// TODO: provide a Mb/s absolute speed
-speed_t speed(timespec ref, timespec t)
+timespec diff(timespec start, timespec end)
 {
-    u64 ref_u = ref.tv_sec * 1000000000 + ref.tv_nsec;
-    u64 t_u   = t  .tv_sec * 1000000000 + t  .tv_nsec;
-    speed_t s;
-    s.ratio = (100 * ref_u) / t_u; // assuming t_u is never zero
-    s.time  = t_u ;
-    s.ref   = ref_u ;
-    return s;
+    timespec duration;
+    duration.tv_sec  = end.tv_sec  - start.tv_sec;
+    duration.tv_nsec = end.tv_nsec - start.tv_nsec;
+    if (duration.tv_nsec < 0) {
+        duration.tv_nsec += 1000000000;
+        duration.tv_sec  -= 1;
+    }
+    return duration;
+}
+
+timespec min(timespec a, timespec b)
+{
+    if (a.tv_sec < b.tv_sec ||
+        (a.tv_sec == b.tv_sec && a.tv_nsec < b.tv_nsec)) {
+        return a;
+    }
+    return b;
+}
+
+u64 speed(timespec duration)
+{
+    static const u64 giga = 1000000000;
+    return giga / (duration.tv_nsec + duration.tv_sec * giga);
 }
 
-static void print(const char *name, speed_t result, const char *lib_name)
+static void print(const char *name, u64 speed, const char *unit)
 {
-    printf("%s: %4d Mb/s vs %4d Mb/s\n", name,
-           1000000 / result.time,
-           1000000 / result.ref);
+    printf("%s: %4" PRIu64 " %s\n", name, speed, unit);
 }
 
 // TODO: adjust this crap
@@ -39,109 +55,121 @@ static void print(const char *name, speed_t result, const char *lib_name)
     timespec duration;                          \
     duration.tv_sec  = 3600 * 24;               \
     duration.tv_nsec = 0;                       \
-    FOR (i, 0, 30) {                            \
+    FOR (i, 0, 50) {                            \
         TIMESTAMP(start);
 
-#define TIMING_END(duration)                    \
+#define TIMING_END                              \
     TIMESTAMP(end);                             \
-    duration = min(diff(start, end), duration); \
-    }
+    duration = diff(start, end);                \
+    } /* end FOR*/                              \
+    return speed(duration)
 
-#define TIMING_RESULT(name, result_size)                          \
-    if (crypto_memcmp(mono, sodium, result_size) != 0) {          \
-        printf(name " benchmark failed (different results)\n");   \
-    }                                                             \
-    return speed(libsodium, monocypher)
 
-
-static speed_t chacha20(void)
+static u64 chacha20(void)
 {
     static u8  in    [SIZE];  p_random(in   , SIZE);
     static u8  key   [  32];  p_random(key  ,   32);
     static u8  nonce [   8];  p_random(nonce,    8);
-    static u8  mono  [SIZE];
+    static u8  out  [SIZE];
 
     TIMING_START {
         crypto_chacha_ctx ctx;
         crypto_chacha20_init(&ctx, key, nonce);
-        crypto_chacha20_encrypt(&ctx, mono, in, SIZE);
+        crypto_chacha20_encrypt(&ctx, out, in, SIZE);
+    }
+    TIMING_END;
+}
+
+static u64 poly1305(void)
+{
+    static u8  in    [SIZE];  p_random(in   , SIZE);
+    static u8  key   [  32];  p_random(key  ,   32);
+    static u8  out  [  16];
+
+    TIMING_START {
+        crypto_poly1305_auth(out, in, SIZE, key);
     }
     TIMING_END;
 }
 
-static speed_t poly1305(void)
+static u64 authenticated(void)
 {
     static u8  in    [SIZE];  p_random(in   , SIZE);
     static u8  key   [  32];  p_random(key  ,   32);
-    static u8  mono  [  16];
+    static u8  nonce [   8];  p_random(nonce,    8);
+    static u8  out   [SIZE];
+    static u8  mac   [  16];
 
     TIMING_START {
-        crypto_poly1305_auth(mono, in, SIZE, key);
+        crypto_lock(mac, out, key, nonce, in, SIZE);
     }
     TIMING_END;
 }
 
-static speed_t blake2b(void)
+static u64 blake2b(void)
 {
-    static u8 in    [SIZE];  p_random(in , SIZE);
-    static u8 key   [  32];  p_random(key,   32);
-    static u8 mono  [  64];
+    static u8 in  [SIZE];  p_random(in , SIZE);
+    static u8 key [  32];  p_random(key,   32);
+    static u8 hash[  64];
 
-    TIMING_START(monocypher) {
-        crypto_blake2b_general(mono, 64, key, 32, in, SIZE);
+    TIMING_START {
+        crypto_blake2b_general(hash, 64, key, 32, in, SIZE);
     }
     TIMING_END;
 }
 
-// TODO: don't just rely on SIZE, add a HARDNESS parameter
-static speed_t argon2i(void)
+static u64 argon2i(void)
 {
-    size_t    nb_blocks = SIZE / 1024;
-    static u8 work_area[SIZE];
-    static u8 password [  16];  p_random(password, 16);
-    static u8 salt     [  16];  p_random(salt    , 16);
-    static u8 mono     [  32];
+    size_t    nb_blocks = 1024;
+    static u8 work_area[MEGABYTE];
+    static u8 password [      16];  p_random(password, 16);
+    static u8 salt     [      16];  p_random(salt    , 16);
+    static u8 hash     [      32];
 
     TIMING_START {
-        crypto_argon2i(mono, 32, work_area, nb_blocks, 3,
+        crypto_argon2i(hash, 32, work_area, nb_blocks, 3,
                        password, 16, salt, 16, 0, 0, 0, 0);
     }
     TIMING_END;
 }
 
-// TODO: change TIMING_END to print scalarmult per second
-static speed_t x25519(void)
+static u64 x25519(void)
 {
-    u8 mono_in  [32] = {9};
-    u8 mono     [32] = {9};
+    u8 in  [32] = {9};
+    u8 out [32] = {9};
 
     TIMING_START {
-        if (crypto_x25519(mono, mono, mono_in)) {
+        if (crypto_x25519(out, out, in)) {
             printf("Monocypher x25519 rejected public key\n");
         }
     }
     TIMING_END;
 }
 
-// TODO: change TIMING_END to print signature/check per second
-static void ed25519(void)
+static u64 edDSA_sign(void)
 {
-    u8 sk       [32];   p_random(sk, 32);
-    u8 pk       [64];
-    crypto_sign_seed_keypair(pk, sk_sodium, sk);
+    u8 sk         [32];  p_random(sk, 32);
+    u8 pk         [32];  crypto_sign_public_key(pk, sk);
+    u8 message    [64];  p_random(message, 64);
+    u8 signature  [64];
 
-    u8 message   [64];  p_random(message, 64);
-    u8 mono_sig  [64];
-
-    // Signature speed
     TIMING_START {
-        crypto_sign(mono_sig, sk, pk, message, 64);
+        crypto_sign(signature, sk, pk, message, 64);
     }
     TIMING_END;
+}
+
+static u64 edDSA_check(void)
+{
+    u8 sk         [32];  p_random(sk, 32);
+    u8 pk         [32];  crypto_sign_public_key(pk, sk);
+    u8 message    [64];  p_random(message, 64);
+    u8 signature  [64];
 
-    // Verification speed (for correct signatures)
-    TIMING_START(monocypher_chk) {
-        if (crypto_check(mono_sig, pk, message, 64)) {
+    crypto_sign(signature, sk, pk, message, 64);
+
+    TIMING_START {
+        if (crypto_check(signature, pk, message, 64)) {
             printf("Monocypher verification failed\n");
         }
     }
@@ -150,13 +178,14 @@ static void ed25519(void)
 
 int main()
 {
-    chacha20();
-    poly1305();
-    blake2b();
-    argon2i();
-    x25519();
-    ed25519();
-
+    print("Chacha20         ", chacha20()      / DIVIDER, "Mb/s"       );
+    print("Poly1305         ", poly1305()      / DIVIDER, "Mb/s"       );
+    print("Auth'd encryption", authenticated() / DIVIDER, "Mb/s"       );
+    print("Blake2b          ", blake2b()       / DIVIDER, "Mb/s"       );
+    print("Argon2i          ", argon2i()      , "Mb/s (3 passes)"      );
+    print("x25519           ", x25519()       , "exchanges  per second");
+    print("EdDSA(sign)      ", edDSA_sign()   , "signatures per second");
+    print("EdDSA(check)     ", edDSA_check()  , "checks     per second");
     printf("\n");
     return 0;
 }