~linaro-toolchain-dev/cortex-strings/trunk

« back to all changes in this revision

Viewing changes to benchmarks/multi/harness.c

  • Committer: Michael Hope
  • Date: 2010-09-02 03:49:37 UTC
  • Revision ID: michael.hope@linaro.org-20100902034937-04yh308gq254n5mh
Added comments.  General tidy up.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** A simple harness that times how long a string function takes to
 
2
 * run.
 
3
 */
 
4
 
 
5
/* PENDING: Add EPL */
 
6
 
1
7
#include <string.h>
2
8
#include <time.h>
3
9
#include <stdint.h>
7
13
#include <assert.h>
8
14
#include <unistd.h>
9
15
 
10
 
#define QUOTEME_(x) #x
11
 
#define QUOTEME(x) QUOTEME_(x)
12
 
 
13
16
#define NUM_ELEMS(_x) (sizeof(_x) / sizeof((_x)[0]))
14
17
 
15
18
#ifndef VERSION
16
19
#define VERSION "(unknown version)"
17
20
#endif
18
21
 
19
 
static const char* version = QUOTEME(VERSION);
20
 
 
21
 
/** Current wall time in seconds */
22
 
static double now()
23
 
{
24
 
  struct timespec ts;
25
 
 
26
 
  int err = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
27
 
  assert(err == 0);
28
 
 
29
 
  return ts.tv_sec + ts.tv_nsec * 1e-9;
30
 
}
31
 
 
32
 
static int get_arg(int argc, char **argv, int idx, int fallback)
33
 
{
34
 
  if (argc > idx)
35
 
    {
36
 
      return atoi(argv[idx]);
37
 
    }
38
 
  else
39
 
    {
40
 
      return fallback;
41
 
    }
42
 
}
43
 
 
 
22
/** Type of functions that can be tested */
 
23
typedef void (*stub_t)(void *dest, void *src, size_t n);
 
24
 
 
25
/** Meta data about one test */
 
26
struct test
 
27
{
 
28
  /** Test name */
 
29
  const char *name;
 
30
  /** Function to test */
 
31
  stub_t stub;
 
32
};
 
33
 
 
34
/** Flush the cache by reading a chunk of memory */
44
35
static void empty(volatile char *against)
45
36
{
46
37
  /* We know that there's a 16 k cache with 64 byte lines giving
54
45
    }
55
46
}
56
47
 
 
48
/** Stub that does nothing.  Used for calibrating */
57
49
static void xbounce(void *dest, void *src, size_t n)
58
50
{
59
51
}
60
52
 
 
53
/** Stub that calls memcpy */
61
54
static void xmemcpy(void *dest, void *src, size_t n)
62
55
{
63
56
  memcpy(dest, src, n);
64
57
}
65
58
 
 
59
/** Stub that calls memset */
66
60
static void xmemset(void *dest, void *src, size_t n)
67
61
{
68
62
  memset(dest, 0, n);
69
63
}
70
64
 
 
65
/** Stub that calls strcpy */
71
66
static void xstrcpy(void *dest, void *src, size_t n)
72
67
{
73
68
  strcpy(dest, src);
74
69
}
75
70
 
 
71
/** Stub that calls strlen */
76
72
static void xstrlen(void *dest, void *src, size_t n)
77
73
{
78
74
  (void)strlen(dest);
79
75
}
80
76
 
 
77
/** Stub that calls strcmp */
81
78
static void xstrcmp(void *dest, void *src, size_t n)
82
79
{
83
 
  strcmp(dest, src);
 
80
  (void)strcmp(dest, src);
84
81
}
85
82
 
86
 
typedef void (*stub_t)(void *dest, void *src, size_t n);
87
 
 
88
 
struct test
89
 
{
90
 
  const char *name;
91
 
  stub_t stub;
92
 
};
93
 
 
 
83
/** All functions that can be tested */
94
84
static const struct test tests[] =
95
85
{
96
86
  { "memcpy", xmemcpy },
102
92
  { NULL }
103
93
};
104
94
 
 
95
/** Show basic usage */
105
96
static void usage(const char* name)
106
97
{
107
98
  printf("%s %s: run a string related benchmark.\n"
108
99
         "usage: %s [-c block-size] [-l loop-count] [-f] [-t test-name]\n"
109
 
         , name, version, name);
 
100
         , name, VERSION, name);
 
101
 
 
102
  printf("Tests:");
 
103
 
 
104
  for (const struct test *ptest = tests; ptest->name != NULL; ptest++)
 
105
    {
 
106
      printf(" %s", ptest->name);
 
107
    }
 
108
 
 
109
  printf("\n");
 
110
 
110
111
  exit(-1);
111
112
}
112
113
 
 
114
/** Find the test by name */
 
