From: Harald Schieche <rehs@gmx.de>
To: qemu-devel@nongnu.org
Cc: Stefan Weil <sw@weilnetz.de>, Harald Schieche <rehs@gmx.de>,
Stefan Hajnoczi <stefanha@redhat.com>,
Anthony Liguori <aliguori@amazon.com>
Subject: [Qemu-devel] [PATCH] Simple performance logging and network limiting based on trace option
Date: Tue, 28 Oct 2014 16:33:42 +0100 [thread overview]
Message-ID: <1414510422-8277-1-git-send-email-rehs@gmx.de> (raw)
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 475cf74..3c5cc71 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -1031,6 +1031,27 @@ static int aio_worker(void *arg)
return ret;
}
+static void log_guest_storage_performance(void)
+{
+ /*
+ * Performance logging isn't specified yet.
+ * Therefore we're using existing tracing.
+ */
+ static int64_t logged_clock;
+ static int64_t counter;
+ int64_t clock = get_clock();
+
+ counter++;
+ if (clock - logged_clock >= 1000000000LL) {
+ if (logged_clock > 0) { /* don't log first event */
+ trace_log_guest_storage_performance
+ (counter, (clock - logged_clock) / 1000000000LL);
+ }
+ counter = 0;
+ logged_clock = clock;
+ }
+}
+
static int paio_submit_co(BlockDriverState *bs, int fd,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
int type)
@@ -1051,6 +1072,7 @@ static int paio_submit_co(BlockDriverState *bs, int fd,
assert(qiov->size == acb->aio_nbytes);
}
+ log_guest_storage_performance();
trace_paio_submit_co(sector_num, nb_sectors, type);
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
return thread_pool_submit_co(pool, aio_worker, acb);
@@ -1076,6 +1098,7 @@ static BlockAIOCB *paio_submit(BlockDriverState *bs, int fd,
assert(qiov->size == acb->aio_nbytes);
}
+ log_guest_storage_performance();
trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
diff --git a/block/raw-win32.c b/block/raw-win32.c
index 7b58881..8cb2743 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -138,6 +138,27 @@ static int aio_worker(void *arg)
return ret;
}
+static void log_guest_storage_performance(void)
+{
+ /*
+ * Performance logging isn't specified yet.
+ * Therefore we're using existing tracing.
+ */
+ static int64_t logged_clock;
+ static int64_t counter;
+ int64_t clock = get_clock();
+
+ counter++;
+ if (clock - logged_clock >= 1000000000LL) {
+ if (logged_clock > 0) { /* don't log first event */
+ trace_log_guest_storage_performance
+ (counter, (clock - logged_clock) / 1000000000LL);
+ }
+ counter = 0;
+ logged_clock = clock;
+ }
+}
+
static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
BlockCompletionFunc *cb, void *opaque, int type)
@@ -156,6 +177,7 @@ static BlockAIOCB *paio_submit(BlockDriverState *bs, HANDLE hfile,
acb->aio_nbytes = nb_sectors * 512;
acb->aio_offset = sector_num * 512;
+ log_guest_storage_performance();
trace_paio_submit(acb, opaque, sector_num, nb_sectors, type);
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
return thread_pool_submit_aio(pool, aio_worker, acb, cb, opaque);
diff --git a/include/net/queue.h b/include/net/queue.h
index fc02b33..d8ea589 100644
--- a/include/net/queue.h
+++ b/include/net/queue.h
@@ -34,6 +34,8 @@ typedef void (NetPacketSent) (NetClientState *sender, ssize_t ret);
#define QEMU_NET_PACKET_FLAG_NONE 0
#define QEMU_NET_PACKET_FLAG_RAW (1<<0)
+void qemu_net_set_bandwidth_limit(int64_t limit);
+
NetQueue *qemu_new_net_queue(void *opaque);
void qemu_del_net_queue(NetQueue *queue);
diff --git a/net/queue.c b/net/queue.c
index f948318..2b0fef7 100644
--- a/net/queue.c
+++ b/net/queue.c
@@ -23,7 +23,9 @@
#include "net/queue.h"
#include "qemu/queue.h"
+#include "qemu/timer.h"
#include "net/net.h"
+#include "trace.h"
/* The delivery handler may only return zero if it will call
* qemu_net_queue_flush() when it determines that it is once again able
@@ -58,6 +60,15 @@ struct NetQueue {
unsigned delivering : 1;
};
+static int64_t bandwidth_limit; /* maximum number of bits per second */
+
+void qemu_net_set_bandwidth_limit(int64_t limit)
+{
+ bandwidth_limit = limit;
+ trace_qemu_net_set_bandwidth_limit(limit);
+}
+
+
NetQueue *qemu_new_net_queue(void *opaque)
{
NetQueue *queue;
@@ -175,6 +186,48 @@ static ssize_t qemu_net_queue_deliver_iov(NetQueue *queue,
return ret;
}
+static int64_t limit_network_performance(int64_t start_clock,
+ int64_t bytes)
+{
+ int64_t clock = get_clock();
+ int64_t sleep_usecs = 0;
+ if (bandwidth_limit > 0) {
+ sleep_usecs = (bytes * 8 * 1000000LL) / bandwidth_limit -
+ (clock - start_clock) / 1000LL;
+ }
+ if (sleep_usecs > 0) {
+ usleep(sleep_usecs);
+ clock = get_clock();
+ }
+
+ return clock;
+}
+
+static void log_and_limit_network_performance(size_t size)
+{
+ /*
+ * Performance logging isn't specified yet.
+ * Therefore we're using existing tracing.
+ */
+ static int64_t logged_clock;
+ static int64_t packets;
+ static int64_t bytes;
+ int64_t clock = 0;
+
+ packets++;
+ bytes = bytes + size;
+ clock = limit_network_performance(logged_clock, bytes);
+ if (clock - logged_clock >= 1000000000LL) {
+ if (logged_clock > 0) { /* don't log first event */
+ trace_log_network_performance
+ (packets, bytes*8, (clock - logged_clock) / 1000000000LL);
+ }
+ packets = 0;
+ bytes = 0;
+ logged_clock = clock;
+ }
+}
+
ssize_t qemu_net_queue_send(NetQueue *queue,
NetClientState *sender,
unsigned flags,
@@ -184,6 +237,7 @@ ssize_t qemu_net_queue_send(NetQueue *queue,
{
ssize_t ret;
+ log_and_limit_network_performance(size) ;
if (queue->delivering || !qemu_can_send_packet(sender)) {
qemu_net_queue_append(queue, sender, flags, data, size, sent_cb);
return 0;
diff --git a/qemu-options.hx b/qemu-options.hx
index 22cf3b9..35aee69 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1916,6 +1916,19 @@ override the default configuration (@option{-net nic -net user}) which
is activated if no @option{-net} options are provided.
ETEXI
+DEF("bandwidth", HAS_ARG, QEMU_OPTION_bandwidth,
+ "-bandwidth [limit=]n\n"
+ " set the maximum bandwidth[bits per second] to 'n' (default=0, no limit)\n",
+ QEMU_ARCH_ALL)
+STEXI
+@item -bandwidth [limit=]@var{n}]
+@findex -bandwidth
+Limit the network bandwith (bits per second).
+If the limit is reached, Qemu will sleep.
+0, the default means no limit.
+This option is active if trace-event "log_network_performance" is active
+ETEXI
+
STEXI
@end table
ETEXI
diff --git a/trace-events b/trace-events
index 6c3a400..04b2d36 100644
--- a/trace-events
+++ b/trace-events
@@ -134,6 +134,7 @@ thread_pool_cancel(void *req, void *opaque) "req %p opaque %p"
# block/raw-posix.c
paio_submit_co(int64_t sector_num, int nb_sectors, int type) "sector_num %"PRId64" nb_sectors %d type %d"
paio_submit(void *acb, void *opaque, int64_t sector_num, int nb_sectors, int type) "acb %p opaque %p sector_num %"PRId64" nb_sectors %d type %d"
+log_guest_storage_performance(int64_t counter, int64_t seconds) "counter %"PRId64" seconds %"PRId64"
# ioport.c
cpu_in(unsigned int addr, unsigned int val) "addr %#x value %u"
@@ -1378,3 +1379,7 @@ i8257_unregistered_dma(int nchan, int dma_pos, int dma_len) "unregistered DMA ch
cpu_set_state(int cpu_index, uint8_t state) "setting cpu %d state to %" PRIu8
cpu_halt(int cpu_index) "halting cpu %d"
cpu_unhalt(int cpu_index) "unhalting cpu %d"
+
+# net/queue.c
+qemu_net_set_bandwidth_limit(int64_t limit) "bits per second %"PRId64"
+log_network_performance(int64_t packets, int64_t bits, int64_t seconds) "packets %"PRId64" "bits %"PRId64" seconds %"PRId64"
diff --git a/vl.c b/vl.c
index 2f81384..02a91e1 100644
--- a/vl.c
+++ b/vl.c
@@ -1309,6 +1309,30 @@ static void smp_parse(QemuOpts *opts)
}
+static QemuOptsList qemu_bandwidth_opts = {
+ .name = "bandwidth-opts",
+ .implied_opt_name = "limit",
+ .merge_lists = true,
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_bandwidth_opts.head),
+ .desc = {
+ {
+ .name = "limit",
+ .type = QEMU_OPT_NUMBER,
+ },
+ { /*End of list */ }
+ },
+};
+
+static void bandwidth_parse(QemuOpts *opts)
+{
+ if (opts) {
+
+ qemu_net_set_bandwidth_limit(qemu_opt_get_number(opts, "limit", 0));
+
+ }
+
+}
+
static void realtime_init(void)
{
if (enable_mlock) {
@@ -2758,6 +2782,7 @@ int main(int argc, char **argv, char **envp)
qemu_add_opts(&qemu_machine_opts);
qemu_add_opts(&qemu_mem_opts);
qemu_add_opts(&qemu_smp_opts);
+ qemu_add_opts(&qemu_bandwidth_opts);
qemu_add_opts(&qemu_boot_opts);
qemu_add_opts(&qemu_sandbox_opts);
qemu_add_opts(&qemu_add_fd_opts);
@@ -3517,6 +3542,12 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
break;
+ case QEMU_OPTION_bandwidth:
+ if (!qemu_opts_parse(qemu_find_opts("bandwidth-opts"),
+ optarg, 1)) {
+ exit(1);
+ }
+ break;
case QEMU_OPTION_vnc:
#ifdef CONFIG_VNC
display_remote++;
@@ -3862,6 +3893,8 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
+ bandwidth_parse(qemu_opts_find(qemu_find_opts("bandwidth-opts"), NULL));
+
/*
* Get the default machine options from the machine if it is not already
* specified either by the configuration file or by the command line.
--
1.9.1
Signed-off-by: Harald Schieche <rehs@gmx.de>
next reply other threads:[~2014-10-28 15:34 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-28 15:33 Harald Schieche [this message]
2014-10-29 15:09 ` [Qemu-devel] [PATCH] Simple performance logging and network limiting based on trace option Stefan Hajnoczi
2014-10-30 14:05 ` harald Schieche
2014-10-31 11:13 ` Stefan Hajnoczi
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=1414510422-8277-1-git-send-email-rehs@gmx.de \
--to=rehs@gmx.de \
--cc=aliguori@amazon.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
--cc=sw@weilnetz.de \
/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;
as well as URLs for NNTP newsgroup(s).