(root)/
glibc-2.38/
benchtests/
bench-skeleton.c
       1  /* Skeleton for benchmark programs.
       2     Copyright (C) 2013-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <string.h>
      20  #include <stdint.h>
      21  #include <stdbool.h>
      22  #include <stdio.h>
      23  #include <time.h>
      24  #include <inttypes.h>
      25  #include "bench-timing.h"
      26  #include "json-lib.h"
      27  #include "bench-util.h"
      28  
      29  #include "bench-util.c"
      30  
      31  #define TIMESPEC_AFTER(a, b) \
      32    (((a).tv_sec == (b).tv_sec)						      \
      33     ? ((a).tv_nsec > (b).tv_nsec)					      \
      34     : ((a).tv_sec > (b).tv_sec))
      35  int
      36  main (int argc, char **argv)
      37  {
      38    unsigned long i, k;
      39    struct timespec runtime;
      40    timing_t start, end;
      41    bool detailed = false;
      42    json_ctx_t json_ctx;
      43  
      44    if (argc == 2 && !strcmp (argv[1], "-d"))
      45      detailed = true;
      46  
      47    bench_start ();
      48  
      49    memset (&runtime, 0, sizeof (runtime));
      50  
      51    unsigned long iters = 1000;
      52  
      53  #ifdef BENCH_INIT
      54    BENCH_INIT ();
      55  #endif
      56  
      57    json_init (&json_ctx, 2, stdout);
      58  
      59    /* Begin function.  */
      60    json_attr_object_begin (&json_ctx, FUNCNAME);
      61  
      62    for (int v = 0; v < NUM_VARIANTS; v++)
      63      {
      64        /* Run for approximately DURATION seconds.  */
      65        clock_gettime (CLOCK_MONOTONIC_RAW, &runtime);
      66        runtime.tv_sec += DURATION;
      67  
      68        bool is_bench = strncmp (VARIANT (v), "workload-", 9) == 0;
      69        double d_total_i = 0;
      70        timing_t total = 0, max = 0, min = 0x7fffffffffffffff;
      71        timing_t throughput = 0, latency = 0;
      72        int64_t c = 0;
      73        uint64_t cur;
      74        BENCH_VARS;
      75        while (1)
      76  	{
      77  	  if (is_bench)
      78  	    {
      79  	      /* Benchmark a real trace of calls - all samples are iterated
      80  		 over once before repeating.  This models actual use more
      81  		 accurately than repeating the same sample many times.  */
      82  	      TIMING_NOW (start);
      83  	      for (k = 0; k < iters; k++)
      84  		for (i = 0; i < NUM_SAMPLES (v); i++)
      85  		  BENCH_FUNC (v, i);
      86  	      TIMING_NOW (end);
      87  	      TIMING_DIFF (cur, start, end);
      88  	      TIMING_ACCUM (throughput, cur);
      89  
      90  	      TIMING_NOW (start);
      91  	      for (k = 0; k < iters; k++)
      92  		for (i = 0; i < NUM_SAMPLES (v); i++)
      93  		  BENCH_FUNC_LAT (v, i);
      94  	      TIMING_NOW (end);
      95  	      TIMING_DIFF (cur, start, end);
      96  	      TIMING_ACCUM (latency, cur);
      97  
      98  	      d_total_i += iters * NUM_SAMPLES (v);
      99  	    }
     100  	  else
     101  	    for (i = 0; i < NUM_SAMPLES (v); i++)
     102  	      {
     103  		TIMING_NOW (start);
     104  		for (k = 0; k < iters; k++)
     105  		  BENCH_FUNC (v, i);
     106  		TIMING_NOW (end);
     107  
     108  		TIMING_DIFF (cur, start, end);
     109  
     110  		if (cur > max)
     111  		  max = cur;
     112  
     113  		if (cur < min)
     114  		  min = cur;
     115  
     116  		TIMING_ACCUM (total, cur);
     117  		/* Accumulate timings for the value.  In the end we will divide
     118  		   by the total iterations.  */
     119  		RESULT_ACCUM (cur, v, i, c * iters, (c + 1) * iters);
     120  
     121  		d_total_i += iters;
     122  	      }
     123  	  c++;
     124  	  struct timespec curtime;
     125  
     126  	  memset (&curtime, 0, sizeof (curtime));
     127  	  clock_gettime (CLOCK_MONOTONIC_RAW, &curtime);
     128  	  if (TIMESPEC_AFTER (curtime, runtime))
     129  	    goto done;
     130  	}
     131  
     132        double d_total_s;
     133        double d_iters;
     134  
     135      done:
     136        d_total_s = total;
     137        d_iters = iters;
     138  
     139        /* Begin variant.  */
     140        json_attr_object_begin (&json_ctx, VARIANT (v));
     141  
     142        if (is_bench)
     143  	{
     144  	  json_attr_double (&json_ctx, "duration", throughput + latency);
     145  	  json_attr_double (&json_ctx, "iterations", 2 * d_total_i);
     146  	  json_attr_double (&json_ctx, "reciprocal-throughput",
     147  			    throughput / d_total_i);
     148  	  json_attr_double (&json_ctx, "latency", latency / d_total_i);
     149  	  json_attr_double (&json_ctx, "max-throughput",
     150  			    d_total_i / throughput * 1000000000.0);
     151  	  json_attr_double (&json_ctx, "min-throughput",
     152  			    d_total_i / latency * 1000000000.0);
     153  	}
     154        else
     155  	{
     156  	  json_attr_double (&json_ctx, "duration", d_total_s);
     157  	  json_attr_double (&json_ctx, "iterations", d_total_i);
     158  	  json_attr_double (&json_ctx, "max", max / d_iters);
     159  	  json_attr_double (&json_ctx, "min", min / d_iters);
     160  	  json_attr_double (&json_ctx, "mean", d_total_s / d_total_i);
     161  	}
     162  
     163        if (detailed && !is_bench)
     164  	{
     165  	  json_array_begin (&json_ctx, "timings");
     166  
     167  	  for (int i = 0; i < NUM_SAMPLES (v); i++)
     168  	    json_element_double (&json_ctx, RESULT (v, i));
     169  
     170  	  json_array_end (&json_ctx);
     171  	}
     172  
     173        /* End variant.  */
     174        json_attr_object_end (&json_ctx);
     175      }
     176  
     177    /* End function.  */
     178    json_attr_object_end (&json_ctx);
     179  
     180    return 0;
     181  }