File: cmph_benchmark.c

package info (click to toggle)
cmph 2.0.2-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 6,748 kB
  • sloc: ansic: 10,582; cpp: 2,429; makefile: 151; sh: 111; python: 48; xml: 5
file content (129 lines) | stat: -rw-r--r-- 3,462 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// A simple benchmark tool around getrusage

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>

#include "cmph_benchmark.h"

typedef struct {
  const char* name;
  void (*func)(int);
  int iters;
  struct rusage begin;
  struct rusage end;
} benchmark_t;

static benchmark_t* global_benchmarks = NULL;

/* Subtract the `struct timeval' values X and Y,
   storing the result in RESULT.
   Return 1 if the difference is negative, otherwise 0.  */

int timeval_subtract ( 
    struct timeval *result, struct timeval *x, struct timeval* y) {
  /* Perform the carry for the later subtraction by updating y. */
  if (x->tv_usec < y->tv_usec) {
    int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
    y->tv_usec -= 1000000 * nsec;
    y->tv_sec += nsec;
  }
  if (x->tv_usec - y->tv_usec > 1000000) {
    int nsec = (x->tv_usec - y->tv_usec) / 1000000;
    y->tv_usec += 1000000 * nsec;
    y->tv_sec -= nsec;
  }

  /* Compute the time remaining to wait.
     tv_usec is certainly positive. */
  result->tv_sec = x->tv_sec - y->tv_sec;
  result->tv_usec = x->tv_usec - y->tv_usec;

  /* Return 1 if result is negative. */
  return x->tv_sec < y->tv_sec;
}

benchmark_t* find_benchmark(const char* name) {
  benchmark_t* benchmark = global_benchmarks;
  while (benchmark && benchmark->name != NULL) {
    if (strcmp(benchmark->name, name) == 0) break;
    ++benchmark;
  }
  if (!benchmark || !benchmark->name) return NULL;
  return benchmark;
}

int global_benchmarks_length() {
  benchmark_t* benchmark = global_benchmarks;
  int length = 0;
  if (benchmark == NULL) return 0;
  while (benchmark->name != NULL) ++length, ++benchmark;
  return length;
}

void bm_register(const char* name, void (*func)(int), int iters) {
  benchmark_t benchmark;
  int length = global_benchmarks_length();
  benchmark.name = name;
  benchmark.func = func;
  benchmark.iters = iters;
  assert(!find_benchmark(name));
  global_benchmarks = (benchmark_t *)realloc(
      global_benchmarks, (length + 2)*sizeof(benchmark_t));
  global_benchmarks[length] = benchmark;
  memset(&benchmark, 0, sizeof(benchmark_t));  // pivot
  global_benchmarks[length + 1] = benchmark;
}

void bm_start(const char* name) {
  benchmark_t* benchmark;
  struct rusage rs;

  benchmark = find_benchmark(name);
  assert(benchmark);
  int ret = getrusage(RUSAGE_SELF, &rs);  
  if (ret != 0) {
    perror("rusage failed");    
    exit(-1);
  }
  benchmark->begin = rs;
  (*benchmark->func)(benchmark->iters);
}

void bm_end(const char* name) { 
  benchmark_t* benchmark;
  struct rusage rs;

  int ret = getrusage(RUSAGE_SELF, &rs);  
  if (ret != 0) {
    perror("rusage failed");    
    exit(-1);
  }

  benchmark = find_benchmark(name);
  benchmark->end = rs;

  struct timeval utime;
  timeval_subtract(&utime, &benchmark->end.ru_utime, &benchmark->begin.ru_utime);
  struct timeval stime;
  timeval_subtract(&stime, &benchmark->end.ru_stime, &benchmark->begin.ru_stime);
  
  printf("Benchmark: %s\n", benchmark->name);
  printf("User time used  : %ld.%06ld\n",
         utime.tv_sec, (long int)utime.tv_usec);
  printf("System time used: %ld.%06ld\n",
         stime.tv_sec, (long int)stime.tv_usec);
  printf("\n");
}
 
void run_benchmarks(int argc, char** argv) {
  benchmark_t* benchmark = global_benchmarks;
  while (benchmark && benchmark->name != NULL) {
    bm_start(benchmark->name);
    bm_end(benchmark->name);
    ++benchmark;
  }
}