public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@elte.hu>
To: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
Cc: linux-kernel@vger.kernel.org,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Paul Mackerras <paulus@samba.org>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Ling Ma <ling.ma@intel.com>
Subject: Re: [PATCH 1/4] perf bench: Add new subsystem and new suite, bench/mem-memcpy.c
Date: Fri, 13 Nov 2009 10:46:50 +0100	[thread overview]
Message-ID: <20091113094650.GA1364@elte.hu> (raw)
In-Reply-To: <1258086186-32317-2-git-send-email-mitake@dcl.info.waseda.ac.jp>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=unknown-8bit, Size: 7140 bytes --]


* Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> wrote:

> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/time.h>
> +#include <assert.h>
> +
> +#define K 1024
> +static char *length_str = (char *)"1MB";
> +static char *routine = (char *)"default";

no cast is needed for string literals.

> +static int use_clockcycle = 0;

also, please use the vertical alignment initialization style used in 
other builtin-*.c tools.

> +
> +typedef unsigned long int clockcycle_t;

We dont do new typedefs in .c's generally. It should be put into a 
header - but i think using u64 would be good too.

> +
> +#ifdef x86_64
> +
> +static inline clockcycle_t get_clock(void)
> +{
> +	long int ret;
> +
> +	asm("rdtsc; shlq $32, %%rdx;"
> +	    "orq %%rdx, %%rax;"
> +	    "movq %%rax, %0;"
> +	    : "=r" (ret));
> +
> +	return ret;
> +}
> +
> +#endif /* x86_64 */

There's full rdtscll implementations in arch/x86/include/asm/tsc.h. They 
should either be included - or copied in part.

> +static const struct option options[] = {
> +	OPT_STRING('l', "length", &length_str, "1MB",
> +		    "Specify length of memory to copy. "
> +		    "available unit: B, MB, GB (upper and lower)"),
> +	OPT_STRING('r', "routine", &routine, "default",
> +		    "Specify routine to copy"),
> +#ifdef x86_64
> +	/*
> +	 * TODO: This should be expanded to any architecuture
> +	 * perf supports
> +	 */
> +	OPT_BOOLEAN('c', "clockcycle", &use_clockcycle,
> +		    "Use CPU's clock cycle for measurement"),
> +#endif /* x86_64 */

That #ifdef x86_64 looks quite ugly.

Also, why not use the 'cycles' perf event to retrieve cycles?

> +	OPT_END()
> +};
> +
> +struct routine {
> +	const char *name;
> +	void * (*fn)(void *dst, const void *src, size_t len);
> +	const char *desc;

We try to align structure definitions vertically too.

> +};
> +
> +struct routine routines[] = {
> +	{ "default",
> +	  memcpy,
> +	  "Default memcpy() provided by glibc" },
> +	{ NULL,
> +	  NULL,
> +	  NULL }

{ NULL, } would be equivalent i guess.

> +};
> +
> +static const char * const bench_mem_memcpy_usage[] = {
> +	"perf bench mem memcpy <options>",
> +	NULL
> +};
> +
> +static size_t str2length(char *_str)
> +{
> +	int i, unit = 1;
> +	char *str;
> +	size_t length = -1;
> +
> +	str = calloc(strlen(_str) + 1, sizeof(char));
> +	assert(str);
> +	strcpy(str, _str);
> +
> +	if (!isdigit(str[0]))
> +		goto err;
> +
> +	for (i = 1; i < (int)strlen(str); i++) {

if 'i' was of type unsigned long then the (int) cast wouldnt be needed i 
suspect?

> +		switch ((int)str[i]) {

is the cast to 'int' needed here?

> +		case 'B':
> +		case 'b':
> +			str[i] = '\0';
> +			break;
> +		case 'K':
> +		case 'k':
> +			if (str[i + 1] != 'B' && str[i + 1] != 'b')
> +				goto err;
> +			unit = K;
> +			str[i] = '\0';
> +			break;
> +		case 'M':
> +		case 'm':
> +			if (str[i + 1] != 'B' && str[i + 1] != 'b')
> +				goto err;
> +			unit = K * K;
> +			str[i] = '\0';
> +			break;
> +		case 'G':
> +		case 'g':
> +			if (str[i + 1] != 'B' && str[i + 1] != 'b')
> +				goto err;
> +			unit = K * K * K;
> +			str[i] = '\0';
> +			break;
> +		case '\0':	/* only specified figures */
> +			unit = 1;
> +			break;
> +		default:
> +			if (!isdigit(str[i]))
> +				goto err;
> +			break;
> +		}
> +	}
> +
> +	length = atoi(str) * unit;
> +	goto end;
> +
> +err:
> +	fprintf(stderr, "Invalid length:%s\n", str);
> +end:
> +	free(str);
> +	return length;
> +}

