| /* Skeleton for benchmark programs. | 
 |    Copyright (C) 2013-2016 Free Software Foundation, Inc. | 
 |    This file is part of the GNU C Library. | 
 |  | 
 |    The GNU C Library 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. | 
 |  | 
 |    The GNU C Library 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 the GNU C Library; if not, see | 
 |    <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include <string.h> | 
 | #include <stdint.h> | 
 | #include <stdbool.h> | 
 | #include <stdio.h> | 
 | #include <time.h> | 
 | #include <inttypes.h> | 
 | #include "bench-timing.h" | 
 | #include "json-lib.h" | 
 | #include "bench-util.h" | 
 |  | 
 | #include "bench-util.c" | 
 |  | 
 | #define TIMESPEC_AFTER(a, b) \ | 
 |   (((a).tv_sec == (b).tv_sec) ?						      \ | 
 |      ((a).tv_nsec > (b).tv_nsec) :					      \ | 
 | 	((a).tv_sec > (b).tv_sec)) | 
 | int | 
 | main (int argc, char **argv) | 
 | { | 
 |   unsigned long i, k; | 
 |   struct timespec runtime; | 
 |   timing_t start, end; | 
 |   bool detailed = false; | 
 |   json_ctx_t json_ctx; | 
 |  | 
 |   if (argc == 2 && !strcmp (argv[1], "-d")) | 
 |     detailed = true; | 
 |  | 
 |   bench_start (); | 
 |  | 
 |   memset (&runtime, 0, sizeof (runtime)); | 
 |  | 
 |   unsigned long iters, res; | 
 |  | 
 | #ifdef BENCH_INIT | 
 |   BENCH_INIT (); | 
 | #endif | 
 |   TIMING_INIT (res); | 
 |  | 
 |   iters = 1000 * res; | 
 |  | 
 |   json_init (&json_ctx, 2, stdout); | 
 |  | 
 |   /* Begin function.  */ | 
 |   json_attr_object_begin (&json_ctx, FUNCNAME); | 
 |  | 
 |   for (int v = 0; v < NUM_VARIANTS; v++) | 
 |     { | 
 |       /* Run for approximately DURATION seconds.  */ | 
 |       clock_gettime (CLOCK_MONOTONIC_RAW, &runtime); | 
 |       runtime.tv_sec += DURATION; | 
 |  | 
 |       double d_total_i = 0; | 
 |       timing_t total = 0, max = 0, min = 0x7fffffffffffffff; | 
 |       int64_t c = 0; | 
 |       while (1) | 
 | 	{ | 
 | 	  for (i = 0; i < NUM_SAMPLES (v); i++) | 
 | 	    { | 
 | 	      uint64_t cur; | 
 | 	      TIMING_NOW (start); | 
 | 	      for (k = 0; k < iters; k++) | 
 | 		BENCH_FUNC (v, i); | 
 | 	      TIMING_NOW (end); | 
 |  | 
 | 	      TIMING_DIFF (cur, start, end); | 
 |  | 
 | 	      if (cur > max) | 
 | 		max = cur; | 
 |  | 
 | 	      if (cur < min) | 
 | 		min = cur; | 
 |  | 
 | 	      TIMING_ACCUM (total, cur); | 
 | 	      /* Accumulate timings for the value.  In the end we will divide | 
 | 	         by the total iterations.  */ | 
 | 	      RESULT_ACCUM (cur, v, i, c * iters, (c + 1) * iters); | 
 |  | 
 | 	      d_total_i += iters; | 
 | 	    } | 
 | 	  c++; | 
 | 	  struct timespec curtime; | 
 |  | 
 | 	  memset (&curtime, 0, sizeof (curtime)); | 
 | 	  clock_gettime (CLOCK_MONOTONIC_RAW, &curtime); | 
 | 	  if (TIMESPEC_AFTER (curtime, runtime)) | 
 | 	    goto done; | 
 | 	} | 
 |  | 
 |       double d_total_s; | 
 |       double d_iters; | 
 |  | 
 |     done: | 
 |       d_total_s = total; | 
 |       d_iters = iters; | 
 |  | 
 |       /* Begin variant.  */ | 
 |       json_attr_object_begin (&json_ctx, VARIANT (v)); | 
 |  | 
 |       json_attr_double (&json_ctx, "duration", d_total_s); | 
 |       json_attr_double (&json_ctx, "iterations", d_total_i); | 
 |       json_attr_double (&json_ctx, "max", max / d_iters); | 
 |       json_attr_double (&json_ctx, "min", min / d_iters); | 
 |       json_attr_double (&json_ctx, "mean", d_total_s / d_total_i); | 
 |  | 
 |       if (detailed) | 
 | 	{ | 
 | 	  json_array_begin (&json_ctx, "timings"); | 
 |  | 
 | 	  for (int i = 0; i < NUM_SAMPLES (v); i++) | 
 | 	    json_element_double (&json_ctx, RESULT (v, i)); | 
 |  | 
 | 	  json_array_end (&json_ctx); | 
 | 	} | 
 |  | 
 |       /* End variant.  */ | 
 |       json_attr_object_end (&json_ctx); | 
 |     } | 
 |  | 
 |   /* End function.  */ | 
 |   json_attr_object_end (&json_ctx); | 
 |  | 
 |   return 0; | 
 | } |