115
static const struct test *find_test(const char *name)
 
116
{
 
117
  if (name == NULL)
 
118
    {
 
119
      return tests + 0;
 
120
    }
 
121
  else
 
122
    {
 
123
      for (const struct test *p = tests; p->name != NULL; p++)
 
124
        {
 
125
          if (strcmp(p->name, name) == 0)
 
126
            {
 
127
              return p;
 
128
            }
 
129
        }
 
130
    }
 
131
 
 
132
  return NULL;
 
133
}
 
134
 
 
135
/** Setup and run a test */
113
136
int main(int argc, char **argv)
114
137
{
 
138
  /* Buffers to read and write from */
115
139
  char *src = calloc(1024, 1024);
116
140
  char *dest = calloc(1024, 1024);
117
141
 
118
142
  assert(src != NULL && dest != NULL);
119
143
 
120
 
  char *variant = strrchr(argv[0], '-');
121
 
  assert(variant != NULL);
122
 
 
 
144
  /* Fill the first 16 k with non-zero, reproducable random data */
123
145
  srandom(1539);
124
146
 
125
147
  for (int i = 0; i < 16*1024; i++)
128
150
      dest[i] = src[i];
129
151
    }
130
152
 
131
 
  int test_id = get_arg(argc, argv, 1, 0);
132
 
  assert(test_id >= 0 && test_id <= NUM_ELEMS(tests));
133
 
 
 
153
  /* Number of bytes per call */
134
154
  int count = 31;
 
155
  /* Number of times to run */
135
156
  int loops = 10000000;
 
157
  /* True to flush the cache each time */
136
158
  int flush = 0;
 
159
  /* Name of the test */
137
160
  const char *name = NULL;
 
161
 
138
162
  int opt;
139
163
 
140
164
  while ((opt = getopt(argc, argv, "c:l:ft:hv")) > 0)
162
186
        }
163
187
    }
164
188
 
165
 
  const struct test *ptest = NULL;
166
 
 
167
 
  if (name == NULL)
168
 
    {
169
 
      ptest = tests + 0;
170
 
    }
171
 
  else
172
 
    {
173
 
      for (const struct test *p = tests; p->name != NULL; p++)
174
 
        {
175
 
          if (strcmp(p->name, name) == 0)
176
 
            {
177
 
              ptest = p;
178
 
              break;
179
 
            }
180
 
        }
181
 
    }
 
189
  /* Find the test by name */
 
190
  const struct test *ptest = find_test(name);
182
191
 
183
192
  if (ptest == NULL)
184
193
    {
185
194
      usage(argv[0]);
186
195
    }
187
196
 
188
 
  stub_t stub = ptest->stub;
189
 
 
 
197
  /* Make sure the buffers are null terminated for any string tests */
190
198
  src[count] = 0;
191
199
  dest[count] = 0;
192
200
 
193
 
  double start = now();
 
201
  struct timespec start, end;
 
202
  int err = clock_gettime(CLOCK_MONOTONIC, &start);
 
203
  assert(err == 0);
 
204
 
 
205
  /* Preload */
 
206
  stub_t stub = ptest->stub;
194
207
 
195
208
  for (int i = 0; i < loops; i++)
196
209
    {
202
215
        }
203
216
    }
204
217
 
205
 
  double end = now();
206
 
  double elapsed = end - start;
207
 
 
208
 
  printf("%s: %s: %.3f for %u loops of %u bytes.  %.3f MB/s\n", variant + 1, ptest->name, elapsed, loops, count, (double)loops*count/elapsed/(1024*1024));
 
218
  err = clock_gettime(CLOCK_MONOTONIC, &end);
 
219
  assert(err == 0);
 
220
 
 
221
  /* Pull the variant name out of the executable */
 
222
  char *variant = strrchr(argv[0], '-');
 
223
 
 
224
  if (variant == NULL)
 
225
    {
 
226
      variant = argv[0];
 
227
    }
 
228
 
 
229
  double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) * 1e-9;
 
230
 
 
231
  /* Dump both machine and human readable versions */
 
232
  printf("%s:%s:%u:%u:%.6f: took %.6f s for %u calls to %s of %u bytes.  ~%.3f MB/s\n", 
 
233
         variant + 1, ptest->name, count, loops, elapsed,
 
234
         elapsed, loops, ptest->name, count,
 
235
         (double)loops*count/elapsed/(1024*1024));
209
236
 
210
237
  return 0;
211
238
}