This should go until a utils/*.c helper file i suspect.

> +
> +static double timeval2double(struct timeval *ts)
> +{
> +	return (double)ts->tv_sec +
> +		(double)ts->tv_usec / (double)1000000;
> +}
> +
> +int bench_mem_memcpy(int argc, const char **argv,
> +		     const char *prefix __used)
> +{
> +	int i;
> +	void *dst, *src;
> +	struct timeval start, stop, diff;
> +	clockcycle_t clock_start = 0, clock_diff = 0;
> +	size_t length;
> +	double bps = 0.0;
> +
> +	argc = parse_options(argc, argv, options,
> +			     bench_mem_memcpy_usage, 0);
> +
> +	/*
> +	 * Caution!
> +	 * Without the statement
> +	 * 	gettimeofday(&diff, NULL);
> +	 * compiler warns (and build environment of perf regards it as error)
> +	 * like this,
> +	 * bench/mem-memcpy.c:93: error: ‘diff.tv_sec’ may be\
> +	 * used uninitialized in this function
> +	 * bench/mem-memcpy.c:93: error: ‘diff.tv_usec’ may be\
> +	 * used uninitialized in this function
> +	 *
> +	 * hmm...
> +	 */
> +	gettimeofday(&diff, NULL);

well, because 'gettimeofday' could fail in theory and then 'diff' 
remains uninitialized. Initializing it would solve that.

> +
> +	length = str2length(length_str);
> +	if ((int)length < 0)
> +		return 1;

str2length should return a proper type instead of forcing a (int) cast 
here.

> +
> +	for (i = 0; routines[i].name; i++)
> +		if (!strcmp(routines[i].name, routine))
> +			break;

Please use { } curly braces around all non-single-line statements. I.e. 
the above should be:

	for (i = 0; routines[i].name; i++) {
		if (!strcmp(routines[i].name, routine))
			break;
	}

It's a tiny bit longer but more robust.

> +	if (!routines[i].name) {
> +		printf("Unknown routine:%s\n", routine);
> +		printf("Available routines...\n");
> +		for (i = 0; routines[i].name; i++)
> +			printf("\t%s ... %s\n",
> +			       routines[i].name, routines[i].desc);
> +		return 1;
> +	}
> +
> +	dst = calloc(length, sizeof(char));
> +	assert(dst);
> +	src = calloc(length, sizeof(char));
> +	assert(src);

Please use BUG_ON() - we try to standardize on kernel code style in perf 
tooling.

> +
> +	if (bench_format == BENCH_FORMAT_DEFAULT)
> +		printf("# Copying %s Bytes from %p to %p ...\n\n",
> +		       length_str, src, dst);

curly braces needed.

> +
> +	if (use_clockcycle) {
> +		clock_start = get_clock();
> +	} else {
> +		gettimeofday(&start, NULL);
> +	}

these curly braces are not needed. (but this code would probably go away 
if the code used perf events to retrieve cycles or time of day elapsed 
time.)

> +
> +	routines[i].fn(dst, src, length);
> +
> +	if (use_clockcycle) {
> +		clock_diff = get_clock() - clock_start;
> +	} else {
> +		gettimeofday(&stop, NULL);
> +		timersub(&stop, &start, &diff);
> +		bps = (double)((double)length / timeval2double(&diff));
> +	}
> +
> +	switch (bench_format) {
> +	case BENCH_FORMAT_DEFAULT:
> +		if (use_clockcycle)
> +			printf(" %14lf Clock/Byte\n",
> +			       (double)clock_diff / (double)length);
> +		else
> +			if (bps < K)
> +				printf(" %14lf B/Sec\n", bps);
> +			else if (bps < K * K)
> +				printf(" %14lfd KB/Sec\n", bps / 1024);
> +			else if (bps < K * K * K)
> +				printf(" %14lf MB/Sec\n", bps / 1024 / 1024);
> +			else
> +				printf(" %14lf GB/Sec\n",
> +				       bps / 1024 / 1024 / 1024);

curly braces needed.

> +		break;
> +	case BENCH_FORMAT_SIMPLE:
> +		if (use_clockcycle)
> +			printf("%lf\n",
> +			       (double)clock_diff / (double)length);
> +		else
> +			printf("%lf\n", bps);
> +		break;
> +	default:
> +		/* reaching here is something disaster */
> +		fprintf(stderr, "Unknown format:%d\n", bench_format);

could use pr_err() here i guess.

> +		exit(1);
> +		break;
> +	}
> +
> +	return 0;
> +}

