10 #include "../util/util.h"
11 #include "../util/parse-options.h"
12 #include "../util/header.h"
24 static const char *length_str =
"1MB";
25 static const char *
routine =
"default";
26 static int iterations = 1;
27 static bool use_cycle;
29 static bool only_prefault;
30 static bool no_prefault;
34 "Specify length of memory to copy. "
35 "Available units: B, KB, MB, GB and TB (upper and lower)"),
37 "Specify routine to copy"),
39 "repeat memcpy() invocation this number of times"),
41 "Use cycles event instead of gettimeofday() for measuring"),
43 "Show only the result with page faults before memcpy()"),
45 "Show only the result without page faults before memcpy()"),
49 typedef void *(*memcpy_t)(
void *,
const void *,
size_t);
59 "Default memcpy() provided by glibc",
63 #define MEMCPY_FN(fn, name, desc) { name, desc, fn },
74 static const char *
const bench_mem_memcpy_usage[] = {
75 "perf bench mem memcpy <options>",
84 static void init_cycle(
void)
88 if (cycle_fd < 0 && errno ==
ENOSYS)
89 die(
"No CONFIG_PERF_EVENTS=y kernel support configured?\n");
94 static u64 get_cycle(
void)
99 ret =
read(cycle_fd, &clk,
sizeof(
u64));
105 static double timeval2double(
struct timeval *
ts)
107 return (
double)ts->
tv_sec +
108 (double)ts->
tv_usec / (
double)1000000;
111 static void alloc_mem(
void **
dst,
void **
src,
size_t length)
115 die(
"memory allocation failed - maybe length is too large?\n");
119 die(
"memory allocation failed - maybe length is too large?\n");
122 static u64 do_memcpy_cycle(
memcpy_t fn,
size_t len,
bool prefault)
124 u64 cycle_start = 0ULL, cycle_end = 0ULL;
128 alloc_mem(&src, &dst, len);
133 cycle_start = get_cycle();
134 for (i = 0; i < iterations; ++
i)
136 cycle_end = get_cycle();
140 return cycle_end - cycle_start;
143 static double do_memcpy_gettimeofday(
memcpy_t fn,
size_t len,
bool prefault)
145 struct timeval tv_start, tv_end, tv_diff;
149 alloc_mem(&src, &dst, len);
155 for (i = 0; i < iterations; ++
i)
159 timersub(&tv_end, &tv_start, &tv_diff);
163 return (
double)((double)len / timeval2double(&tv_diff));
166 #define pf (no_prefault ? 0 : 1)
168 #define print_bps(x) do { \
170 printf(" %14lf B/Sec", x); \
171 else if (x < K * K) \
172 printf(" %14lfd KB/Sec", x / K); \
173 else if (x < K * K * K) \
174 printf(" %14lf MB/Sec", x / K / K); \
176 printf(" %14lf GB/Sec", x / K / K / K); \
184 double result_bps[2];
188 bench_mem_memcpy_usage, 0);
195 result_cycle[0] = result_cycle[1] = 0ULL;
196 result_bps[0] = result_bps[1] = 0.0;
199 fprintf(stderr,
"Invalid length:%s\n", length_str);
204 if (only_prefault && no_prefault)
205 only_prefault = no_prefault =
false;
207 for (i = 0; routines[
i].
name; i++) {
211 if (!routines[i].
name) {
213 printf(
"Available routines...\n");
214 for (i = 0; routines[
i].
name; i++) {
216 routines[i].name, routines[i].
desc);
222 printf(
"# Copying %s Bytes ...\n\n", length_str);
224 if (!only_prefault && !no_prefault) {
228 do_memcpy_cycle(routines[i].fn, len,
false);
230 do_memcpy_cycle(routines[i].fn, len,
true);
233 do_memcpy_gettimeofday(routines[i].fn,
236 do_memcpy_gettimeofday(routines[i].fn,
242 do_memcpy_cycle(routines[i].fn,
246 do_memcpy_gettimeofday(routines[i].fn,
253 if (!only_prefault && !no_prefault) {
255 printf(
" %14lf Cycle/Byte\n",
256 (
double)result_cycle[0]
258 printf(
" %14lf Cycle/Byte (with prefault)\n",
259 (
double)result_cycle[1]
265 printf(
" (with prefault)\n");
269 printf(
" %14lf Cycle/Byte",
270 (
double)result_cycle[
pf]
275 printf(
"%s\n", only_prefault ?
" (with prefault)" :
"");
279 if (!only_prefault && !no_prefault) {
282 (
double)result_cycle[0] / (
double)len,
283 (
double)result_cycle[1] / (
double)len);
286 result_bps[0], result_bps[1]);
290 printf(
"%lf\n", (
double)result_cycle[
pf]