Patchwork [03/10] Add printf debug to savevm

login
register
mail settings
Submitter Juan Quintela
Date Nov. 23, 2010, 11:03 p.m.
Message ID <ab28b24ebd9582826697372c4abb3f8f0b719733.1290552026.git.quintela@redhat.com>
Download mbox | patch
Permalink /patch/72775/
State New
Headers show

Comments

Juan Quintela - Nov. 23, 2010, 11:03 p.m.
From: Juan Quintela <quintela@trasno.org>

Once there, print all sections that take more than 100ms to migrate.
buffered file runs a timer at that 100ms interval.

Signed-off-by: Juan Quintela <quintela@trasno.org>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 savevm.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 46 insertions(+), 2 deletions(-)
Anthony Liguori - Nov. 30, 2010, 2 a.m.
On 11/23/2010 05:03 PM, Juan Quintela wrote:
> From: Juan Quintela<quintela@trasno.org>
>
> Once there, print all sections that take more than 100ms to migrate.
> buffered file runs a timer at that 100ms interval.
>
> Signed-off-by: Juan Quintela<quintela@trasno.org>
> Signed-off-by: Juan Quintela<quintela@redhat.com>
> ---
>   savevm.c |   48 ++++++++++++++++++++++++++++++++++++++++++++++--
>   1 files changed, 46 insertions(+), 2 deletions(-)
>
> diff --git a/savevm.c b/savevm.c
> index 4e49765..ceed6de 100644
> --- a/savevm.c
> +++ b/savevm.c
> @@ -83,6 +83,24 @@
>   #include "migration.h"
>   #include "qemu_socket.h"
>   #include "qemu-queue.h"
> +#include "buffered_file.h"
> +
> +//#define DEBUG_SAVEVM
> +
> +#ifdef DEBUG_SAVEVM
> +#define DPRINTF(fmt, ...) \
> +    do { printf("savevm: " fmt, ## __VA_ARGS__); } while (0)
> +static int64_t start, stop;
> +#define START_SAVEVM_CLOCK()	do { start = qemu_get_clock(rt_clock); } while (0)
> +#define STOP_SAVEVM_CLOCK() \
> +	do { stop = qemu_get_clock(rt_clock) - start; \
> +	} while (0)
> +#else
> +#define DPRINTF(fmt, ...) \
> +    do { } while (0)
> +#define START_SAVEVM_CLOCK()  do { } while (0)
> +#define STOP_SAVEVM_CLOCK()   do { } while (0)
> +#endif
>
>   #define SELF_ANNOUNCE_ROUNDS 5
>
> @@ -1480,11 +1498,23 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
>           if (se->save_live_state == NULL)
>               continue;
>
> +        START_SAVEVM_CLOCK();
> +
>    

No magic macros like this please.  Maybe you want to add tracepoints?

>           /* Section type */
>           qemu_put_byte(f, QEMU_VM_SECTION_PART);
>           qemu_put_be32(f, se->section_id);
>
>           ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
> +        STOP_SAVEVM_CLOCK();
> +#ifdef DEBUG_SAVEVM
> +	if (stop>  buffered_file_interval) {
> +		/* buffered_file run a timer at 100ms */
> +		static int times_missing = 1;
> +		DPRINTF("save live iterate section id %u name %s took %ld milliseconds %u times\n",
> +			se->section_id,	se->idstr, stop, times_missing++);
> +	}
> +#endif
> +
>           if (!ret) {
>               /* Do not proceed to the next vmstate before this one reported
>                  completion of the current stage. This serializes the migration
> @@ -1516,13 +1546,18 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
>           if (se->save_live_state == NULL)
>               continue;
>
> +        START_SAVEVM_CLOCK();
>           /* Section type */
>           qemu_put_byte(f, QEMU_VM_SECTION_END);
>           qemu_put_be32(f, se->section_id);
>
>           se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
> +        STOP_SAVEVM_CLOCK();
> +        DPRINTF("save live end section id %u name %s took %ld milliseconds\n",
> +		se->section_id, se->idstr, stop);
>       }
>
> +    START_SAVEVM_CLOCK();
>       QTAILQ_FOREACH(se,&savevm_handlers, entry) {
>           int len;
>
> @@ -1542,12 +1577,14 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
>           qemu_put_be32(f, se->version_id);
>
>           r = vmstate_save(f, se);
> +        DPRINTF("save section id %u name %s\n", se->section_id, se->idstr);
>           if (r<  0) {
>               monitor_printf(mon, "cannot migrate with device '%s'\n", se->idstr);
>               return r;
>           }
>       }
> -
> +    STOP_SAVEVM_CLOCK();
> +    DPRINTF("save devices took %ld milliseconds\n", stop);
>       qemu_put_byte(f, QEMU_VM_EOF);
>
>       if (qemu_file_has_error(f))
> @@ -1746,8 +1783,11 @@ int qemu_loadvm_state(QEMUFile *f)
>               le->section_id = section_id;
>               le->version_id = version_id;
>               QLIST_INSERT_HEAD(&loadvm_handlers, le, entry);
> -
> +            START_SAVEVM_CLOCK();
>               ret = vmstate_load(f, le->se, le->version_id);
> +            STOP_SAVEVM_CLOCK();
> +            DPRINTF("load section id %u name %s took %ld milliseconds\n", le->section_id,
> +		    le->se->idstr, stop);
>               if (ret<  0) {
>                   fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
>                           instance_id, idstr);
> @@ -1769,7 +1809,11 @@ int qemu_loadvm_state(QEMUFile *f)
>                   goto out;
>               }
>
> +            START_SAVEVM_CLOCK();
>               ret = vmstate_load(f, le->se, le->version_id);
> +            STOP_SAVEVM_CLOCK();
> +            DPRINTF("load section id %u name %s took %ld milliseconds\n", le->section_id,
> +		    le->se->idstr, stop);
>               if (ret<  0) {
>                   fprintf(stderr, "qemu: warning: error while loading state section id %d\n",
>                           section_id);
>    

Yeah, all of this should be done via tracing.  Maybe Stefan can make 
some suggestions.

Regards,

Anthony Liguori
Stefan Hajnoczi - Nov. 30, 2010, 10:36 a.m.
On Mon, Nov 29, 2010 at 08:00:18PM -0600, Anthony Liguori wrote:
> Yeah, all of this should be done via tracing.  Maybe Stefan can make
> some suggestions.

Here is an example of how to record savevm timestamps using tracing.
Actually the timestamp is recorded automatically when a trace event
fires.

Add these to the trace-events file:
savevm_start(void) ""
savevm_stop(unsigned int section_id) "section_id %u"

Then use trace_savevm_start() instead of START_SAVEVM_CLOCK() and
trace_savevm_stop() instead of STOP_SAVEVM_CLOCK() in savevm.c.  Also
#include "trace.h".

All the macros and inline timestamp analysis can be removed from
savevm.c.

./configure --trace-backend=simple [...]
make

After running savevm look for the trace-<pid> file that QEMU produces in
its current working directory.  You can pretty-print it like this:
./simpletrace.py trace-events trace-<pid>

The second field in the simpletrace.py output is the time delta (in
microseconds) since the last trace event.  So you can easily see how
long start->stop took.

For more info see docs/tracing.txt.  You might prefer to use SystemTap
(./configure --trace-backend=dtrace) so you can write stap scripts to do
more powerful analysis.

Stefan
Juan Quintela - Nov. 30, 2010, 10:40 p.m.
Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> wrote:
> On Mon, Nov 29, 2010 at 08:00:18PM -0600, Anthony Liguori wrote:
>> Yeah, all of this should be done via tracing.  Maybe Stefan can make
>> some suggestions.
>
> Here is an example of how to record savevm timestamps using tracing.
> Actually the timestamp is recorded automatically when a trace event
> fires.
>
> Add these to the trace-events file:
> savevm_start(void) ""
> savevm_stop(unsigned int section_id) "section_id %u"
>
> Then use trace_savevm_start() instead of START_SAVEVM_CLOCK() and
> trace_savevm_stop() instead of STOP_SAVEVM_CLOCK() in savevm.c.  Also
> #include "trace.h".
>
> All the macros and inline timestamp analysis can be removed from
> savevm.c.
>
> ./configure --trace-backend=simple [...]
> make
>
> After running savevm look for the trace-<pid> file that QEMU produces in
> its current working directory.  You can pretty-print it like this:
> ./simpletrace.py trace-events trace-<pid>
>
> The second field in the simpletrace.py output is the time delta (in
> microseconds) since the last trace event.  So you can easily see how
> long start->stop took.
>
> For more info see docs/tracing.txt.  You might prefer to use SystemTap
> (./configure --trace-backend=dtrace) so you can write stap scripts to do
> more powerful analysis.

Thanks.

Searching for guru, I basically want to only print the values when the
difference is bigger that some values (number of calls is really big, I
need to learn how to script the analisys).

But clearly this "have to be" easier than change printf's and ifs and
rerun the test.

Later, Juan.

> Stefan
Stefan Hajnoczi - Dec. 1, 2010, 7:50 a.m.
On Tue, Nov 30, 2010 at 11:40:36PM +0100, Juan Quintela wrote:
> Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> wrote:
> > On Mon, Nov 29, 2010 at 08:00:18PM -0600, Anthony Liguori wrote:
> >> Yeah, all of this should be done via tracing.  Maybe Stefan can make
> >> some suggestions.
> >
> > Here is an example of how to record savevm timestamps using tracing.
> > Actually the timestamp is recorded automatically when a trace event
> > fires.
> >
> > Add these to the trace-events file:
> > savevm_start(void) ""
> > savevm_stop(unsigned int section_id) "section_id %u"
> >
> > Then use trace_savevm_start() instead of START_SAVEVM_CLOCK() and
> > trace_savevm_stop() instead of STOP_SAVEVM_CLOCK() in savevm.c.  Also
> > #include "trace.h".
> >
> > All the macros and inline timestamp analysis can be removed from
> > savevm.c.
> >
> > ./configure --trace-backend=simple [...]
> > make
> >
> > After running savevm look for the trace-<pid> file that QEMU produces in
> > its current working directory.  You can pretty-print it like this:
> > ./simpletrace.py trace-events trace-<pid>
> >
> > The second field in the simpletrace.py output is the time delta (in
> > microseconds) since the last trace event.  So you can easily see how
> > long start->stop took.
> >
> > For more info see docs/tracing.txt.  You might prefer to use SystemTap
> > (./configure --trace-backend=dtrace) so you can write stap scripts to do
> > more powerful analysis.
> 
> Thanks.
> 
> Searching for guru, I basically want to only print the values when the
> difference is bigger that some values (number of calls is really big, I
> need to learn how to script the analisys).

You can use awk(1) on the simpletrace.py output:
$1 ~ /savevm_stop/ {
	/* Print savevm_stop line when >100 ms duration */
	if ($2 > 100000) {
		printf("%s times_missing=%u\n", $0, times_missing++);
	}
}

Or you can use --trace-backend=dtrace and write SystemTap scripts:
http://sourceware.org/systemtap/SystemTap_Beginners_Guide/
http://sourceware.org/systemtap/langref/

Stefan

Patch

diff --git a/savevm.c b/savevm.c
index 4e49765..ceed6de 100644
--- a/savevm.c
+++ b/savevm.c
@@ -83,6 +83,24 @@ 
 #include "migration.h"
 #include "qemu_socket.h"
 #include "qemu-queue.h"
+#include "buffered_file.h"
+
+//#define DEBUG_SAVEVM
+
+#ifdef DEBUG_SAVEVM
+#define DPRINTF(fmt, ...) \
+    do { printf("savevm: " fmt, ## __VA_ARGS__); } while (0)
+static int64_t start, stop;
+#define START_SAVEVM_CLOCK()	do { start = qemu_get_clock(rt_clock); } while (0)
+#define STOP_SAVEVM_CLOCK() \
+	do { stop = qemu_get_clock(rt_clock) - start; \
+	} while (0)
+#else
+#define DPRINTF(fmt, ...) \
+    do { } while (0)
+#define START_SAVEVM_CLOCK()  do { } while (0)
+#define STOP_SAVEVM_CLOCK()   do { } while (0)
+#endif

 #define SELF_ANNOUNCE_ROUNDS 5

@@ -1480,11 +1498,23 @@  int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
         if (se->save_live_state == NULL)
             continue;

+        START_SAVEVM_CLOCK();
+
         /* Section type */
         qemu_put_byte(f, QEMU_VM_SECTION_PART);
         qemu_put_be32(f, se->section_id);

         ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
+        STOP_SAVEVM_CLOCK();
+#ifdef DEBUG_SAVEVM
+	if (stop > buffered_file_interval) {
+		/* buffered_file run a timer at 100ms */
+		static int times_missing = 1;
+		DPRINTF("save live iterate section id %u name %s took %ld milliseconds %u times\n",
+			se->section_id,	se->idstr, stop, times_missing++);
+	}
+#endif
+
         if (!ret) {
             /* Do not proceed to the next vmstate before this one reported
                completion of the current stage. This serializes the migration
@@ -1516,13 +1546,18 @@  int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
         if (se->save_live_state == NULL)
             continue;

+        START_SAVEVM_CLOCK();
         /* Section type */
         qemu_put_byte(f, QEMU_VM_SECTION_END);
         qemu_put_be32(f, se->section_id);

         se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
+        STOP_SAVEVM_CLOCK();
+        DPRINTF("save live end section id %u name %s took %ld milliseconds\n",
+		se->section_id, se->idstr, stop);
     }

+    START_SAVEVM_CLOCK();
     QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         int len;

@@ -1542,12 +1577,14 @@  int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
         qemu_put_be32(f, se->version_id);

         r = vmstate_save(f, se);
+        DPRINTF("save section id %u name %s\n", se->section_id, se->idstr);
         if (r < 0) {
             monitor_printf(mon, "cannot migrate with device '%s'\n", se->idstr);
             return r;
         }
     }
-
+    STOP_SAVEVM_CLOCK();
+    DPRINTF("save devices took %ld milliseconds\n", stop);
     qemu_put_byte(f, QEMU_VM_EOF);

     if (qemu_file_has_error(f))
@@ -1746,8 +1783,11 @@  int qemu_loadvm_state(QEMUFile *f)
             le->section_id = section_id;
             le->version_id = version_id;
             QLIST_INSERT_HEAD(&loadvm_handlers, le, entry);
-
+            START_SAVEVM_CLOCK();
             ret = vmstate_load(f, le->se, le->version_id);
+            STOP_SAVEVM_CLOCK();
+            DPRINTF("load section id %u name %s took %ld milliseconds\n", le->section_id,
+		    le->se->idstr, stop);
             if (ret < 0) {
                 fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
                         instance_id, idstr);
@@ -1769,7 +1809,11 @@  int qemu_loadvm_state(QEMUFile *f)
                 goto out;
             }

+            START_SAVEVM_CLOCK();
             ret = vmstate_load(f, le->se, le->version_id);
+            STOP_SAVEVM_CLOCK();
+            DPRINTF("load section id %u name %s took %ld milliseconds\n", le->section_id,
+		    le->se->idstr, stop);
             if (ret < 0) {
                 fprintf(stderr, "qemu: warning: error while loading state section id %d\n",
                         section_id);