Thanks,

	Ingo

  reply	other threads:[~2009-11-13  9:47 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-13  4:23 [PATCH 0/4] perf bench: Add new subsystem "mem" and new suite "memcpy" Hitoshi Mitake
2009-11-13  4:23 ` [PATCH 1/4] perf bench: Add new subsystem and new suite, bench/mem-memcpy.c Hitoshi Mitake
2009-11-13  9:46   ` Ingo Molnar [this message]
2009-11-15  3:50     ` Hitoshi Mitake
2009-11-17 11:19     ` Hitoshi Mitake
2009-11-17 11:21       ` Ingo Molnar
2009-11-17 11:42         ` [PATCH 1/4] perf bench: Add mem-memcpy.c:memcpy() benchmark Hitoshi Mitake
2009-11-17 12:53           ` Ingo Molnar
2009-11-17 14:36             ` Hitoshi Mitake
2009-11-17 15:09               ` [PATCH v2 " Hitoshi Mitake
2009-11-17 15:09               ` [PATCH v2 2/4] perf bench: Modify bench.h for prototype of bench_mem_memcpy() Hitoshi Mitake
2009-11-17 15:09               ` [PATCH v2 3/4] perf bench: Modify builtin-bench.c for new subsystem "mem" Hitoshi Mitake
2009-11-17 15:09               ` [PATCH v2 4/4] perf bench: Modify Makefile for new source file mem-memcpy.c Hitoshi Mitake
2009-11-17 15:11                 ` Hitoshi Mitake
2009-11-17 15:15                   ` [PATCH v2 1/4] perf bench: Add mem-memcpy.c:memcpy() benchmark Hitoshi Mitake
2009-11-17 15:15                   ` [PATCH v2 2/4] perf bench: Modify bench.h for prototype of bench_mem_memcpy() Hitoshi Mitake
2009-11-17 15:15                   ` [PATCH v2 3/4] perf bench: Modify builtin-bench.c for new subsystem "mem" Hitoshi Mitake
2009-11-17 15:15                   ` [PATCH v2 4/4] perf bench: Modify Makefile for new source file mem-memcpy.c Hitoshi Mitake
2009-11-17 15:18                     ` Hitoshi Mitake
2009-11-17 15:20                       ` [PATCH v3 1/4] perf bench: Add mem-memcpy.c:memcpy() benchmark Hitoshi Mitake
2009-11-17 15:42                         ` [tip:perf/core] perf bench: Add memcpy() benchmark tip-bot for Hitoshi Mitake
2009-11-19  5:36                         ` [tip:perf/bench] " tip-bot for Hitoshi Mitake
2009-11-17 15:20                       ` [PATCH v3 2/4] perf bench: Modify bench.h for prototype of bench_mem_memcpy() Hitoshi Mitake
2009-11-17 15:20                       ` [PATCH v3 3/4] perf bench: Modify builtin-bench.c for new subsystem "mem" Hitoshi Mitake
2009-11-17 15:20                       ` [PATCH v3 4/4] perf bench: Modify Makefile for new source file mem-memcpy.c Hitoshi Mitake
2009-11-17 15:37                       ` [PATCH v2 " Ingo Molnar
2009-11-17 15:42                         ` Ingo Molnar
2009-11-18  1:42                           ` Hitoshi Mitake
2009-11-17 11:42         ` [PATCH 2/4] perf bench: Modify bench.h for prototype of bench_mem_memcpy() Hitoshi Mitake
2009-11-17 11:42         ` [PATCH 3/4] perf bench: Modify builtin-bench.c for new subsystem "mem" Hitoshi Mitake
2009-11-17 11:42         ` [PATCH 4/4] perf bench: Modify Makefile for new source file mem-memcpy.c Hitoshi Mitake
2009-11-13  4:23 ` [PATCH 2/4] perf bench: Modify bench/bench.h for new prototype: bench_mem_memcpy() Hitoshi Mitake
2009-11-13  4:23 ` [PATCH 3/4] perf bench: Modify builtin-bench.c for new subsystem "mem" Hitoshi Mitake
2009-11-13  4:23 ` [PATCH 4/4] perf bench: Modify Makefile to build " Hitoshi Mitake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20091113094650.GA1364@elte.hu \
    --to=mingo@elte.hu \
    --cc=a.p.zijlstra@chello.nl \
    --cc=fweisbec@gmail.com \
    --cc=ling.ma@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mitake@dcl.info.waseda.ac.jp \
    --cc=paulus@samba.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox