diff mbox series

[v17,16/16] accel/tcg: Dump hot TBs at the end of the execution

Message ID 20231003183058.1639121-17-richard.henderson@linaro.org
State New
Headers show
Series TCG code quality tracking | expand

Commit Message

Richard Henderson Oct. 3, 2023, 6:30 p.m. UTC
From: Fei Wu <fei2.wu@intel.com>

Dump the hottest TBs if -d tb_stats:{all,jit,exec}[:dump_num_at_exit]

Signed-off-by: Fei Wu <fei2.wu@intel.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 bsd-user/bsd-proc.h    |  2 ++
 include/tcg/tb-stats.h | 10 +++++++++-
 accel/tcg/monitor.c    |  8 +++++---
 accel/tcg/tb-stats.c   | 27 ++++++++++++++++++++++++++-
 linux-user/exit.c      | 10 ++++++----
 softmmu/runstate.c     |  2 ++
 stubs/tb-stats.c       |  6 +++++-
 util/log.c             | 20 ++++++++++++++++----
 8 files changed, 71 insertions(+), 14 deletions(-)

Comments

Philippe Mathieu-Daudé Oct. 10, 2023, 12:36 p.m. UTC | #1
On 3/10/23 20:30, Richard Henderson wrote:
> From: Fei Wu <fei2.wu@intel.com>
> 
> Dump the hottest TBs if -d tb_stats:{all,jit,exec}[:dump_num_at_exit]
> 
> Signed-off-by: Fei Wu <fei2.wu@intel.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   bsd-user/bsd-proc.h    |  2 ++
>   include/tcg/tb-stats.h | 10 +++++++++-
>   accel/tcg/monitor.c    |  8 +++++---
>   accel/tcg/tb-stats.c   | 27 ++++++++++++++++++++++++++-
>   linux-user/exit.c      | 10 ++++++----
>   softmmu/runstate.c     |  2 ++
>   stubs/tb-stats.c       |  6 +++++-
>   util/log.c             | 20 ++++++++++++++++----
>   8 files changed, 71 insertions(+), 14 deletions(-)


> diff --git a/softmmu/runstate.c b/softmmu/runstate.c
> index 1652ed0439..2c6fb9bff1 100644
> --- a/softmmu/runstate.c
> +++ b/softmmu/runstate.c
> @@ -59,6 +59,7 @@
>   #include "sysemu/runstate-action.h"
>   #include "sysemu/sysemu.h"
>   #include "sysemu/tpm.h"
> +#include "tcg/tb-stats.h"
>   #include "trace.h"
>   
>   static NotifierList exit_notifiers =
> @@ -846,6 +847,7 @@ void qemu_cleanup(void)
>       /* No more vcpu or device emulation activity beyond this point */
>       vm_shutdown();
>       replay_finish();
> +    tb_stats_dump_atexit();
>   
>       /*
>        * We must cancel all block jobs while the block layer is drained,
> diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c
> index ceaa1622ce..f9e4ef5d04 100644
> --- a/stubs/tb-stats.c
> +++ b/stubs/tb-stats.c
> @@ -11,6 +11,10 @@
>   #include "qemu/osdep.h"
>   #include "tcg/tb-stats.h"
>   
> -void tb_stats_init(uint32_t flags)
> +void tb_stats_init(uint32_t flags, uint32_t atexit)
> +{
> +}
> +
> +void tb_stats_dump_atexit(void)
>   {
>   }

The stub isn't needed using:

-- >8 --
diff --git a/softmmu/runstate.c b/softmmu/runstate.c
index 2c6fb9bff1..d05e2b8e1c 100644
--- a/softmmu/runstate.c
+++ b/softmmu/runstate.c
@@ -52,6 +52,7 @@
  #include "qom/object.h"
  #include "qom/object_interfaces.h"
  #include "sysemu/cpus.h"
+#include "sysemu/tcg.h"
  #include "sysemu/qtest.h"
  #include "sysemu/replay.h"
  #include "sysemu/reset.h"
@@ -847,7 +848,9 @@ void qemu_cleanup(void)
      /* No more vcpu or device emulation activity beyond this point */
      vm_shutdown();
      replay_finish();
