~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/bench/mem-memset.c

Version: ~ [ linux-5.10-rc1 ] ~ [ linux-5.9.1 ] ~ [ linux-5.8.16 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.72 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.152 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.202 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.240 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.240 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp