csecp256k1

Haskell FFI bindings to bitcoin-core/secp256k1 (docs.ppad.tech/csecp256k1).
git clone git://git.ppad.tech/csecp256k1.git
Log | Files | Refs | README | LICENSE

bench.h (5077B)


      1 /***********************************************************************
      2  * Copyright (c) 2014 Pieter Wuille                                    *
      3  * Distributed under the MIT software license, see the accompanying    *
      4  * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
      5  ***********************************************************************/
      6 
      7 #ifndef SECP256K1_BENCH_H
      8 #define SECP256K1_BENCH_H
      9 
     10 #include <stdlib.h>
     11 #include <stdint.h>
     12 #include <stdio.h>
     13 #include <string.h>
     14 
     15 #if (defined(_MSC_VER) && _MSC_VER >= 1900)
     16 #  include <time.h>
     17 #else
     18 #  include <sys/time.h>
     19 #endif
     20 
     21 static int64_t gettime_i64(void) {
     22 #if (defined(_MSC_VER) && _MSC_VER >= 1900)
     23     /* C11 way to get wallclock time */
     24     struct timespec tv;
     25     if (!timespec_get(&tv, TIME_UTC)) {
     26         fputs("timespec_get failed!", stderr);
     27         exit(1);
     28     }
     29     return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL;
     30 #else
     31     struct timeval tv;
     32     gettimeofday(&tv, NULL);
     33     return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL;
     34 #endif
     35 }
     36 
     37 #define FP_EXP (6)
     38 #define FP_MULT (1000000LL)
     39 
     40 /* Format fixed point number. */
     41 static void print_number(const int64_t x) {
     42     int64_t x_abs, y;
     43     int c, i, rounding, g; /* g = integer part size, c = fractional part size */
     44     size_t ptr;
     45     char buffer[30];
     46 
     47     if (x == INT64_MIN) {
     48         /* Prevent UB. */
     49         printf("ERR");
     50         return;
     51     }
     52     x_abs = x < 0 ? -x : x;
     53 
     54     /* Determine how many decimals we want to show (more than FP_EXP makes no
     55      * sense). */
     56     y = x_abs;
     57     c = 0;
     58     while (y > 0LL && y < 100LL * FP_MULT && c < FP_EXP) {
     59         y *= 10LL;
     60         c++;
     61     }
     62 
     63     /* Round to 'c' decimals. */
     64     y = x_abs;
     65     rounding = 0;
     66     for (i = c; i < FP_EXP; ++i) {
     67         rounding = (y % 10) >= 5;
     68         y /= 10;
     69     }
     70     y += rounding;
     71 
     72     /* Format and print the number. */
     73     ptr = sizeof(buffer) - 1;
     74     buffer[ptr] = 0;
     75     g = 0;
     76     if (c != 0) { /* non zero fractional part */
     77         for (i = 0; i < c; ++i) {
     78             buffer[--ptr] = '0' + (y % 10);
     79             y /= 10;
     80         }
     81     } else if (c == 0) { /* fractional part is 0 */
     82         buffer[--ptr] = '0'; 
     83     }
     84     buffer[--ptr] = '.';
     85     do {
     86         buffer[--ptr] = '0' + (y % 10);
     87         y /= 10;
     88         g++;
     89     } while (y != 0);
     90     if (x < 0) {
     91         buffer[--ptr] = '-';
     92         g++;
     93     }
     94     printf("%5.*s", g, &buffer[ptr]); /* Prints integer part */
     95     printf("%-*s", FP_EXP, &buffer[ptr + g]); /* Prints fractional part */
     96 }
     97 
     98 static void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void*), void (*teardown)(void*, int), void* data, int count, int iter) {
     99     int i;
    100     int64_t min = INT64_MAX;
    101     int64_t sum = 0;
    102     int64_t max = 0;
    103     for (i = 0; i < count; i++) {
    104         int64_t begin, total;
    105         if (setup != NULL) {
    106             setup(data);
    107         }
    108         begin = gettime_i64();
    109         benchmark(data, iter);
    110         total = gettime_i64() - begin;
    111         if (teardown != NULL) {
    112             teardown(data, iter);
    113         }
    114         if (total < min) {
    115             min = total;
    116         }
    117         if (total > max) {
    118             max = total;
    119         }
    120         sum += total;
    121     }
    122     /* ',' is used as a column delimiter */
    123     printf("%-30s, ", name);
    124     print_number(min * FP_MULT / iter);
    125     printf("   , ");
    126     print_number(((sum * FP_MULT) / count) / iter);
    127     printf("   , ");
    128     print_number(max * FP_MULT / iter);
    129     printf("\n");
    130 }
    131 
    132 static int have_flag(int argc, char** argv, char *flag) {
    133     char** argm = argv + argc;
    134     argv++;
    135     while (argv != argm) {
    136         if (strcmp(*argv, flag) == 0) {
    137             return 1;
    138         }
    139         argv++;
    140     }
    141     return 0;
    142 }
    143 
    144 /* takes an array containing the arguments that the user is allowed to enter on the command-line
    145    returns:
    146       - 1 if the user entered an invalid argument
    147       - 0 if all the user entered arguments are valid */
    148 static int have_invalid_args(int argc, char** argv, char** valid_args, size_t n) {
    149     size_t i;
    150     int found_valid;
    151     char** argm = argv + argc;
    152     argv++;
    153 
    154     while (argv != argm) {
    155         found_valid = 0;
    156         for (i = 0; i < n; i++) {
    157             if (strcmp(*argv, valid_args[i]) == 0) {
    158                 found_valid = 1; /* user entered a valid arg from the list */
    159                 break;
    160             }
    161         }
    162         if (found_valid == 0) {
    163             return 1; /* invalid arg found */
    164         }
    165         argv++;
    166     }
    167     return 0;
    168 }
    169 
    170 static int get_iters(int default_iters) {
    171     char* env = getenv("SECP256K1_BENCH_ITERS");
    172     if (env) {
    173         return strtol(env, NULL, 0);
    174     } else {
    175         return default_iters;
    176     }
    177 }
    178 
    179 static void print_output_table_header_row(void) {
    180     char* bench_str = "Benchmark";     /* left justified */
    181     char* min_str = "    Min(us)    "; /* center alignment */
    182     char* avg_str = "    Avg(us)    ";
    183     char* max_str = "    Max(us)    ";
    184     printf("%-30s,%-15s,%-15s,%-15s\n", bench_str, min_str, avg_str, max_str);
    185     printf("\n");
    186 }
    187 
    188 #endif /* SECP256K1_BENCH_H */