-    tb_stats_dump_atexit();
+    if (tcg_enabled()) {
+        tb_stats_dump_atexit();
+    }

      /*
       * We must cancel all block jobs while the block layer is drained,
---
Alex Bennée Oct. 10, 2023, 1:23 p.m. UTC | #2
Philippe Mathieu-Daudé <philmd@linaro.org> writes:

> On 3/10/23 20:30, Richard Henderson wrote:
>> From: Fei Wu <fei2.wu@intel.com>
>> Dump the hottest TBs if -d
>> tb_stats:{all,jit,exec}[:dump_num_at_exit]
>> Signed-off-by: Fei Wu <fei2.wu@intel.com>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   bsd-user/bsd-proc.h    |  2 ++
>>   include/tcg/tb-stats.h | 10 +++++++++-
>>   accel/tcg/monitor.c    |  8 +++++---
>>   accel/tcg/tb-stats.c   | 27 ++++++++++++++++++++++++++-
>>   linux-user/exit.c      | 10 ++++++----
>>   softmmu/runstate.c     |  2 ++
>>   stubs/tb-stats.c       |  6 +++++-
>>   util/log.c             | 20 ++++++++++++++++----
>>   8 files changed, 71 insertions(+), 14 deletions(-)
>
>
>> diff --git a/softmmu/runstate.c b/softmmu/runstate.c
>> index 1652ed0439..2c6fb9bff1 100644
>> --- a/softmmu/runstate.c
>> +++ b/softmmu/runstate.c
>> @@ -59,6 +59,7 @@
>>   #include "sysemu/runstate-action.h"
>>   #include "sysemu/sysemu.h"
>>   #include "sysemu/tpm.h"
>> +#include "tcg/tb-stats.h"
>>   #include "trace.h"
>>     static NotifierList exit_notifiers =
>> @@ -846,6 +847,7 @@ void qemu_cleanup(void)
>>       /* No more vcpu or device emulation activity beyond this point */
>>       vm_shutdown();
>>       replay_finish();
>> +    tb_stats_dump_atexit();
>>         /*
>>        * We must cancel all block jobs while the block layer is drained,
>> diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c
>> index ceaa1622ce..f9e4ef5d04 100644
>> --- a/stubs/tb-stats.c
>> +++ b/stubs/tb-stats.c
>> @@ -11,6 +11,10 @@
>>   #include "qemu/osdep.h"
>>   #include "tcg/tb-stats.h"
>>   -void tb_stats_init(uint32_t flags)
>> +void tb_stats_init(uint32_t flags, uint32_t atexit)
>> +{
>> +}
>> +
>> +void tb_stats_dump_atexit(void)
>>   {
>>   }
>
> The stub isn't needed using:
>
> -- >8 --
> diff --git a/softmmu/runstate.c b/softmmu/runstate.c
> index 2c6fb9bff1..d05e2b8e1c 100644
> --- a/softmmu/runstate.c
> +++ b/softmmu/runstate.c
> @@ -52,6 +52,7 @@
>  #include "qom/object.h"
>  #include "qom/object_interfaces.h"
>  #include "sysemu/cpus.h"
> +#include "sysemu/tcg.h"
>  #include "sysemu/qtest.h"
>  #include "sysemu/replay.h"
>  #include "sysemu/reset.h"
> @@ -847,7 +848,9 @@ void qemu_cleanup(void)
>      /* No more vcpu or device emulation activity beyond this point */
>      vm_shutdown();
>      replay_finish();
> -    tb_stats_dump_atexit();
> +    if (tcg_enabled()) {
> +        tb_stats_dump_atexit();
> +    }

Why be different from replay_finish() which is a stub?
diff mbox series

Patch

diff --git a/bsd-user/bsd-proc.h b/bsd-user/bsd-proc.h
index 0e1d461c4c..84b52b399a 100644
--- a/bsd-user/bsd-proc.h
+++ b/bsd-user/bsd-proc.h
@@ -21,12 +21,14 @@ 
 #define BSD_PROC_H_
 
 #include <sys/resource.h>
