aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@axis.com>2014-12-02 10:50:39 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2014-12-09 07:14:00 -0500
commit308197b9474bcde2cafba2cd19bef46e0c0428bd (patch)
tree2b3bc8b3f22f549a66298c5ff4f30dea07dbabb7 /tools
parentcfa0bd52d0ba9b852f76c7b3f1055edd5e5c7846 (diff)
perf bench: Prepare memcpy for merge
The memset benchmark is largely copy-pasted from the memcpy benchmark. Prepare the memcpy file for merge with memset by extracting out a generic function. Signed-off-by: Rabin Vincent <rabin.vincent@axis.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Rabin Vincent <rabinv@axis.com> Link: http://lkml.kernel.org/r/1417535441-3965-1-git-send-email-rabin.vincent@axis.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/bench/mem-memcpy.c182
1 files changed, 104 insertions, 78 deletions
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index 2465141b554b..4a4493a7a1f8 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -52,16 +52,18 @@ typedef void *(*memcpy_t)(void *, const void *, size_t);
52struct routine { 52struct routine {
53 const char *name; 53 const char *name;
54 const char *desc; 54 const char *desc;
55 memcpy_t fn; 55 union {
56 memcpy_t memcpy;
57 } fn;
56}; 58};
57 59
58struct routine routines[] = { 60struct routine memcpy_routines[] = {
59 { "default", 61 { .name = "default",
60 "Default memcpy() provided by glibc", 62 .desc = "Default memcpy() provided by glibc",
61 memcpy }, 63 .fn.memcpy = memcpy },
62#ifdef HAVE_ARCH_X86_64_SUPPORT 64#ifdef HAVE_ARCH_X86_64_SUPPORT
63 65
64#define MEMCPY_FN(fn, name, desc) { name, desc, fn }, 66#define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn},
65#include "mem-memcpy-x86-64-asm-def.h" 67#include "mem-memcpy-x86-64-asm-def.h"
66#undef MEMCPY_FN 68#undef MEMCPY_FN
67 69
@@ -69,7 +71,7 @@ struct routine routines[] = {
69 71
70 { NULL, 72 { NULL,
71 NULL, 73 NULL,
72 NULL } 74 {NULL} }
73}; 75};
74 76
75static const char * const bench_mem_memcpy_usage[] = { 77static const char * const bench_mem_memcpy_usage[] = {
@@ -110,63 +112,6 @@ static double timeval2double(struct timeval *ts)
110 (double)ts->tv_usec / (double)1000000; 112 (double)ts->tv_usec / (double)1000000;
111} 113}
112 114
113static void alloc_mem(void **dst, void **src, size_t length)
114{
115 *dst = zalloc(length);
116 if (!*dst)
117 die("memory allocation failed - maybe length is too large?\n");
118
119 *src = zalloc(length);
120 if (!*src)
121 die("memory allocation failed - maybe length is too large?\n");
122 /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */
123 memset(*src, 0, length);
124}
125
126static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault)
127{
128 u64 cycle_start = 0ULL, cycle_end = 0ULL;
129 void *src = NULL, *dst = NULL;
130 int i;
131
132 alloc_mem(&src, &dst, len);
133
134 if (prefault)
135 fn(dst, src, len);
136
137 cycle_start = get_cycle();
138 for (i = 0; i < iterations; ++i)
139 fn(dst, src, len);
140 cycle_end = get_cycle();
141
142 free(src);
143 free(dst);
144 return cycle_end - cycle_start;
145}
146
147static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
148{
149 struct timeval tv_start, tv_end, tv_diff;
150 void *src = NULL, *dst = NULL;
151 int i;
152
153 alloc_mem(&src, &dst, len);
154
155 if (prefault)
156 fn(dst, src, len);
157
158 BUG_ON(gettimeofday(&tv_start, NULL));
159 for (i = 0; i < iterations; ++i)
160 fn(dst, src, len);
161 BUG_ON(gettimeofday(&tv_end, NULL));
162
163 timersub(&tv_end, &tv_start, &tv_diff);
164
165 free(src);
166 free(dst);
167 return (double)((double)len / timeval2double(&tv_diff));
168}
169
170#define pf (no_prefault ? 0 : 1) 115#define pf (no_prefault ? 0 : 1)
171 116
172#define print_bps(x) do { \ 117#define print_bps(x) do { \
@@ -180,8 +125,16 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
180 printf(" %14lf GB/Sec", x / K / K / K); \ 125 printf(" %14lf GB/Sec", x / K / K / K); \
181 } while (0) 126 } while (0)
182 127
183int bench_mem_memcpy(int argc, const char **argv, 128struct bench_mem_info {
184 const char *prefix __maybe_unused) 129 const struct routine *routines;
130 u64 (*do_cycle)(const struct routine *r, size_t len, bool prefault);
131 double (*do_gettimeofday)(const struct routine *r, size_t len, bool prefault);
132 const char *const *usage;
133};
134
135static int bench_mem_common(int argc, const char **argv,
136 const char *prefix __maybe_unused,
137 struct bench_mem_info *info)
185{ 138{
186 int i; 139 int i;
187 size_t len; 140 size_t len;
@@ -189,7 +142,7 @@ int bench_mem_memcpy(int argc, const char **argv,
189 u64 result_cycle[2]; 142 u64 result_cycle[2];
190 143
191 argc = parse_options(argc, argv, options, 144 argc = parse_options(argc, argv, options,
192 bench_mem_memcpy_usage, 0); 145 info->usage, 0);
193 146
194 if (no_prefault && only_prefault) { 147 if (no_prefault && only_prefault) {
195 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n"); 148 fprintf(stderr, "Invalid options: -o and -n are mutually exclusive\n");
@@ -213,16 +166,16 @@ int bench_mem_memcpy(int argc, const char **argv,
213 if (only_prefault && no_prefault) 166 if (only_prefault && no_prefault)
214 only_prefault = no_prefault = false; 167 only_prefault = no_prefault = false;
215 168
216 for (i = 0; routines[i].name; i++) { 169 for (i = 0; info->routines[i].name; i++) {
217 if (!strcmp(routines[i].name, routine)) 170 if (!strcmp(info->routines[i].name, routine))
218 break; 171 break;
219 } 172 }
220 if (!routines[i].name) { 173 if (!info->routines[i].name) {
221 printf("Unknown routine:%s\n", routine); 174 printf("Unknown routine:%s\n", routine);
222 printf("Available routines...\n"); 175 printf("Available routines...\n");
223 for (i = 0; routines[i].name; i++) { 176 for (i = 0; info->routines[i].name; i++) {
224 printf("\t%s ... %s\n", 177 printf("\t%s ... %s\n",
225 routines[i].name, routines[i].desc); 178 info->routines[i].name, info->routines[i].desc);
226 } 179 }
227 return 1; 180 return 1;
228 } 181 }
@@ -234,25 +187,25 @@ int bench_mem_memcpy(int argc, const char **argv,
234 /* show both of results */ 187 /* show both of results */
235 if (use_cycle) { 188 if (use_cycle) {
236 result_cycle[0] = 189 result_cycle[0] =
237 do_memcpy_cycle(routines[i].fn, len, false); 190 info->do_cycle(&info->routines[i], len, false);
238 result_cycle[1] = 191 result_cycle[1] =
239 do_memcpy_cycle(routines[i].fn, len, true); 192 info->do_cycle(&info->routines[i], len, true);
240 } else { 193 } else {
241 result_bps[0] = 194 result_bps[0] =
242 do_memcpy_gettimeofday(routines[i].fn, 195 info->do_gettimeofday(&info->routines[i],
243 len, false); 196 len, false);
244 result_bps[1] = 197 result_bps[1] =
245 do_memcpy_gettimeofday(routines[i].fn, 198 info->do_gettimeofday(&info->routines[i],
246 len, true); 199 len, true);
247 } 200 }
248 } else { 201 } else {
249 if (use_cycle) { 202 if (use_cycle) {
250 result_cycle[pf] = 203 result_cycle[pf] =
251 do_memcpy_cycle(routines[i].fn, 204 info->do_cycle(&info->routines[i],
252 len, only_prefault); 205 len, only_prefault);
253 } else { 206 } else {
254 result_bps[pf] = 207 result_bps[pf] =
255 do_memcpy_gettimeofday(routines[i].fn, 208 info->do_gettimeofday(&info->routines[i],
256 len, only_prefault); 209 len, only_prefault);
257 } 210 }
258 } 211 }
@@ -310,3 +263,76 @@ int bench_mem_memcpy(int argc, const char **argv,
310 263
311 return 0; 264 return 0;
312} 265}
266
267static void memcpy_alloc_mem(void **dst, void **src, size_t length)
268{
269 *dst = zalloc(length);
270 if (!*dst)
271 die("memory allocation failed - maybe length is too large?\n");
272
273 *src = zalloc(length);
274 if (!*src)
275 die("memory allocation failed - maybe length is too large?\n");
276 /* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */
277 memset(*src, 0, length);
278}
279
280static u64 do_memcpy_cycle(const struct routine *r, size_t len, bool prefault)
281{
282 u64 cycle_start = 0ULL, cycle_end = 0ULL;
283 void *src = NULL, *dst = NULL;
284 memcpy_t fn = r->fn.memcpy;
285 int i;
286
287 memcpy_alloc_mem(&src, &dst, len);
288
289 if (prefault)
290 fn(dst, src, len);
291
292 cycle_start = get_cycle();
293 for (i = 0; i < iterations; ++i)
294 fn(dst, src, len);
295 cycle_end = get_cycle();
296
297 free(src);
298 free(dst);
299 return cycle_end - cycle_start;
300}
301
302static double do_memcpy_gettimeofday(const struct routine *r, size_t len,
303 bool prefault)
304{
305 struct timeval tv_start, tv_end, tv_diff;
306 memcpy_t fn = r->fn.memcpy;
307 void *src = NULL, *dst = NULL;
308 int i;
309
310 memcpy_alloc_mem(&src, &dst, len);
311
312 if (prefault)
313 fn(dst, src, len);
314
315 BUG_ON(gettimeofday(&tv_start, NULL));
316 for (i = 0; i < iterations; ++i)
317 fn(dst, src, len);
318 BUG_ON(gettimeofday(&tv_end, NULL));
319
320 timersub(&tv_end, &tv_start, &tv_diff);
321
322 free(src);
323 free(dst);
324 return (double)((double)len / timeval2double(&tv_diff));
325}
326
327int bench_mem_memcpy(int argc, const char **argv,
328 const char *prefix __maybe_unused)
329{
330 struct bench_mem_info info = {
331 .routines = memcpy_routines,
332 .do_cycle = do_memcpy_cycle,
333 .do_gettimeofday = do_memcpy_gettimeofday,
334 .usage = bench_mem_memcpy_usage,
335 };
336
337 return bench_mem_common(argc, argv, prefix, &info);
338}