1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*
2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * mem-memcpy.c
3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * memcpy: Simple memory copy in various ways
5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng *
6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */
8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <ctype.h>
9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../perf.h"
11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../util/util.h"
12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../util/parse-options.h"
13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "../util/header.h"
14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "bench.h"
15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "mem-memcpy-arch.h"
16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdio.h>
18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <stdlib.h>
19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <string.h>
20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <sys/time.h>
21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <errno.h>
22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define K 1024
24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic const char	*length_str	= "1MB";
26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic const char	*routine	= "default";
27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic bool		use_clock;
28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic int		clock_fd;
29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic bool		only_prefault;
30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic bool		no_prefault;
31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic const struct option options[] = {
33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_STRING('l', "length", &length_str, "1MB",
34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    "Specify length of memory to copy. "
35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    "available unit: B, MB, GB (upper and lower)"),
36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_STRING('r', "routine", &routine, "default",
37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    "Specify routine to copy"),
38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_BOOLEAN('c', "clock", &use_clock,
39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    "Use CPU clock for measuring"),
40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_BOOLEAN('o', "only-prefault", &only_prefault,
41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    "Show only the result with page faults before memcpy()"),
42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_BOOLEAN('n', "no-prefault", &no_prefault,
43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		    "Show only the result without page faults before memcpy()"),
44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	OPT_END()
45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengtypedef void *(*memcpy_t)(void *, const void *, size_t);
48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct routine {
50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *name;
51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	const char *desc;
52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	memcpy_t fn;
53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct routine routines[] = {
56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	{ "default",
57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	  "Default memcpy() provided by glibc",
58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	  memcpy },
59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#ifdef ARCH_X86_64
60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define MEMCPY_FN(fn, name, desc) { name, desc, fn },
62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include "mem-memcpy-x86-64-asm-def.h"
63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#undef MEMCPY_FN
64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif
66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	{ NULL,
68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	  NULL,
69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	  NULL   }
70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic const char * const bench_mem_memcpy_usage[] = {
73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	"perf bench mem memcpy <options>",
74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	NULL
75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic struct perf_event_attr clock_attr = {
78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	.type		= PERF_TYPE_HARDWARE,
79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	.config		= PERF_COUNT_HW_CPU_CYCLES
80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng};
81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void init_clock(void)
83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (clock_fd < 0 && errno == ENOSYS)
87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	else
89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		BUG_ON(clock_fd < 0);
90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic u64 get_clock(void)
93e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
94e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int ret;
95e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	u64 clk;
96e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
97e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	ret = read(clock_fd, &clk, sizeof(u64));
98e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	BUG_ON(ret != sizeof(u64));
99e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
100e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return clk;
101e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
102e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
103e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic double timeval2double(struct timeval *ts)
104e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
105e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return (double)ts->tv_sec +
106e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		(double)ts->tv_usec / (double)1000000;
107e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
108e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
109e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic void alloc_mem(void **dst, void **src, size_t length)
110e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
111e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	*dst = zalloc(length);
112e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!dst)
113e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		die("memory allocation failed - maybe length is too large?\n");
114e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
115e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	*src = zalloc(length);
116e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!src)
117e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		die("memory allocation failed - maybe length is too large?\n");
118e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
119e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
120e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
121e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
122e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	u64 clock_start = 0ULL, clock_end = 0ULL;
123e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	void *src = NULL, *dst = NULL;
124e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
125e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	alloc_mem(&src, &dst, len);
126e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
127e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (prefault)
128e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		fn(dst, src, len);
129e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
130e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	clock_start = get_clock();
131e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fn(dst, src, len);
132e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	clock_end = get_clock();
133e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
134e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(src);
135e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(dst);
136e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return clock_end - clock_start;
137e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
138e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
139e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
140e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
141e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	struct timeval tv_start, tv_end, tv_diff;
142e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	void *src = NULL, *dst = NULL;
143e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
144e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	alloc_mem(&src, &dst, len);
145e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
146e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (prefault)
147e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		fn(dst, src, len);
148e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
149e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	gettimeofday(&tv_start, NULL);
150e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	fn(dst, src, len);
151e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	gettimeofday(&tv_end, NULL);
152e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
153e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	timersub(&tv_end, &tv_start, &tv_diff);
154e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
155e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(src);
156e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	free(dst);
157e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return (double)((double)len / timeval2double(&tv_diff));
158e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
159e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
160e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define pf (no_prefault ? 0 : 1)
161e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
162e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define print_bps(x) do {					\
163e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (x < K)					\
164e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printf(" %14lf B/Sec", x);		\
165e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else if (x < K * K)				\
166e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printf(" %14lfd KB/Sec", x / K);	\
167e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else if (x < K * K * K)				\
168e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printf(" %14lf MB/Sec", x / K / K);	\
169e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		else						\
170e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printf(" %14lf GB/Sec", x / K / K / K); \
171e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} while (0)
172e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
173e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengint bench_mem_memcpy(int argc, const char **argv,
174e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		     const char *prefix __used)
175e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng{
176e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	int i;
177e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	size_t len;
178e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	double result_bps[2];
179e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	u64 result_clock[2];
180e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
181e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	argc = parse_options(argc, argv, options,
182e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			     bench_mem_memcpy_usage, 0);
183e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
184e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (use_clock)
185e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		init_clock();
186e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
187e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	len = (size_t)perf_atoll((char *)length_str);
188e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
189e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	result_clock[0] = result_clock[1] = 0ULL;
190e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	result_bps[0] = result_bps[1] = 0.0;
191e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
192e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if ((s64)len <= 0) {
193e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		fprintf(stderr, "Invalid length:%s\n", length_str);
194e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return 1;
195e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
196e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
197e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	/* same to without specifying either of prefault and no-prefault */
198e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (only_prefault && no_prefault)
199e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		only_prefault = no_prefault = false;
200e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
201e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	for (i = 0; routines[i].name; i++) {
202e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!strcmp(routines[i].name, routine))
203e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			break;
204e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
205e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!routines[i].name) {
206e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printf("Unknown routine:%s\n", routine);
207e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printf("Available routines...\n");
208e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		for (i = 0; routines[i].name; i++) {
209e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printf("\t%s ... %s\n",
210e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			       routines[i].name, routines[i].desc);
211e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
212e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		return 1;
213e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
214e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
215e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (bench_format == BENCH_FORMAT_DEFAULT)
216e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		printf("# Copying %s Bytes ...\n\n", length_str);
217e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
218e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	if (!only_prefault && !no_prefault) {
219e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* show both of results */
220e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (use_clock) {
221e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			result_clock[0] =
222e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				do_memcpy_clock(routines[i].fn, len, false);
223e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			result_clock[1] =
224e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				do_memcpy_clock(routines[i].fn, len, true);
225e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else {
226e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			result_bps[0] =
227e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				do_memcpy_gettimeofday(routines[i].fn,
228e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						len, false);
229e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			result_bps[1] =
230e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				do_memcpy_gettimeofday(routines[i].fn,
231e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						len, true);
232e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
233e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	} else {
234e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (use_clock) {
235e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			result_clock[pf] =
236e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				do_memcpy_clock(routines[i].fn,
237e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						len, only_prefault);
238e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else {
239e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			result_bps[pf] =
240e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				do_memcpy_gettimeofday(routines[i].fn,
241e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng						len, only_prefault);
242e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
243e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
244e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
245e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	switch (bench_format) {
246e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	case BENCH_FORMAT_DEFAULT:
247e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!only_prefault && !no_prefault) {
248e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (use_clock) {
249e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				printf(" %14lf Clock/Byte\n",
250e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					(double)result_clock[0]
251e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					/ (double)len);
252e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				printf(" %14lf Clock/Byte (with prefault)\n",
253e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					(double)result_clock[1]
254e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					/ (double)len);
255e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else {
256e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				print_bps(result_bps[0]);
257e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				printf("\n");
258e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				print_bps(result_bps[1]);
259e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				printf(" (with prefault)\n");
260e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
261e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else {
262e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (use_clock) {
263e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				printf(" %14lf Clock/Byte",
264e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					(double)result_clock[pf]
265e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					/ (double)len);
266e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else
267e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				print_bps(result_bps[pf]);
268e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
269e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			printf("%s\n", only_prefault ? " (with prefault)" : "");
270e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
271e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
272e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	case BENCH_FORMAT_SIMPLE:
273e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		if (!only_prefault && !no_prefault) {
274e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (use_clock) {
275e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				printf("%lf %lf\n",
276e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					(double)result_clock[0] / (double)len,
277e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					(double)result_clock[1] / (double)len);
278e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else {
279e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				printf("%lf %lf\n",
280e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					result_bps[0], result_bps[1]);
281e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			}
282e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		} else {
283e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			if (use_clock) {
284e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				printf("%lf\n", (double)result_clock[pf]
285e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng					/ (double)len);
286e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng			} else
287e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng				printf("%lf\n", result_bps[pf]);
288e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		}
289e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
290e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	default:
291e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		/* reaching this means there's some disaster: */
292e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		die("unknown format: %d\n", bench_format);
293e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng		break;
294e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	}
295e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng
296e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng	return 0;
297e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}
298