perf: bench: prepare memcpy for merge
PATCH 1/3 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.
--- tools/perf/bench/mem-memcpy.c | 182 +++++++++++++++++++++++------------------ 1 file changed, 104 insertions(+), 78 deletions(-)
tools/perf/bench/mem-memcpy.c +104 -78
@@ -52,16 +52,18 @@ typedef void *(*memcpy_t)(void *, const void *, size_t);struct routine {const char *name;const char *desc; -memcpy_t fn; +union { +memcpy_t memcpy; + } fn; }; -struct routine routines[] = { - {"default" , -"Default memcpy() provided by glibc" , - memcpy }, +struct routine memcpy_routines[] = { + { .name ="default" , + .desc ="Default memcpy() provided by glibc" , + .fn.memcpy = memcpy }, #ifdef HAVE_ARCH_X86_64_SUPPORT -#define MEMCPY_FN(fn, name, desc) { name, desc, fn }, +#define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn}, #include "mem-memcpy-x86-64-asm-def.h" #undef MEMCPY_FN
@@ -69,7 +71,7 @@ struct routine routines[] = { {NULL ,NULL , - NULL } + {NULL} } }; static const char * const bench_mem_memcpy_usage[] = {
@@ -110,63 +112,6 @@ static double timeval2double(struct timeval *ts) (double )ts->tv_usec / (double )1000000 ; } -static void alloc_mem (void **dst,void **src,size_t length) -{ - *dst =zalloc (length); -if (!*dst) -die ("memory allocation failed - maybe length is too large?\n" ); - - *src =zalloc (length); -if (!*src) -die ("memory allocation failed - maybe length is too large?\n" ); -/* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */ -memset (*src,0 , length); -} - -static u64 do_memcpy_cycle (memcpy_t fn,size_t len,bool prefault) -{ -u64 cycle_start =0ULL , cycle_end =0ULL ; -void *src =NULL , *dst =NULL ; -int i; - -alloc_mem (&src, &dst, len); - -if (prefault) -fn (dst, src, len); - - cycle_start =get_cycle (); -for (i =0 ; i < iterations; ++i) -fn (dst, src, len); - cycle_end =get_cycle (); - -free (src); -free (dst); -return cycle_end - cycle_start; -} - -static double do_memcpy_gettimeofday (memcpy_t fn,size_t len,bool prefault) -{ -struct timeval tv_start, tv_end, tv_diff; -void *src =NULL , *dst =NULL ; -int i; - -alloc_mem (&src, &dst, len); - -if (prefault) -fn (dst, src, len); - -BUG_ON (gettimeofday (&tv_start,NULL )); -for (i =0 ; i < iterations; ++i) -fn (dst, src, len); -BUG_ON (gettimeofday (&tv_end,NULL )); - -timersub (&tv_end, &tv_start, &tv_diff); - -free (src); -free (dst); -return (double )((double )len /timeval2double (&tv_diff)); -} -#define pf (no_prefault ? 0 : 1)#define print_bps (x) do { \
@@ -180,8 +125,16 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)printf (" %14lf GB/Sec" , x /K /K /K ); \ }while (0 ) -int bench_mem_memcpy(int argc, const char **argv, - const char *prefix __maybe_unused) +struct bench_mem_info { +const struct routine *routines; +u64 (*do_cycle)(const struct routine *r,size_t len,bool prefault); +double (*do_gettimeofday)(const struct routine *r,size_t len,bool prefault); +const char *const *usage; +}; + +static int bench_mem_common (int argc,const char **argv, +const char *prefix__maybe_unused , +struct bench_mem_info *info) {int i;size_t len;
@@ -189,7 +142,7 @@ int bench_mem_memcpy(int argc, const char **argv,u64 result_cycle[2 ]; argc =parse_options (argc, argv, options, - bench_mem_memcpy_usage,0 ); + info->usage,0 );if (no_prefault && only_prefault) {fprintf (stderr,"Invalid options: -o and -n are mutually exclusive\n" );
@@ -213,16 +166,16 @@ int bench_mem_memcpy(int argc, const char **argv,if (only_prefault && no_prefault) only_prefault = no_prefault = false; -for (i =0 ; routines[i].name; i++) { -if (!strcmp (routines[i].name, routine)) +for (i =0 ; info->routines[i].name; i++) { +if (!strcmp (info->routines[i].name, routine))break ; } -if (!routines[i].name) { +if (!info->routines[i].name) {printf ("Unknown routine:%s\n" , routine);printf ("Available routines...\n" ); -for (i =0 ; routines[i].name; i++) { +for (i =0 ; info->routines[i].name; i++) {printf ("\t%s ... %s\n" , - routines[i].name, routines[i].desc); + info->routines[i].name, info->routines[i].desc); }return 1 ; }
@@ -234,25 +187,25 @@ int bench_mem_memcpy(int argc, const char **argv,/* show both of results */ if (use_cycle) { result_cycle[0 ] = -do_memcpy_cycle (routines[i].fn, len, false); + info->do_cycle (&info->routines[i], len, false); result_cycle[1 ] = -do_memcpy_cycle (routines[i].fn, len, true); + info->do_cycle (&info->routines[i], len, true); }else { result_bps[0 ] = -do_memcpy_gettimeofday (routines[i].fn, + info->do_gettimeofday (&info->routines[i], len, false); result_bps[1 ] = -do_memcpy_gettimeofday (routines[i].fn, + info->do_gettimeofday (&info->routines[i], len, true); } }else {if (use_cycle) { result_cycle[pf] = -do_memcpy_cycle (routines[i].fn, + info->do_cycle (&info->routines[i], len, only_prefault); }else { result_bps[pf] = -do_memcpy_gettimeofday (routines[i].fn, + info->do_gettimeofday (&info->routines[i], len, only_prefault); } }
@@ -310,3 +263,76 @@ int bench_mem_memcpy(int argc, const char **argv,return 0 ; } + +static void memcpy_alloc_mem (void **dst,void **src,size_t length) +{ + *dst =zalloc (length); +if (!*dst) +die ("memory allocation failed - maybe length is too large?\n" ); + + *src =zalloc (length); +if (!*src) +die ("memory allocation failed - maybe length is too large?\n" ); +/* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */ +memset (*src,0 , length); +} + +static u64 do_memcpy_cycle (const struct routine *r,size_t len,bool prefault) +{ +u64 cycle_start =0ULL , cycle_end =0ULL ; +void *src =NULL , *dst =NULL ; +memcpy_t fn = r->fn.memcpy; +int i; + +memcpy_alloc_mem (&src, &dst, len); + +if (prefault) +fn (dst, src, len); + + cycle_start =get_cycle (); +for (i =0 ; i < iterations; ++i) +fn (dst, src, len); + cycle_end =get_cycle (); + +free (src); +free (dst); +return cycle_end - cycle_start; +} + +static double do_memcpy_gettimeofday (const struct routine *r,size_t len, +bool prefault) +{ +struct timeval tv_start, tv_end, tv_diff; +memcpy_t fn = r->fn.memcpy; +void *src =NULL , *dst =NULL ; +int i; + +memcpy_alloc_mem (&src, &dst, len); + +if (prefault) +fn (dst, src, len); + +BUG_ON (gettimeofday (&tv_start,NULL )); +for (i =0 ; i < iterations; ++i) +fn (dst, src, len); +BUG_ON (gettimeofday (&tv_end,NULL )); + +timersub (&tv_end, &tv_start, &tv_diff); + +free (src); +free (dst); +return (double )((double )len /timeval2double (&tv_diff)); +} + +int bench_mem_memcpy (int argc,const char **argv, +const char *prefix__maybe_unused ) +{ +struct bench_mem_info info = { + .routines = memcpy_routines, + .do_cycle = do_memcpy_cycle, + .do_gettimeofday = do_memcpy_gettimeofday, + .usage = bench_mem_memcpy_usage, + }; + +return bench_mem_common (argc, argv, prefix, &info); +}
Signature · 1 line
1.7.10.4
PATCH 2/3 perf: bench: merge memset into memcpy
The memset benchmark is largely copy-pasted from the memcpy benchmark. Merge the two now that memcpy is made more generic.
--- tools/perf/Makefile.perf | 1 - tools/perf/bench/mem-memcpy.c | 90 ++++++++++++ tools/perf/bench/mem-memset.c | 304 ----------------------------------------- 3 files changed, 90 insertions(+), 305 deletions(-) delete mode 100644 tools/perf/bench/mem-memset.c
tools/perf/Makefile.perf +0 -1
@@ -458,7 +458,6 @@ BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o endif BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o -BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o
tools/perf/bench/mem-memcpy.c +90 -0
111 lines not on this page · raw message
tools/perf/bench/mem-memset.c deleted +0 -304
304 lines not on this page · raw message
Signature · 1 line
1.7.10.4
tip-bot for Rabin Vincent
merge bot[tip:perf/urgent] perf bench: Merge memset into memcpy
perf bench: Merge memset into memcpy
Commit-ID: 5bce1a5772cb52aad7e0466484ba07cfbfec2478 Gitweb: http://git.kernel.org/tip/5bce1a5772cb52aad7e0466484ba07cfbfec2478 Author: Rabin Vincent <[email protected]> AuthorDate: Tue, 2 Dec 2014 16:50:40 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 9 Dec 2014 09:14:05 -0300
perf bench: Merge memset into memcpy
The memset benchmark is largely copy-pasted from the memcpy benchmark. Merge the two now that memcpy is made more generic.
--- tools/perf/Makefile.perf | 1 - tools/perf/bench/mem-memcpy.c | 90 +++++++++++++ tools/perf/bench/mem-memset.c | 304 ------------------------------------------ 3 files changed, 90 insertions(+), 305 deletions(-)
tools/perf/Makefile.perf +0 -1
@@ -458,7 +458,6 @@ BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o endif BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o -BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o BUILTIN_OBJS += $(OUTPUT)bench/futex-hash.o BUILTIN_OBJS += $(OUTPUT)bench/futex-wake.o BUILTIN_OBJS += $(OUTPUT)bench/futex-requeue.o
tools/perf/bench/mem-memcpy.c +90 -0
111 lines not on this page · raw message
tools/perf/bench/mem-memset.c deleted +0 -304
304 lines not on this page · raw message
PATCH 3/3 perf: bench: fix memcpy/memset output
In reply to Rabin VincentThe memcpy and memset benchmarks return bogus results when iterations > 0 because the iterations value is not taken into account when calculating the final result:
$ perf bench mem memset --only-prefault --length 1GB --iterations 1 # Running 'mem/memset' benchmark: # Copying 1GB Bytes ...
20.798669 GB/Sec (with prefault) $ perf bench mem memset --only-prefault --length 1GB --iterations 10 # Running 'mem/memset' benchmark: # Copying 1GB Bytes ...
2.086576 GB/Sec (with prefault) $ perf bench mem memset --only-prefault --length 1GB --iterations 100 # Running 'mem/memset' benchmark: # Copying 1GB Bytes ...
212.840917 MB/Sec (with prefault)
Fix this.
--- tools/perf/bench/mem-memcpy.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
tools/perf/bench/mem-memcpy.c +10 -8
@@ -141,6 +141,7 @@ static int bench_mem_common(int argc, const char **argv, {int i;size_t len; +double totallen;double result_bps[2 ];u64 result_cycle[2 ];
@@ -156,6 +157,7 @@ static int bench_mem_common(int argc, const char **argv,init_cycle (); len = (size_t )perf_atoll ((char *)length_str); + totallen = (double )len * iterations; result_cycle[0 ] = result_cycle[1 ] =0ULL ; result_bps[0 ] = result_bps[1 ] =0.0 ;
@@ -219,10 +221,10 @@ static int bench_mem_common(int argc, const char **argv,if (use_cycle) {printf (" %14lf Cycle/Byte\n" , (double )result_cycle[0 ] - / (double )len); + / totallen);printf (" %14lf Cycle/Byte (with prefault)\n" , (double )result_cycle[1 ] - / (double )len); + / totallen); }else {print_bps (result_bps[0 ]);printf ("\n" );
@@ -233,7 +235,7 @@ static int bench_mem_common(int argc, const char **argv,if (use_cycle) {printf (" %14lf Cycle/Byte" , (double )result_cycle[pf] - / (double )len); + / totallen); }else print_bps (result_bps[pf]);
@@ -244,8 +246,8 @@ static int bench_mem_common(int argc, const char **argv,if (!only_prefault && !no_prefault) {if (use_cycle) {printf ("%lf %lf\n" , - (double )result_cycle[0 ] / (double )len, - (double )result_cycle[1 ] / (double )len); + (double )result_cycle[0 ] / totallen, + (double )result_cycle[1 ] / totallen); }else {printf ("%lf %lf\n" , result_bps[0 ], result_bps[1 ]);
@@ -253,7 +255,7 @@ static int bench_mem_common(int argc, const char **argv, }else {if (use_cycle) {printf ("%lf\n" , (double )result_cycle[pf] - / (double )len); + / totallen); }else printf ("%lf\n" , result_bps[pf]); }
@@ -324,7 +326,7 @@ static double do_memcpy_gettimeofday(const struct routine *r, size_t len,free (src);free (dst); -return (double )((double )len /timeval2double (&tv_diff)); +return (double )(((double )len * iterations) /timeval2double (&tv_diff)); } int bench_mem_memcpy(int argc, const char **argv,
@@ -389,7 +391,7 @@ static double do_memset_gettimeofday(const struct routine *r, size_t len,timersub (&tv_end, &tv_start, &tv_diff);free (dst); -return (double )((double )len /timeval2double (&tv_diff)); +return (double )(((double )len * iterations) /timeval2double (&tv_diff)); }static const char *const bench_mem_memset_usage[] = {
Signature · 1 line
1.7.10.4
Re: [PATCH 3/3] perf: bench: fix memcpy/memset output
Quoted 18 lines · Rabin Vincent
The memcpy and memset benchmarks return bogus results when iterations > 0 because the iterations value is not taken into account when calculating the final result:
$ perf bench mem memset --only-prefault --length 1GB --iterations 1 # Running 'mem/memset' benchmark: # Copying 1GB Bytes ...20.798669 GB/Sec (with prefault) $ perf bench mem memset --only-prefault --length 1GB --iterations 10 # Running 'mem/memset' benchmark: # Copying 1GB Bytes ...2.086576 GB/Sec (with prefault) $ perf bench mem memset --only-prefault --length 1GB --iterations 100 # Running 'mem/memset' benchmark: # Copying 1GB Bytes ...
Quoted 5 lines
212.840917 MB/Sec (with prefault)Fix this.
Signed-off-by Rabin Vincent <[email protected]>
Thanks,
Ingo
tip-bot for Rabin Vincent
merge bot[tip:perf/urgent] perf bench: Fix memcpy/memset output
In reply to Rabin Vincentperf bench: Fix memcpy/memset output
Commit-ID: 1182f883113483cefbc3be0178a2df2dc9ae8b77 Gitweb: http://git.kernel.org/tip/1182f883113483cefbc3be0178a2df2dc9ae8b77 Author: Rabin Vincent <[email protected]> AuthorDate: Tue, 2 Dec 2014 16:50:41 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 9 Dec 2014 09:14:08 -0300
perf bench: Fix memcpy/memset output
The memcpy and memset benchmarks return bogus results when iterations > 0 because the iterations value is not taken into account when calculating the final result:
$ perf bench mem memset --only-prefault --length 1GB --iterations 1 # Running 'mem/memset' benchmark: # Copying 1GB Bytes ...
20.798669 GB/Sec (with prefault) $ perf bench mem memset --only-prefault --length 1GB --iterations 10 # Running 'mem/memset' benchmark: # Copying 1GB Bytes ...
2.086576 GB/Sec (with prefault) $ perf bench mem memset --only-prefault --length 1GB --iterations 100 # Running 'mem/memset' benchmark: # Copying 1GB Bytes ...
212.840917 MB/Sec (with prefault)
Fix this.
--- tools/perf/bench/mem-memcpy.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
tools/perf/bench/mem-memcpy.c +10 -8
@@ -141,6 +141,7 @@ static int bench_mem_common(int argc, const char **argv, {int i;size_t len; +double totallen;double result_bps[2 ];u64 result_cycle[2 ];
@@ -156,6 +157,7 @@ static int bench_mem_common(int argc, const char **argv,init_cycle (); len = (size_t )perf_atoll ((char *)length_str); + totallen = (double )len * iterations; result_cycle[0 ] = result_cycle[1 ] =0ULL ; result_bps[0 ] = result_bps[1 ] =0.0 ;
@@ -219,10 +221,10 @@ static int bench_mem_common(int argc, const char **argv,if (use_cycle) {printf (" %14lf Cycle/Byte\n" , (double )result_cycle[0 ] - / (double )len); + / totallen);printf (" %14lf Cycle/Byte (with prefault)\n" , (double )result_cycle[1 ] - / (double )len); + / totallen); }else {print_bps (result_bps[0 ]);printf ("\n" );
@@ -233,7 +235,7 @@ static int bench_mem_common(int argc, const char **argv,if (use_cycle) {printf (" %14lf Cycle/Byte" , (double )result_cycle[pf] - / (double )len); + / totallen); }else print_bps (result_bps[pf]);
@@ -244,8 +246,8 @@ static int bench_mem_common(int argc, const char **argv,if (!only_prefault && !no_prefault) {if (use_cycle) {printf ("%lf %lf\n" , - (double )result_cycle[0 ] / (double )len, - (double )result_cycle[1 ] / (double )len); + (double )result_cycle[0 ] / totallen, + (double )result_cycle[1 ] / totallen); }else {printf ("%lf %lf\n" , result_bps[0 ], result_bps[1 ]);
@@ -253,7 +255,7 @@ static int bench_mem_common(int argc, const char **argv, }else {if (use_cycle) {printf ("%lf\n" , (double )result_cycle[pf] - / (double )len); + / totallen); }else printf ("%lf\n" , result_bps[pf]); }
@@ -324,7 +326,7 @@ static double do_memcpy_gettimeofday(const struct routine *r, size_t len,free (src);free (dst); -return (double )((double )len /timeval2double (&tv_diff)); +return (double )(((double )len * iterations) /timeval2double (&tv_diff)); } int bench_mem_memcpy(int argc, const char **argv,
@@ -389,7 +391,7 @@ static double do_memset_gettimeofday(const struct routine *r, size_t len,timersub (&tv_end, &tv_start, &tv_diff);free (dst); -return (double )((double )len /timeval2double (&tv_diff)); +return (double )(((double )len * iterations) /timeval2double (&tv_diff)); }static const char *const bench_mem_memset_usage[] = {
tip-bot for Rabin Vincent
merge bot[tip:perf/urgent] perf bench: Prepare memcpy for merge
In reply to Rabin Vincentperf bench: Prepare memcpy for merge
Commit-ID: 308197b9474bcde2cafba2cd19bef46e0c0428bd Gitweb: http://git.kernel.org/tip/308197b9474bcde2cafba2cd19bef46e0c0428bd Author: Rabin Vincent <[email protected]> AuthorDate: Tue, 2 Dec 2014 16:50:39 +0100 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 9 Dec 2014 09:14:00 -0300
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.
--- tools/perf/bench/mem-memcpy.c | 182 ++++++++++++++++++++++++------------------ 1 file changed, 104 insertions(+), 78 deletions(-)
tools/perf/bench/mem-memcpy.c +104 -78
@@ -52,16 +52,18 @@ typedef void *(*memcpy_t)(void *, const void *, size_t);struct routine {const char *name;const char *desc; -memcpy_t fn; +union { +memcpy_t memcpy; + } fn; }; -struct routine routines[] = { - {"default" , -"Default memcpy() provided by glibc" , - memcpy }, +struct routine memcpy_routines[] = { + { .name ="default" , + .desc ="Default memcpy() provided by glibc" , + .fn.memcpy = memcpy }, #ifdef HAVE_ARCH_X86_64_SUPPORT -#define MEMCPY_FN(fn, name, desc) { name, desc, fn }, +#define MEMCPY_FN(_fn, _name, _desc) {.name = _name, .desc = _desc, .fn.memcpy = _fn}, #include "mem-memcpy-x86-64-asm-def.h" #undef MEMCPY_FN
@@ -69,7 +71,7 @@ struct routine routines[] = { {NULL ,NULL , - NULL } + {NULL} } }; static const char * const bench_mem_memcpy_usage[] = {
@@ -110,63 +112,6 @@ static double timeval2double(struct timeval *ts) (double )ts->tv_usec / (double )1000000 ; } -static void alloc_mem (void **dst,void **src,size_t length) -{ - *dst =zalloc (length); -if (!*dst) -die ("memory allocation failed - maybe length is too large?\n" ); - - *src =zalloc (length); -if (!*src) -die ("memory allocation failed - maybe length is too large?\n" ); -/* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */ -memset (*src,0 , length); -} - -static u64 do_memcpy_cycle (memcpy_t fn,size_t len,bool prefault) -{ -u64 cycle_start =0ULL , cycle_end =0ULL ; -void *src =NULL , *dst =NULL ; -int i; - -alloc_mem (&src, &dst, len); - -if (prefault) -fn (dst, src, len); - - cycle_start =get_cycle (); -for (i =0 ; i < iterations; ++i) -fn (dst, src, len); - cycle_end =get_cycle (); - -free (src); -free (dst); -return cycle_end - cycle_start; -} - -static double do_memcpy_gettimeofday (memcpy_t fn,size_t len,bool prefault) -{ -struct timeval tv_start, tv_end, tv_diff; -void *src =NULL , *dst =NULL ; -int i; - -alloc_mem (&src, &dst, len); - -if (prefault) -fn (dst, src, len); - -BUG_ON (gettimeofday (&tv_start,NULL )); -for (i =0 ; i < iterations; ++i) -fn (dst, src, len); -BUG_ON (gettimeofday (&tv_end,NULL )); - -timersub (&tv_end, &tv_start, &tv_diff); - -free (src); -free (dst); -return (double )((double )len /timeval2double (&tv_diff)); -} -#define pf (no_prefault ? 0 : 1)#define print_bps (x) do { \
@@ -180,8 +125,16 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)printf (" %14lf GB/Sec" , x /K /K /K ); \ }while (0 ) -int bench_mem_memcpy(int argc, const char **argv, - const char *prefix __maybe_unused) +struct bench_mem_info { +const struct routine *routines; +u64 (*do_cycle)(const struct routine *r,size_t len,bool prefault); +double (*do_gettimeofday)(const struct routine *r,size_t len,bool prefault); +const char *const *usage; +}; + +static int bench_mem_common (int argc,const char **argv, +const char *prefix__maybe_unused , +struct bench_mem_info *info) {int i;size_t len;
@@ -189,7 +142,7 @@ int bench_mem_memcpy(int argc, const char **argv,u64 result_cycle[2 ]; argc =parse_options (argc, argv, options, - bench_mem_memcpy_usage,0 ); + info->usage,0 );if (no_prefault && only_prefault) {fprintf (stderr,"Invalid options: -o and -n are mutually exclusive\n" );
@@ -213,16 +166,16 @@ int bench_mem_memcpy(int argc, const char **argv,if (only_prefault && no_prefault) only_prefault = no_prefault = false; -for (i =0 ; routines[i].name; i++) { -if (!strcmp (routines[i].name, routine)) +for (i =0 ; info->routines[i].name; i++) { +if (!strcmp (info->routines[i].name, routine))break ; } -if (!routines[i].name) { +if (!info->routines[i].name) {printf ("Unknown routine:%s\n" , routine);printf ("Available routines...\n" ); -for (i =0 ; routines[i].name; i++) { +for (i =0 ; info->routines[i].name; i++) {printf ("\t%s ... %s\n" , - routines[i].name, routines[i].desc); + info->routines[i].name, info->routines[i].desc); }return 1 ; }
@@ -234,25 +187,25 @@ int bench_mem_memcpy(int argc, const char **argv,/* show both of results */ if (use_cycle) { result_cycle[0 ] = -do_memcpy_cycle (routines[i].fn, len, false); + info->do_cycle (&info->routines[i], len, false); result_cycle[1 ] = -do_memcpy_cycle (routines[i].fn, len, true); + info->do_cycle (&info->routines[i], len, true); }else { result_bps[0 ] = -do_memcpy_gettimeofday (routines[i].fn, + info->do_gettimeofday (&info->routines[i], len, false); result_bps[1 ] = -do_memcpy_gettimeofday (routines[i].fn, + info->do_gettimeofday (&info->routines[i], len, true); } }else {if (use_cycle) { result_cycle[pf] = -do_memcpy_cycle (routines[i].fn, + info->do_cycle (&info->routines[i], len, only_prefault); }else { result_bps[pf] = -do_memcpy_gettimeofday (routines[i].fn, + info->do_gettimeofday (&info->routines[i], len, only_prefault); } }
@@ -310,3 +263,76 @@ int bench_mem_memcpy(int argc, const char **argv,return 0 ; } + +static void memcpy_alloc_mem (void **dst,void **src,size_t length) +{ + *dst =zalloc (length); +if (!*dst) +die ("memory allocation failed - maybe length is too large?\n" ); + + *src =zalloc (length); +if (!*src) +die ("memory allocation failed - maybe length is too large?\n" ); +/* Make sure to always replace the zero pages even if MMAP_THRESH is crossed */ +memset (*src,0 , length); +} + +static u64 do_memcpy_cycle (const struct routine *r,size_t len,bool prefault) +{ +u64 cycle_start =0ULL , cycle_end =0ULL ; +void *src =NULL , *dst =NULL ; +memcpy_t fn = r->fn.memcpy; +int i; + +memcpy_alloc_mem (&src, &dst, len); + +if (prefault) +fn (dst, src, len); + + cycle_start =get_cycle (); +for (i =0 ; i < iterations; ++i) +fn (dst, src, len); + cycle_end =get_cycle (); + +free (src); +free (dst); +return cycle_end - cycle_start; +} + +static double do_memcpy_gettimeofday (const struct routine *r,size_t len, +bool prefault) +{ +struct timeval tv_start, tv_end, tv_diff; +memcpy_t fn = r->fn.memcpy; +void *src =NULL , *dst =NULL ; +int i; + +memcpy_alloc_mem (&src, &dst, len); + +if (prefault) +fn (dst, src, len); + +BUG_ON (gettimeofday (&tv_start,NULL )); +for (i =0 ; i < iterations; ++i) +fn (dst, src, len); +BUG_ON (gettimeofday (&tv_end,NULL )); + +timersub (&tv_end, &tv_start, &tv_diff); + +free (src); +free (dst); +return (double )((double )len /timeval2double (&tv_diff)); +} + +int bench_mem_memcpy (int argc,const char **argv, +const char *prefix__maybe_unused ) +{ +struct bench_mem_info info = { + .routines = memcpy_routines, + .do_cycle = do_memcpy_cycle, + .do_gettimeofday = do_memcpy_gettimeofday, + .usage = bench_mem_memcpy_usage, + }; + +return bench_mem_common (argc, argv, prefix, &info); +}