All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: Laurent Vivier <laurent@vivier.eu>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] qemu-nbd: add statistics
Date: Wed, 13 Oct 2010 15:45:49 +0200	[thread overview]
Message-ID: <4CB5B80D.5020600@redhat.com> (raw)
In-Reply-To: <1286306151-17056-1-git-send-email-laurent@vivier.eu>

Hi Laurent,

Am 05.10.2010 21:15, schrieb Laurent Vivier:
> During qemu-nbd run, I/O statistics can be now displayed using
> the option '-a N' where N is the number of seconds between each
> collect.
> 
> The statistics diplayed are : I/O per second, kilobytes read per second,
> kilobytes written per second, and the maximum values for each of them.
> 
> Example:
> 
> ...
> 0 io/s, 0 R kB/s 0 W kB/s (29 io/s, 59 R kB/s, 0 W kB/s)
> 123 io/s, 247 R kB/s 0 W kB/s (123 io/s, 247 R kB/s, 0 W kB/s)
> 145 io/s, 290 R kB/s 0 W kB/s (145 io/s, 290 R kB/s, 0 W kB/s)
> 383 io/s, 767 R kB/s 0 W kB/s (383 io/s, 767 R kB/s, 0 W kB/s)
> 273 io/s, 547 R kB/s 0 W kB/s (383 io/s, 767 R kB/s, 0 W kB/s)
> 2221 io/s, 4443 R kB/s 0 W kB/s (2221 io/s, 4443 R kB/s, 0 W kB/s)
> 0 io/s, 0 R kB/s 0 W kB/s (2221 io/s, 4443 R kB/s, 0 W kB/s)
> 0 io/s, 0 R kB/s 0 W kB/s (2221 io/s, 4443 R kB/s, 0 W kB/s)
> ...
> 
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  nbd.c      |   10 ++++++++
>  nbd.h      |    4 +++
>  qemu-nbd.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 80 insertions(+), 2 deletions(-)
> 
> diff --git a/nbd.c b/nbd.c
> index 4bf2eb7..730c514 100644
> --- a/nbd.c
> +++ b/nbd.c
> @@ -65,6 +65,12 @@
>  
>  #define NBD_OPT_EXPORT_NAME	(1 << 0)
>  
> +/* for I/O statistics */
> +
> +uint64_t nbd_stats_io = 0;
> +uint64_t nbd_stats_read = 0;
> +uint64_t nbd_stats_written = 0;
> +
>  /* That's all folks */
>  
>  #define read_sync(fd, buffer, size) nbd_wr_sync(fd, buffer, size, true)
> @@ -687,6 +693,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
>  	switch (request.type) {
>  	case NBD_CMD_READ:
>  		TRACE("Request type is READ");
> +		nbd_stats_io++;
> +		nbd_stats_read += request.len;
>  
>  		if (bdrv_read(bs, (request.from + dev_offset) / 512,
>  			      data + NBD_REPLY_SIZE,
> @@ -721,6 +729,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset,
>  		break;
>  	case NBD_CMD_WRITE:
>  		TRACE("Request type is WRITE");
> +		nbd_stats_io++;
> +		nbd_stats_written += request.len;
>  
>  		TRACE("Reading %u byte(s)", request.len);
>  
> diff --git a/nbd.h b/nbd.h
> index fc3a594..2d9457b 100644
> --- a/nbd.h
> +++ b/nbd.h
> @@ -44,6 +44,10 @@ enum {
>  
>  #define NBD_DEFAULT_PORT	10809
>  
> +extern uint64_t nbd_stats_io;
> +extern uint64_t nbd_stats_read;
> +extern uint64_t nbd_stats_written;
> +
>  size_t nbd_wr_sync(int fd, void *buffer, size_t size, bool do_read);
>  int tcp_socket_outgoing(const char *address, uint16_t port);
>  int tcp_socket_incoming(const char *address, uint16_t port);
> diff --git a/qemu-nbd.c b/qemu-nbd.c
> index 99f1d22..7626c37 100644
> --- a/qemu-nbd.c
> +++ b/qemu-nbd.c
> @@ -37,6 +37,7 @@
>  #define NBD_BUFFER_SIZE (1024*1024)
>  
>  static int verbose;
> +static int delay = 0;

I'd prefer calling this nbd_stat_delay or something. delay is relatively
unspecific for a global variable.

>  static void usage(const char *name)
>  {
> @@ -44,6 +45,7 @@ static void usage(const char *name)
>  "Usage: %s [OPTIONS] FILE\n"
>  "QEMU Disk Network Block Device Server\n"
>  "\n"
> +"  -a, --stats=N        display statistics every N seconds\n"
>  "  -p, --port=PORT      port to listen on (default `%d')\n"
>  "  -o, --offset=OFFSET  offset into the image\n"
>  "  -b, --bind=IFACE     interface to bind to (default `0.0.0.0')\n"
> @@ -180,6 +182,49 @@ static void show_parts(const char *device)
>      }
>  }
>  
> +static void nbd_stats(void)
> +{
> +	static struct timespec prev;
> +	static int first = 1;
> +	static uint64_t max_read = 0, max_written = 0, max_io = 0;
> +	struct timespec current;
> +	long seconds;
> +	uint64_t current_read = 0, current_written = 0, current_io = 0;
> +
> +	clock_gettime(CLOCK_MONOTONIC, &current);

I think there was a discussion recently that clock_gettime doesn't exist
everywhere. Is there a specific reason why qemu_gettimeofday() isn't
good enough here?

> +	if (first) {
> +		first = 0;
> +		prev = current;
> +		return;
> +	}
> +
> +	seconds = (current.tv_sec - prev.tv_sec) * 1000 +
> +                  (current.tv_nsec - prev.tv_nsec) / 1000000;

Despite the name of the variable, this looks like milliseconds.

> +
> +	if (seconds < delay * 1000)
> +		return;
> +
> +	current_io = nbd_stats_io * 1000 / seconds;
> +	if (current_io > max_io)
> +		max_io = current_io;
> +	current_read = nbd_stats_read * 1000 / seconds / 1024;
> +	if (current_read > max_read)
> +		max_read = current_read;
> +	current_written = nbd_stats_written * 1000 / seconds / 1024;
> +	if (current_written > max_written)
> +		max_written = current_written;
> +
> +	printf("%"PRIu64" io/s, %"PRIu64" R kB/s %"PRIu64" W kB/s "
> +               "(%"PRIu64" io/s, %"PRIu64" R kB/s, %"PRIu64" W kB/s)\n",

Maybe add a "max: " message in the brackets, so that users know what
this is supposed to mean?

> +		current_io, current_read, current_written,
> +		max_io, max_read, max_written);
> +
> +	nbd_stats_io = 0;
> +	nbd_stats_read = 0;
> +	nbd_stats_written = 0;
> +	prev = current;
> +}

Please use four spaces instead of tabs for indentation.

> +
>  int main(int argc, char **argv)
>  {
>      BlockDriverState *bs;
> @@ -195,11 +240,12 @@ int main(int argc, char **argv)
>      char *device = NULL;
>      char *socket = NULL;
>      char sockpath[128];
> -    const char *sopt = "hVb:o:p:rsnP:c:dvk:e:t";
> +    const char *sopt = "hVb:o:a:p:rsnP:c:dvk:e:t";
>      struct option lopt[] = {
>          { "help", 0, NULL, 'h' },
>          { "version", 0, NULL, 'V' },
>          { "bind", 1, NULL, 'b' },
> +        { "stats", 1, NULL, 'a' },
>          { "port", 1, NULL, 'p' },
>          { "socket", 1, NULL, 'k' },
>          { "offset", 1, NULL, 'o' },
> @@ -243,6 +289,15 @@ int main(int argc, char **argv)
>          case 'b':
>              bindto = optarg;
>              break;
> +        case 'a':
> +            delay = strtol(optarg, &end, 0);
> +            if (*end) {
> +                errx(EXIT_FAILURE, "Invalid statistics delay `%s'", optarg);
> +            }
> +            if (delay < 0) {
> +                errx(EXIT_FAILURE, "Statisctics delay must be positive `%s'", optarg);

Typo in the message ("Statisctics")

> +            }
> +            break;
>          case 'p':
>              li = strtol(optarg, &end, 0);
>              if (*end) {
> @@ -456,7 +511,16 @@ int main(int argc, char **argv)
>          for (i = 0; i < nb_fds; i++)
>              FD_SET(sharing_fds[i], &fds);
>  
> -        ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
> +        if (delay) {
> +            struct timeval timeout;
> +
> +            nbd_stats();
> +            timeout.tv_sec = delay;
> +            timeout.tv_usec = 0;
> +            ret = select(max_fd + 1, &fds, NULL, NULL, &timeout);
> +        } else {
> +            ret = select(max_fd + 1, &fds, NULL, NULL, NULL);
> +        }

With some bad luck we can end up with almost 2*delay between two outputs
(request is processed with seconds = 1000 * delay - epsilon and then we
wait another delay seconds). I'm not sure if we really care, though.

Kevin

      reply	other threads:[~2010-10-13 13:51 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-05 19:15 [Qemu-devel] [PATCH] qemu-nbd: add statistics Laurent Vivier
2010-10-13 13:45 ` Kevin Wolf [this message]

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=4CB5B80D.5020600@redhat.com \
    --to=kwolf@redhat.com \
    --cc=laurent@vivier.eu \
    --cc=qemu-devel@nongnu.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.