[git] GCRYPT - branch, LIBGCRYPT-1-5-BRANCH, updated. libgcrypt-1.5.3-4-g450adc3

by Werner Koch cvs at cvs.gnupg.org
Mon Dec 9 08:50:20 CET 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU crypto library".

The branch, LIBGCRYPT-1-5-BRANCH has been updated
       via  450adc39b461bdf48230fa0f9ef7317e9937a8e5 (commit)
      from  182640abc40b5ce77d4c0aaa0aa8c09d05a92138 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 450adc39b461bdf48230fa0f9ef7317e9937a8e5
Author: Werner Koch <wk at gnupg.org>
Date:   Tue Oct 22 14:26:53 2013 +0200

    tests: Add bench-slope.
    
    * tests/bench-slope.c: New.  This is a stripped down version taken
    from master.
    * tests/Makefile.am (noinst_PROGRAMS): Add bench-slope.

diff --git a/tests/Makefile.am b/tests/Makefile.am
index 689a3db..e2aa12f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -40,7 +40,7 @@ AM_CFLAGS = $(GPG_ERROR_CFLAGS)
 LDADD = ../src/libgcrypt.la $(DL_LIBS) ../compat/libcompat.la $(GPG_ERROR_LIBS)
 
 EXTRA_PROGRAMS = testapi pkbench
-noinst_PROGRAMS = $(TESTS) fipsdrv rsacvt
+noinst_PROGRAMS = $(TESTS) fipsdrv rsacvt bench-slope
 
 EXTRA_DIST = README rsa-16k.key cavs_tests.sh cavs_driver.pl \
 	     pkcs1v2-oaep.h pkcs1v2-pss.h pkcs1v2-v15c.h pkcs1v2-v15s.h
diff --git a/tests/bench-slope.c b/tests/bench-slope.c
new file mode 100644
index 0000000..8897b64
--- /dev/null
+++ b/tests/bench-slope.c
@@ -0,0 +1,1148 @@
+/* bench-slope.c - for libgcrypt
+ * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna at iki.fi>
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <time.h>
+
+#ifdef _GCRYPT_IN_LIBGCRYPT
+# include "../src/gcrypt.h"
+# include "../compat/libcompat.h"
+#else
+# include <gcrypt.h>
+#endif
+
+#ifndef STR
+#define STR(v) #v
+#define STR2(v) STR(v)
+#endif
+
+#define PGM "bench-slope"
+
+static int verbose;
+static int csv_mode;
+static int num_measurement_repetitions;
+
+/* CPU Ghz value provided by user, allows constructing cycles/byte and other
+   results.  */
+static double cpu_ghz = -1;
+
+/* The name of the currently printed section.  */
+static char *current_section_name;
+/* The name of the currently printed algorithm.  */
+static char *current_algo_name;
+/* The name of the currently printed mode.  */
+static char *current_mode_name;
+
+
+/*************************************** Default parameters for measurements. */
+
+/* Start at small buffer size, to get reasonable timer calibration for fast
+ * implementations (AES-NI etc). Sixteen selected to support the largest block
+ * size of current set cipher blocks. */
+#define BUF_START_SIZE			16
+
+/* From ~0 to ~4kbytes give comparable results with results from academia
+ * (SUPERCOP). */
+#define BUF_END_SIZE			(BUF_START_SIZE + 4096)
+
+/* With 128 byte steps, we get (4096)/64 = 64 data points. */
+#define BUF_STEP_SIZE			64
+
+/* Number of repeated measurements at each data point. The median of these
+ * measurements is selected as data point further analysis. */
+#define NUM_MEASUREMENT_REPETITIONS	64
+
+/**************************************************** High-resolution timers. */
+
+/* This benchmarking module needs needs high resolution timer.  */
+#undef NO_GET_NSEC_TIME
+#if defined(_WIN32)
+struct nsec_time
+{
+  LARGE_INTEGER perf_count;
+};
+
+static void
+get_nsec_time (struct nsec_time *t)
+{
+  BOOL ok;
+
+  ok = QueryPerformanceCounter (&t->perf_count);
+  assert (ok);
+}
+
+static double
+get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
+{
+  static double nsecs_per_count = 0.0;
+  double nsecs;
+
+  if (nsecs_per_count == 0.0)
+    {
+      LARGE_INTEGER perf_freq;
+      BOOL ok;
+
+      /* Get counts per second. */
+      ok = QueryPerformanceFrequency (&perf_freq);
+      assert (ok);
+
+      nsecs_per_count = 1.0 / perf_freq.QuadPart;
+      nsecs_per_count *= 1000000.0 * 1000.0;	/* sec => nsec */
+
+      assert (nsecs_per_count > 0.0);
+    }
+
+  nsecs = end->perf_count.QuadPart - start->perf_count.QuadPart;	/* counts */
+  nsecs *= nsecs_per_count;	/* counts * (nsecs / count) => nsecs */
+
+  return nsecs;
+}
+#elif defined(HAVE_CLOCK_GETTIME)
+struct nsec_time
+{
+  struct timespec ts;
+};
+
+static void
+get_nsec_time (struct nsec_time *t)
+{
+  int err;
+
+  err = clock_gettime (CLOCK_REALTIME, &t->ts);
+  assert (err == 0);
+}
+
+static double
+get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
+{
+  double nsecs;
+
+  nsecs = end->ts.tv_sec - start->ts.tv_sec;
+  nsecs *= 1000000.0 * 1000.0;	/* sec => nsec */
+
+  /* This way we don't have to care if tv_nsec unsigned or signed. */
+  if (end->ts.tv_nsec >= start->ts.tv_nsec)
+    nsecs += end->ts.tv_nsec - start->ts.tv_nsec;
+  else
+    nsecs -= start->ts.tv_nsec - end->ts.tv_nsec;
+
+  return nsecs;
+}
+#elif defined(HAVE_GETTIMEOFDAY)
+struct nsec_time
+{
+  struct timeval tv;
+};
+
+static void
+get_nsec_time (struct nsec_time *t)
+{
+  int err;
+
+  err = gettimeofday (&t->tv, NULL);
+  assert (err == 0);
+}
+
+static double
+get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
+{
+  double nsecs;
+
+  nsecs = end->tv.tv_sec - start->tv.tv_sec;
+  nsecs *= 1000000;		/* sec => µsec */
+
+  /* This way we don't have to care if tv_usec unsigned or signed. */
+  if (end->tv.tv_usec >= start->tv.tv_usec)
+    nsecs += end->tv.tv_usec - start->tv.tv_usec;
+  else
+    nsecs -= start->tv.tv_usec - end->tv.tv_usec;
+
+  nsecs *= 1000;		/* µsec => nsec */
+
+  return nsecs;
+}
+#else
+#define NO_GET_NSEC_TIME 1
+#endif
+
+
+/* If no high resolution timer found, provide dummy bench-slope.  */
+#ifdef NO_GET_NSEC_TIME
+
+
+int
+main (void)
+{
+  /* No nsec timer => SKIP test. */
+  return 77;
+}
+
+
+#else /* !NO_GET_NSEC_TIME */
+
+
+/********************************************** Slope benchmarking framework. */
+
+struct bench_obj
+{
+  const struct bench_ops *ops;
+
+  unsigned int num_measure_repetitions;
+  unsigned int min_bufsize;
+  unsigned int max_bufsize;
+  unsigned int step_size;
+
+  void *priv;
+};
+
+typedef int (*const bench_initialize_t) (struct bench_obj * obj);
+typedef void (*const bench_finalize_t) (struct bench_obj * obj);
+typedef void (*const bench_do_run_t) (struct bench_obj * obj, void *buffer,
+				      size_t buflen);
+
+struct bench_ops
+{
+  bench_initialize_t initialize;
+  bench_finalize_t finalize;
+  bench_do_run_t do_run;
+};
+
+
+double
+get_slope (double (*const get_x) (unsigned int idx, void *priv),
+	   void *get_x_priv, double y_points[], unsigned int npoints,
+	   double *overhead)
+{
+  double sumx, sumy, sumx2, sumy2, sumxy;
+  unsigned int i;
+  double b, a;
+
+  sumx = sumy = sumx2 = sumy2 = sumxy = 0;
+
+  for (i = 0; i < npoints; i++)
+    {
+      double x, y;
+
+      x = get_x (i, get_x_priv);	/* bytes */
+      y = y_points[i];		/* nsecs */
+
+      sumx += x;
+      sumy += y;
+      sumx2 += x * x;
+      /*sumy2 += y * y;*/
+      sumxy += x * y;
+    }
+
+  b = (npoints * sumxy - sumx * sumy) / (npoints * sumx2 - sumx * sumx);
+  a = (sumy - b * sumx) / npoints;
+
+  if (overhead)
+    *overhead = a;		/* nsecs */
+
+  return b;			/* nsecs per byte */
+}
+
+
+double
+get_bench_obj_point_x (unsigned int idx, void *priv)
+{
+  struct bench_obj *obj = priv;
+  return (double) (obj->min_bufsize + (idx * obj->step_size));
+}
+
+
+unsigned int
+get_num_measurements (struct bench_obj *obj)
+{
+  unsigned int buf_range = obj->max_bufsize - obj->min_bufsize;
+  unsigned int num = buf_range / obj->step_size + 1;
+
+  while (obj->min_bufsize + (num * obj->step_size) > obj->max_bufsize)
+    num--;
+
+  return num + 1;
+}
+
+
+static int
+double_cmp (const void *_a, const void *_b)
+{
+  const double *a, *b;
+
+  a = _a;
+  b = _b;
+
+  if (*a > *b)
+    return 1;
+  if (*a < *b)
+    return -1;
+  return 0;
+}
+
+
+double
+do_bench_obj_measurement (struct bench_obj *obj, void *buffer, size_t buflen,
+			  double *measurement_raw,
+			  unsigned int loop_iterations)
+{
+  const unsigned int num_repetitions = obj->num_measure_repetitions;
+  const bench_do_run_t do_run = obj->ops->do_run;
+  struct nsec_time start, end;
+  unsigned int rep, loop;
+  double res;
+
+  if (num_repetitions < 1 || loop_iterations < 1)
+    return 0.0;
+
+  for (rep = 0; rep < num_repetitions; rep++)
+    {
+      get_nsec_time (&start);
+
+      for (loop = 0; loop < loop_iterations; loop++)
+	do_run (obj, buffer, buflen);
+
+      get_nsec_time (&end);
+
+      measurement_raw[rep] = get_time_nsec_diff (&start, &end);
+    }
+
+  /* Return median of repeated measurements. */
+  qsort (measurement_raw, num_repetitions, sizeof (measurement_raw[0]),
+	 double_cmp);
+
+  if (num_repetitions % 2 == 1)
+    return measurement_raw[num_repetitions / 2];
+
+  res = measurement_raw[num_repetitions / 2]
+    + measurement_raw[num_repetitions / 2 - 1];
+  return res / 2;
+}
+
+
+unsigned int
+adjust_loop_iterations_to_timer_accuracy (struct bench_obj *obj, void *buffer,
+					  double *measurement_raw)
+{
+  const double increase_thres = 3.0;
+  double tmp, nsecs;
+  unsigned int loop_iterations;
+  unsigned int test_bufsize;
+
+  test_bufsize = obj->min_bufsize;
+  if (test_bufsize == 0)
+    test_bufsize += obj->step_size;
+
+  loop_iterations = 0;
+  do
+    {
+      /* Increase loop iterations until we get other results than zero.  */
+      nsecs =
+	do_bench_obj_measurement (obj, buffer, test_bufsize,
+				  measurement_raw, ++loop_iterations);
+    }
+  while (nsecs < 1.0 - 0.1);
+  do
+    {
+      /* Increase loop iterations until we get reasonable increase for elapsed time.  */
+      tmp =
+	do_bench_obj_measurement (obj, buffer, test_bufsize,
+				  measurement_raw, ++loop_iterations);
+    }
+  while (tmp < nsecs * (increase_thres - 0.1));
+
+  return loop_iterations;
+}
+
+
+/* Benchmark and return linear regression slope in nanoseconds per byte.  */
+double
+do_slope_benchmark (struct bench_obj *obj)
+{
+  unsigned int num_measurements;
+  double *measurements = NULL;
+  double *measurement_raw = NULL;
+  double slope, overhead;
+  unsigned int loop_iterations, midx, i;
+  unsigned char *real_buffer = NULL;
+  unsigned char *buffer;
+  size_t cur_bufsize;
+  int err;
+
+  err = obj->ops->initialize (obj);
+  if (err < 0)
+    return -1;
+
+  num_measurements = get_num_measurements (obj);
+  measurements = calloc (num_measurements, sizeof (*measurements));
+  if (!measurements)
+    goto err_free;
+
+  measurement_raw =
+    calloc (obj->num_measure_repetitions, sizeof (*measurement_raw));
+  if (!measurement_raw)
+    goto err_free;
+
+  if (num_measurements < 1 || obj->num_measure_repetitions < 1 ||
+      obj->max_bufsize < 1 || obj->min_bufsize > obj->max_bufsize)
+    goto err_free;
+
+  real_buffer = malloc (obj->max_bufsize + 128);
+  if (!real_buffer)
+    goto err_free;
+  /* Get aligned buffer */
+  buffer = real_buffer;
+  buffer += 128 - ((real_buffer - (unsigned char *) 0) & (128 - 1));
+
+  for (i = 0; i < obj->max_bufsize; i++)
+    buffer[i] = 0x55 ^ (-i);
+
+  /* Adjust number of loop iterations up to timer accuracy.  */
+  loop_iterations = adjust_loop_iterations_to_timer_accuracy (obj, buffer,
+							      measurement_raw);
+
+  /* Perform measurements */
+  for (midx = 0, cur_bufsize = obj->min_bufsize;
+       cur_bufsize <= obj->max_bufsize; cur_bufsize += obj->step_size, midx++)
+    {
+      measurements[midx] =
+	do_bench_obj_measurement (obj, buffer, cur_bufsize, measurement_raw,
+				  loop_iterations);
+      measurements[midx] /= loop_iterations;
+    }
+
+  assert (midx == num_measurements);
+
+  slope =
+    get_slope (&get_bench_obj_point_x, obj, measurements, num_measurements,
+	       &overhead);
+
+  free (measurement_raw);
+  free (real_buffer);
+  obj->ops->finalize (obj);
+
+  return slope;
+
+err_free:
+  if (measurement_raw)
+    free (measurement_raw);
+  if (measurements)
+    free (measurements);
+  if (real_buffer)
+    free (real_buffer);
+  obj->ops->finalize (obj);
+
+  return -1;
+}
+
+
+/********************************************************** Printing results. */
+
+static void
+double_to_str (char *out, size_t outlen, double value)
+{
+  const char *fmt;
+
+  if (value < 1.0)
+    fmt = "%.3f";
+  else if (value < 100.0)
+    fmt = "%.2f";
+  else
+    fmt = "%.1f";
+
+  snprintf (out, outlen, fmt, value);
+}
+
+static void
+bench_print_result_csv (double nsecs_per_byte)
+{
+  double cycles_per_byte, mbytes_per_sec;
+  char nsecpbyte_buf[16];
+  char mbpsec_buf[16];
+  char cpbyte_buf[16];
+
+  *cpbyte_buf = 0;
+
+  double_to_str (nsecpbyte_buf, sizeof (nsecpbyte_buf), nsecs_per_byte);
+
+  /* If user didn't provide CPU speed, we cannot show cycles/byte results.  */
+  if (cpu_ghz > 0.0)
+    {
+      cycles_per_byte = nsecs_per_byte * cpu_ghz;
+      double_to_str (cpbyte_buf, sizeof (cpbyte_buf), cycles_per_byte);
+    }
+
+  mbytes_per_sec =
+    (1000.0 * 1000.0 * 1000.0) / (nsecs_per_byte * 1024 * 1024);
+  double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec);
+
+  /* We print two empty fields to allow for future enhancements.  */
+  printf ("%s,%s,%s,,,%s,ns/B,%s,MiB/s,%s,c/B\n",
+          current_section_name,
+          current_algo_name? current_algo_name : "",
+          current_mode_name? current_mode_name : "",
+          nsecpbyte_buf,
+          mbpsec_buf,
+          cpbyte_buf);
+
+}
+
+static void
+bench_print_result_std (double nsecs_per_byte)
+{
+  double cycles_per_byte, mbytes_per_sec;
+  char nsecpbyte_buf[16];
+  char mbpsec_buf[16];
+  char cpbyte_buf[16];
+
+  strcpy (cpbyte_buf, "-");
+
+  double_to_str (nsecpbyte_buf, sizeof (nsecpbyte_buf), nsecs_per_byte);
+
+  /* If user didn't provide CPU speed, we cannot show cycles/byte results.  */
+  if (cpu_ghz > 0.0)
+    {
+      cycles_per_byte = nsecs_per_byte * cpu_ghz;
+      double_to_str (cpbyte_buf, sizeof (cpbyte_buf), cycles_per_byte);
+    }
+
+  mbytes_per_sec =
+    (1000.0 * 1000.0 * 1000.0) / (nsecs_per_byte * 1024 * 1024);
+  double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec);
+
+  strncat (nsecpbyte_buf, " ns/B", sizeof (nsecpbyte_buf) - 1);
+  strncat (mbpsec_buf, " MiB/s", sizeof (mbpsec_buf) - 1);
+  strncat (cpbyte_buf, " c/B", sizeof (cpbyte_buf) - 1);
+
+  printf ("%14s %15s %13s\n", nsecpbyte_buf, mbpsec_buf, cpbyte_buf);
+}
+
+static void
+bench_print_result (double nsecs_per_byte)
+{
+  if (csv_mode)
+    bench_print_result_csv (nsecs_per_byte);
+  else
+    bench_print_result_std (nsecs_per_byte);
+}
+
+static void
+bench_print_section (const char *section_name, const char *print_name)
+{
+  if (csv_mode)
+    {
+      gcry_free (current_section_name);
+      current_section_name = gcry_xstrdup (section_name);
+    }
+  else
+    printf ("%s:\n", print_name);
+}
+
+static void
+bench_print_header (int algo_width, const char *algo_name)
+{
+  if (csv_mode)
+    {
+      gcry_free (current_algo_name);
+      current_algo_name = gcry_xstrdup (algo_name);
+    }
+  else
+    {
+      if (algo_width < 0)
+        printf (" %-*s | ", -algo_width, algo_name);
+      else
+        printf (" %-*s | ", algo_width, algo_name);
+      printf ("%14s %15s %13s\n", "nanosecs/byte", "mebibytes/sec",
+              "cycles/byte");
+    }
+}
+
+static void
+bench_print_algo (int algo_width, const char *algo_name)
+{
+  if (csv_mode)
+    {
+      gcry_free (current_algo_name);
+      current_algo_name = gcry_xstrdup (algo_name);
+    }
+  else
+    {
+      if (algo_width < 0)
+        printf (" %-*s | ", -algo_width, algo_name);
+      else
+        printf (" %-*s | ", algo_width, algo_name);
+    }
+}
+
+static void
+bench_print_mode (int width, const char *mode_name)
+{
+  if (csv_mode)
+    {
+      gcry_free (current_mode_name);
+      current_mode_name = gcry_xstrdup (mode_name);
+    }
+  else
+    {
+      if (width < 0)
+        printf (" %-*s | ", -width, mode_name);
+      else
+        printf (" %*s | ", width, mode_name);
+      fflush (stdout);
+    }
+}
+
+static void
+bench_print_footer (int algo_width)
+{
+  if (!csv_mode)
+    printf (" %-*s =\n", algo_width, "");
+}
+
+
+/********************************************************* Cipher benchmarks. */
+
+struct bench_cipher_mode
+{
+  int mode;
+  const char *name;
+  struct bench_ops *ops;
+
+  int algo;
+};
+
+
+static int
+bench_encrypt_init (struct bench_obj *obj)
+{
+  struct bench_cipher_mode *mode = obj->priv;
+  gcry_cipher_hd_t hd;
+  int err, keylen;
+
+  obj->min_bufsize = BUF_START_SIZE;
+  obj->max_bufsize = BUF_END_SIZE;
+  obj->step_size = BUF_STEP_SIZE;
+  obj->num_measure_repetitions = num_measurement_repetitions;
+
+  err = gcry_cipher_open (&hd, mode->algo, mode->mode, 0);
+  if (err)
+    {
+      fprintf (stderr, PGM ": error opening cipher `%s'\n",
+	       gcry_cipher_algo_name (mode->algo));
+      exit (1);
+    }
+
+  keylen = gcry_cipher_get_algo_keylen (mode->algo);
+  if (keylen)
+    {
+      char key[keylen];
+      int i;
+
+      for (i = 0; i < keylen; i++)
+	key[i] = 0x33 ^ (11 - i);
+
+      err = gcry_cipher_setkey (hd, key, keylen);
+      if (err)
+	{
+	  fprintf (stderr, PGM ": gcry_cipher_setkey failed: %s\n",
+		   gpg_strerror (err));
+	  gcry_cipher_close (hd);
+	  exit (1);
+	}
+    }
+  else
+    {
+      fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
+	       gcry_cipher_algo_name (mode->algo));
+      gcry_cipher_close (hd);
+      exit (1);
+    }
+
+  obj->priv = hd;
+
+  return 0;
+}
+
+static void
+bench_encrypt_free (struct bench_obj *obj)
+{
+  gcry_cipher_hd_t hd = obj->priv;
+
+  gcry_cipher_close (hd);
+}
+
+static void
+bench_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
+{
+  gcry_cipher_hd_t hd = obj->priv;
+  int err;
+
+  err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen);
+  if (err)
+    {
+      fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
+	       gpg_strerror (err));
+      gcry_cipher_close (hd);
+      exit (1);
+    }
+}
+
+static void
+bench_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
+{
+  gcry_cipher_hd_t hd = obj->priv;
+  int err;
+
+  err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
+  if (err)
+    {
+      fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
+	       gpg_strerror (err));
+      gcry_cipher_close (hd);
+      exit (1);
+    }
+}
+
+static struct bench_ops encrypt_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_encrypt_do_bench
+};
+
+static struct bench_ops decrypt_ops = {
+  &bench_encrypt_init,
+  &bench_encrypt_free,
+  &bench_decrypt_do_bench
+};
+
+
+
+static struct bench_cipher_mode cipher_modes[] = {
+  {GCRY_CIPHER_MODE_ECB, "ECB enc", &encrypt_ops},
+  {GCRY_CIPHER_MODE_ECB, "ECB dec", &decrypt_ops},
+  {GCRY_CIPHER_MODE_CBC, "CBC enc", &encrypt_ops},
+  {GCRY_CIPHER_MODE_CBC, "CBC dec", &decrypt_ops},
+  {GCRY_CIPHER_MODE_CFB, "CFB enc", &encrypt_ops},
+  {GCRY_CIPHER_MODE_CFB, "CFB dec", &decrypt_ops},
+  {GCRY_CIPHER_MODE_OFB, "OFB enc", &encrypt_ops},
+  {GCRY_CIPHER_MODE_OFB, "OFB dec", &decrypt_ops},
+  {GCRY_CIPHER_MODE_CTR, "CTR enc", &encrypt_ops},
+  {GCRY_CIPHER_MODE_CTR, "CTR dec", &decrypt_ops},
+  {0},
+};
+
+
+static void
+cipher_bench_one (int algo, struct bench_cipher_mode *pmode)
+{
+  struct bench_cipher_mode mode = *pmode;
+  struct bench_obj obj = { 0 };
+  double result;
+  unsigned int blklen;
+
+  mode.algo = algo;
+
+  /* Check if this mode is ok */
+  blklen = gcry_cipher_get_algo_blklen (algo);
+  if (!blklen)
+    return;
+
+  /* Stream cipher? Only test with ECB. */
+  if (blklen == 1 && mode.mode != GCRY_CIPHER_MODE_ECB)
+    return;
+  if (blklen == 1 && mode.mode == GCRY_CIPHER_MODE_ECB)
+    {
+      mode.mode = GCRY_CIPHER_MODE_STREAM;
+      mode.name = mode.ops == &encrypt_ops ? "STREAM enc" : "STREAM dec";
+    }
+
+  bench_print_mode (14, mode.name);
+
+  obj.ops = mode.ops;
+  obj.priv = &mode;
+
+  result = do_slope_benchmark (&obj);
+
+  bench_print_result (result);
+}
+
+
+static void
+_cipher_bench (int algo)
+{
+  const char *algoname;
+  int i;
+
+  algoname = gcry_cipher_algo_name (algo);
+
+  bench_print_header (14, algoname);
+
+  for (i = 0; cipher_modes[i].mode; i++)
+    cipher_bench_one (algo, &cipher_modes[i]);
+
+  bench_print_footer (14);
+}
+
+
+void
+cipher_bench (char **argv, int argc)
+{
+  int i, algo;
+
+  bench_print_section ("cipher", "Cipher");
+
+  if (argv && argc)
+    {
+      for (i = 0; i < argc; i++)
+	{
+	  algo = gcry_cipher_map_name (argv[i]);
+	  if (algo)
+	    _cipher_bench (algo);
+	}
+    }
+  else
+    {
+      for (i = 1; i < 400; i++)
+	if (!gcry_cipher_test_algo (i))
+	  _cipher_bench (i);
+    }
+}
+
+
+/*********************************************************** Hash benchmarks. */
+
+struct bench_hash_mode
+{
+  const char *name;
+  struct bench_ops *ops;
+
+  int algo;
+};
+
+
+static int
+bench_hash_init (struct bench_obj *obj)
+{
+  struct bench_hash_mode *mode = obj->priv;
+  gcry_md_hd_t hd;
+  int err;
+
+  obj->min_bufsize = BUF_START_SIZE;
+  obj->max_bufsize = BUF_END_SIZE;
+  obj->step_size = BUF_STEP_SIZE;
+  obj->num_measure_repetitions = num_measurement_repetitions;
+
+  err = gcry_md_open (&hd, mode->algo, 0);
+  if (err)
+    {
+      fprintf (stderr, PGM ": error opening hash `%s'\n",
+	       gcry_md_algo_name (mode->algo));
+      exit (1);
+    }
+
+  obj->priv = hd;
+
+  return 0;
+}
+
+static void
+bench_hash_free (struct bench_obj *obj)
+{
+  gcry_md_hd_t hd = obj->priv;
+
+  gcry_md_close (hd);
+}
+
+static void
+bench_hash_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
+{
+  gcry_md_hd_t hd = obj->priv;
+
+  gcry_md_reset (hd);
+  gcry_md_write (hd, buf, buflen);
+  gcry_md_final (hd);
+}
+
+static struct bench_ops hash_ops = {
+  &bench_hash_init,
+  &bench_hash_free,
+  &bench_hash_do_bench
+};
+
+
+static struct bench_hash_mode hash_modes[] = {
+  {"", &hash_ops},
+  {0},
+};
+
+
+static void
+hash_bench_one (int algo, struct bench_hash_mode *pmode)
+{
+  struct bench_hash_mode mode = *pmode;
+  struct bench_obj obj = { 0 };
+  double result;
+
+  mode.algo = algo;
+
+  if (mode.name[0] == '\0')
+    bench_print_algo (-14, gcry_md_algo_name (algo));
+  else
+    bench_print_algo (14, mode.name);
+
+  obj.ops = mode.ops;
+  obj.priv = &mode;
+
+  result = do_slope_benchmark (&obj);
+
+  bench_print_result (result);
+}
+
+static void
+_hash_bench (int algo)
+{
+  int i;
+
+  for (i = 0; hash_modes[i].name; i++)
+    hash_bench_one (algo, &hash_modes[i]);
+}
+
+void
+hash_bench (char **argv, int argc)
+{
+  int i, algo;
+
+  bench_print_section ("hash", "Hash");
+  bench_print_header (14, "");
+
+  if (argv && argc)
+    {
+      for (i = 0; i < argc; i++)
+	{
+	  algo = gcry_md_map_name (argv[i]);
+	  if (algo)
+	    _hash_bench (algo);
+	}
+    }
+  else
+    {
+      for (i = 1; i < 400; i++)
+	if (!gcry_md_test_algo (i))
+	  _hash_bench (i);
+    }
+
+  bench_print_footer (14);
+}
+
+
+/************************************************************** Main program. */
+
+void
+print_help (void)
+{
+  static const char *help_lines[] = {
+    "usage: bench-slope [options] [hash|cipher [algonames]]",
+    "",
+    " options:",
+    "   --cpu-mhz <mhz>           Set CPU speed for calculating cycles",
+    "                             per bytes results.",
+    "   --disable-hwf <features>  Disable hardware acceleration feature(s)",
+    "                             for benchmarking.",
+    "   --repetitions <n>         Use N repetitions (default "
+                                     STR2(NUM_MEASUREMENT_REPETITIONS) ")",
+    "   --csv                     Use CSV output format",
+    NULL
+  };
+  const char **line;
+
+  for (line = help_lines; *line; line++)
+    fprintf (stdout, "%s\n", *line);
+}
+
+
+/* Warm up CPU.  */
+static void
+warm_up_cpu (void)
+{
+  struct nsec_time start, end;
+
+  get_nsec_time (&start);
+  do
+    {
+      get_nsec_time (&end);
+    }
+  while (get_time_nsec_diff (&start, &end) < 1000.0 * 1000.0 * 1000.0);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int last_argc = -1;
+  int debug = 0;
+
+  num_measurement_repetitions = NUM_MEASUREMENT_REPETITIONS;
+
+  if (argc)
+    {
+      argc--;
+      argv++;
+    }
+
+  /* We skip this test if we are running under the test suite (no args
+     and srcdir defined) and GCRYPT_NO_BENCHMARKS is set.  */
+  if (!argc && getenv ("srcdir") && getenv ("GCRYPT_NO_BENCHMARKS"))
+    exit (77);
+
+  while (argc && last_argc != argc)
+    {
+      last_argc = argc;
+
+      if (!strcmp (*argv, "--"))
+	{
+	  argc--;
+	  argv++;
+	  break;
+	}
+      else if (!strcmp (*argv, "--help"))
+	{
+	  print_help ();
+	  exit (0);
+	}
+      else if (!strcmp (*argv, "--verbose"))
+	{
+	  verbose++;
+	  argc--;
+	  argv++;
+	}
+      else if (!strcmp (*argv, "--debug"))
+	{
+	  verbose += 2;
+	  debug++;
+	  argc--;
+	  argv++;
+	}
+      else if (!strcmp (*argv, "--csv"))
+	{
+	  csv_mode = 1;
+	  argc--;
+	  argv++;
+	}
+      else if (!strcmp (*argv, "--disable-hwf"))
+	{
+	  argc--;
+	  argv++;
+	  if (argc)
+	    {
+	      if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL))
+		fprintf (stderr,
+			 PGM
+			 ": unknown hardware feature `%s' - option ignored\n",
+			 *argv);
+	      argc--;
+	      argv++;
+	    }
+	}
+      else if (!strcmp (*argv, "--cpu-mhz"))
+	{
+	  argc--;
+	  argv++;
+	  if (argc)
+	    {
+	      cpu_ghz = atof (*argv);
+	      cpu_ghz /= 1000;	/* Mhz => Ghz */
+
+	      argc--;
+	      argv++;
+	    }
+	}
+      else if (!strcmp (*argv, "--repetitions"))
+	{
+	  argc--;
+	  argv++;
+	  if (argc)
+	    {
+	      num_measurement_repetitions = atof (*argv);
+              if (num_measurement_repetitions < 2)
+                {
+                  fprintf (stderr,
+                           PGM
+                           ": value for --repetitions too small - using %d\n",
+                           NUM_MEASUREMENT_REPETITIONS);
+                  num_measurement_repetitions = NUM_MEASUREMENT_REPETITIONS;
+                }
+	      argc--;
+	      argv++;
+	    }
+	}
+    }
+
+  gcry_control (GCRYCTL_SET_VERBOSITY, (int) verbose);
+
+  if (!gcry_check_version (GCRYPT_VERSION))
+    {
+      fprintf (stderr, PGM ": version mismatch; pgm=%s, library=%s\n",
+	       GCRYPT_VERSION, gcry_check_version (NULL));
+      exit (1);
+    }
+
+  if (debug)
+    gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
+
+  gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+
+  if (!argc)
+    {
+      warm_up_cpu ();
+      hash_bench (NULL, 0);
+      cipher_bench (NULL, 0);
+    }
+  else if (!strcmp (*argv, "hash"))
+    {
+      argc--;
+      argv++;
+
+      warm_up_cpu ();
+      hash_bench ((argc == 0) ? NULL : argv, argc);
+    }
+  else if (!strcmp (*argv, "cipher"))
+    {
+      argc--;
+      argv++;
+
+      warm_up_cpu ();
+      cipher_bench ((argc == 0) ? NULL : argv, argc);
+    }
+  else
+    {
+      fprintf (stderr, PGM ": unknown argument: %s\n", *argv);
+      print_help ();
+    }
+
+  return 0;
+}
+
+#endif /* !NO_GET_NSEC_TIME */

-----------------------------------------------------------------------

Summary of changes:
 tests/Makefile.am   |    2 +-
 tests/bench-slope.c | 1148 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1149 insertions(+), 1 deletion(-)
 create mode 100644 tests/bench-slope.c


hooks/post-receive
-- 
The GNU crypto library
http://git.gnupg.org




More information about the Gnupg-commits mailing list