github.com/ethereum/go-ethereum@v1.16.1/crypto/secp256k1/libsecp256k1/src/bench.h (about)

     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(EXIT_FAILURE);
    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 */