Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.13-rc5 297 lines 6.7 kB view raw
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 24static const char *length_str = "1MB"; 25static const char *routine = "default"; 26static int iterations = 1; 27static bool use_cycle; 28static int cycle_fd; 29static bool only_prefault; 30static bool no_prefault; 31 32static 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 49typedef void *(*memset_t)(void *, int, size_t); 50 51struct routine { 52 const char *name; 53 const char *desc; 54 memset_t fn; 55}; 56 57static 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 74static const char * const bench_mem_memset_usage[] = { 75 "perf bench mem memset <options>", 76 NULL 77}; 78 79static struct perf_event_attr cycle_attr = { 80 .type = PERF_TYPE_HARDWARE, 81 .config = PERF_COUNT_HW_CPU_CYCLES 82}; 83 84static 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 94static 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 105static double timeval2double(struct timeval *ts) 106{ 107 return (double)ts->tv_sec + 108 (double)ts->tv_usec / (double)1000000; 109} 110 111static 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 118static 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 138static 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 173int 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}