+#include "tcg/tb-stats.h"
 
 /* exit(2) */
 static inline abi_long do_bsd_exit(void *cpu_env, abi_long arg1)
 {
     gdb_exit(arg1);
     qemu_plugin_user_exit();
+    tb_stats_dump_atexit();
     _exit(arg1);
 
     return 0;
diff --git a/include/tcg/tb-stats.h b/include/tcg/tb-stats.h
index edee73b63b..d3cca94f84 100644
--- a/include/tcg/tb-stats.h
+++ b/include/tcg/tb-stats.h
@@ -41,11 +41,12 @@  extern uint32_t tb_stats_enabled;
 /**
  * tb_stats_init:
  * @flags: TB_STATS_* flags to enable.
+ * @atexit: count of hottest tbs to log.
  *
  * Initialize translation block statistics, enabling @flags.
  * If @flags is 0, disable all statistics.
  */
-void tb_stats_init(uint32_t flags);
+void tb_stats_init(uint32_t flags, uint32_t atexit);
 
 /*
  * This struct stores statistics such as execution count of the
@@ -154,4 +155,11 @@  gint tb_stats_sort_by_hg(gconstpointer, gconstpointer);
  */
 GString *tb_stats_dump(TBStatistics *s, unsigned index);
 
+/**
+ * tb_stats_dump_atexit:
+ *
+ * Log any requested TBs at end of execution.
+ */
+void tb_stats_dump_atexit(void);
+
 #endif /* TCG_TB_STATS_H */
diff --git a/accel/tcg/monitor.c b/accel/tcg/monitor.c
index 1be3218715..7719583654 100644
--- a/accel/tcg/monitor.c
+++ b/accel/tcg/monitor.c
@@ -245,7 +245,7 @@  static void tb_stats_init_safe(CPUState *cpu, run_on_cpu_data icmd)
 {
     uint32_t flags = icmd.host_int;
 
-    tb_stats_init(flags);
+    tb_stats_init(flags, 0);
     tb_flush(cpu);
 }
 
@@ -335,8 +335,10 @@  static void hmp_info_tblist(Monitor *mon, const QDict *qdict)
         return;
     }
 
-    g_ptr_array_unref(tb_ctx.last_search);
-    tb_ctx.last_search = NULL;
+    if (tb_ctx.last_search) {
+        g_ptr_array_unref(tb_ctx.last_search);
+        tb_ctx.last_search = NULL;
+    }
 
     array = tb_stats_collect(max, sort);
     max = array->len;
diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c
index 0f84c14a88..62a6228799 100644
--- a/accel/tcg/tb-stats.c
+++ b/accel/tcg/tb-stats.c
@@ -8,10 +8,12 @@ 
 
 #include "qemu/osdep.h"
 #include "qemu/xxhash.h"
+#include "qemu/log.h"
 #include "tcg/tb-stats.h"
 #include "tb-context.h"
 
 uint32_t tb_stats_enabled;
+static uint32_t tb_stats_atexit;
 
 static bool tb_stats_cmp(const void *ap, const void *bp)
 {
@@ -34,7 +36,7 @@  static void tb_stats_free(void *p, uint32_t hash, void *userp)
     g_free(s);
 }
 
-void tb_stats_init(uint32_t flags)
+void tb_stats_init(uint32_t flags, uint32_t atexit)
 {
     tb_stats_enabled = flags;
     if (flags) {
@@ -48,6 +50,14 @@  void tb_stats_init(uint32_t flags)
         qht_iter(&tb_ctx.stats, tb_stats_free, NULL);
         qht_destroy(&tb_ctx.stats);
     }
+
+    /*
+     * This function is also used by HMP, when atexit is 0.
+     * Preserve the value set from the command-line.
+     */
+    if (atexit) {
+        tb_stats_atexit = atexit;
+    }
 }
 
 static void tb_stats_reset(void *p, uint32_t hash, void *userp)
@@ -204,3 +214,18 @@  GString *tb_stats_dump(TBStatistics *s, unsigned index)
     }
     return buf;
 }
+
+void tb_stats_dump_atexit(void)
+{
+    if (tb_stats_enabled && tb_stats_atexit) {
+        g_autoptr(GPtrArray) array =
+            tb_stats_collect(tb_stats_atexit, tb_stats_sort_by_coverage);
+
+        for (uint32_t i = 0, n = array->len; i < n; ++i) {
+            TBStatistics *s = g_ptr_array_index(array, i);
+            g_autoptr(GString) str = tb_stats_dump(s, i);
+
+            qemu_log("%s\n", str->str);
+        }
+    }
+}
diff --git a/linux-user/exit.c b/linux-user/exit.c
index 50266314e0..4487aaac7e 100644
--- a/linux-user/exit.c
+++ b/linux-user/exit.c
@@ -22,6 +22,7 @@ 
 #include "qemu.h"
 #include "user-internals.h"
 #include "qemu/plugin.h"
+#include "tcg/tb-stats.h"
 
 #ifdef CONFIG_GCOV
 extern void __gcov_dump(void);
@@ -30,9 +31,10 @@  extern void __gcov_dump(void);
 void preexit_cleanup(CPUArchState *env, int code)
 {
 #ifdef CONFIG_GCOV
-        __gcov_dump();
+    __gcov_dump();
 #endif
-        gdb_exit(code);
-        qemu_plugin_user_exit();
-        perf_exit();
+    gdb_exit(code);
+    qemu_plugin_user_exit();
+    perf_exit();
+    tb_stats_dump_atexit();
 }
diff --git a/softmmu/runstate.c b/softmmu/runstate.c
index 1652ed0439..2c6fb9bff1 100644
--- a/softmmu/runstate.c
+++ b/softmmu/runstate.c
@@ -59,6 +59,7 @@ 
 #include "sysemu/runstate-action.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/tpm.h"
+#include "tcg/tb-stats.h"
 #include "trace.h"
 
 static NotifierList exit_notifiers =
@@ -846,6 +847,7 @@  void qemu_cleanup(void)
     /* No more vcpu or device emulation activity beyond this point */
     vm_shutdown();
     replay_finish();
+    tb_stats_dump_atexit();
 
     /*
      * We must cancel all block jobs while the block layer is drained,
diff --git a/stubs/tb-stats.c b/stubs/tb-stats.c
index ceaa1622ce..f9e4ef5d04 100644
--- a/stubs/tb-stats.c
+++ b/stubs/tb-stats.c
@@ -11,6 +11,10 @@ 
 #include "qemu/osdep.h"
 #include "tcg/tb-stats.h"
 
-void tb_stats_init(uint32_t flags)
+void tb_stats_init(uint32_t flags, uint32_t atexit)
+{
+}
+
+void tb_stats_dump_atexit(void)
 {
 }
diff --git a/util/log.c b/util/log.c
index 0cb987fb74..789b19a226 100644
--- a/util/log.c
+++ b/util/log.c
@@ -526,19 +526,31 @@  int qemu_str_to_log_mask(const char *str, Error **errp)
 #ifdef CONFIG_TCG
         } else if (g_str_has_prefix(t, "tb_stats:") && t[9] != '\0') {
             int flags = TB_STATS_NONE;
+            unsigned atexit = 0;
             char *v = t + 9;
+            char *e = strchr(v, ':');
+            size_t len;
 
-            if (g_str_equal(v, "all")) {
+            if (e) {
+                len = e - v;
+                if (qemu_strtoui(e + 1, NULL, 10, &atexit) < 0) {
+                    error_setg(errp, "Invalid -d option \"%s\"", t);
+                    goto error;
+                }
+            } else {
+                len = strlen(v);
+            }
+            if (strncmp(v, "all", len) == 0) {
                 flags = TB_STATS_ALL;
-            } else if (g_str_equal(v, "jit")) {
+            } else if (strncmp(v, "jit", len) == 0) {
                 flags = TB_STATS_JIT;
-            } else if (g_str_equal(v, "exec")) {
+            } else if (strncmp(v, "exec", len) == 0) {
                 flags = TB_STATS_EXEC;
             } else {
                 error_setg(errp, "Invalid -d option \"%s\"", t);
                 goto error;
             }
-            tb_stats_init(flags);
+            tb_stats_init(flags, atexit);
 #endif
         } else {
             for (item = qemu_log_items; item->mask != 0; item++) {