From: "Alex Bennée" <alex.bennee@linaro.org>
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Richard Henderson <rth@twiddle.net>,
vandersonmr <vandersonmr2@gmail.com>,
"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
Markus Armbruster <armbru@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v4 6/7] monitor: adding tb_stats hmp command
Date: Fri, 26 Jul 2019 17:57:02 +0100 [thread overview]
Message-ID: <87muh0hgyp.fsf@linaro.org> (raw)
In-Reply-To: <20190720010235.32444-7-vandersonmr2@gmail.com>
vandersonmr <vandersonmr2@gmail.com> writes:
> Adding tb_stats [start|pause|stop|filter] command to hmp.
> This allows controlling the collection of statistics.
> It is also possible to set the level of collection:
> all, jit, or exec.
>
> The goal of this command is to allow the dynamic exploration
> of the TCG behavior and quality. Therefore, for now, a
> corresponding QMP command is not worthwhile.
>
> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
> ---
> accel/tcg/tb-stats.c | 107 ++++++++++++++++++++++++++++++++++++++++
> hmp-commands.hx | 17 +++++++
> include/exec/tb-stats.h | 13 +++++
> include/qemu/log.h | 1 +
> monitor/misc.c | 40 +++++++++++++++
> 5 files changed, 178 insertions(+)
>
> diff --git a/accel/tcg/tb-stats.c b/accel/tcg/tb-stats.c
> index 44497d4f9b..6c330e1b02 100644
> --- a/accel/tcg/tb-stats.c
> +++ b/accel/tcg/tb-stats.c
> @@ -6,6 +6,9 @@
>
> #include "qemu/qemu-print.h"
>
> +/* only accessed in safe work */
> +static GList *last_search;
> +
> struct jit_profile_info {
> uint64_t translations;
> uint64_t aborted;
> @@ -104,4 +107,108 @@ void dump_jit_profile_info(TCGProfile *s)
> }
> }
>
> +static void dessaloc_tbstats(void *p, uint32_t hash, void *userp)
> +{
> + g_free(p);
> +}
surely free_tbstats would be a better name?
> +
> +void clean_tbstats(void)
> +{
> + /* remove all tb_stats */
> + qht_iter(&tb_ctx.tb_stats, dessaloc_tbstats, NULL);
> + qht_destroy(&tb_ctx.tb_stats);
> +}
> +
> +static void reset_tbstats_flag(void *p, uint32_t hash, void *userp)
> +{
> + uint32_t flag = *((int *)userp);
> + TBStatistics *tbs = p;
> + tbs->stats_enabled = flag;
> +}
> +
> +void set_tbstats_flags(uint32_t flag)
> +{
> + /* iterate over tbstats setting their flag as TB_NOTHING */
> + qht_iter(&tb_ctx.tb_stats, reset_tbstats_flag, &flag);
> +}
> +
> +void do_hmp_tbstats_safe(CPUState *cpu, run_on_cpu_data icmd)
> +{
> + struct TbstatsCommand *cmdinfo = icmd.host_ptr;
> + int cmd = cmdinfo->cmd;
> + uint32_t level = cmdinfo->level;
> +
> + /* for safe, always pause TB generation while running this commands */
> + mmap_lock();
This doesn't serialise in all cases - in fact it's running as safe work
which is our serial case. The mmap_lock is really only needed for code
generation in linux-user. I think the lock/unlock can be dropped from
these operations.
> +
> + switch (cmd) {
> + case START:
> + if (tb_stats_collection_paused()) {
> + set_tbstats_flags(level);
> + } else {
> + if (tb_stats_collection_enabled()) {
> + qemu_printf("TB information already being recorded");
> + return;
> + }
> + qht_init(&tb_ctx.tb_stats, tb_stats_cmp, CODE_GEN_HTABLE_SIZE,
> + QHT_MODE_AUTO_RESIZE);
I'm wary of initialising this in multiple places. Maybe move this to
enable_collect_tb_stats and drop the initialisation in tb_htable_init.
> + }
> +
> + set_default_tbstats_flag(level);
> + enable_collect_tb_stats();
> + tb_flush(cpu);
> + break;
> + case PAUSE:
> + if (!tb_stats_collection_enabled()) {
> + qemu_printf("TB information not being recorded");
> + return;
> + }
> +
> + /* Continue to create TBStatistic structures but stop collecting statistics */
> + pause_collect_tb_stats();
> + tb_flush(cpu);
> + set_default_tbstats_flag(TB_NOTHING);
> + set_tbstats_flags(TB_PAUSED);
Minor style suggestion - make the tb_flush the last thing you do once
you have moved things around. You are in safe work so nothing should be
happening anyway and it reads better.
> + break;
> + case STOP:
> + if (!tb_stats_collection_enabled()) {
> + qemu_printf("TB information not being recorded");
> + return;
> + }
> +
> + /* Dissalloc all TBStatistics structures and stop creating new ones */
> + disable_collect_tb_stats();
> + tb_flush(cpu);
> + clean_tbstats();
As above.
> + break;
> + case FILTER:
> + if (!tb_stats_collection_enabled()) {
> + qemu_printf("TB information not being recorded");
> + return;
> + }
> + if (!last_search) {
> + qemu_printf("no search on record! execute info tbs before filtering!");
> + return;
> + }
> +
> + tb_flush(cpu);
> + set_default_tbstats_flag(TB_NOTHING);
> +
> + /* Set all tbstats as paused, then return only the ones from last_search */
> + pause_collect_tb_stats();
> + set_tbstats_flags(TB_PAUSED);
> +
> + for (GList *iter = last_search; iter; iter = g_list_next(iter)) {
> + TBStatistics *tbs = iter->data;
> + tbs->stats_enabled = level;
> + }
If we are only interested in tracking the N hotestest at this point we
want to prevent allocation of new TBStats and free all the unused ones?
> +
> + break;
> + default: /* INVALID */
g_assert_not_reached()? This would be an internal bug if we ever sent
the wrong command?
> + break;
> + }
> +
> + mmap_unlock();
> + g_free(cmdinfo);
> +}
>
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index bfa5681dd2..419898751e 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1885,6 +1885,23 @@ STEXI
> @findex qemu-io
> Executes a qemu-io command on the given block device.
>
> +ETEXI
> +#if defined(CONFIG_TCG)
> + {
> + .name = "tb_stats",
> + .args_type = "command:s,level:s?",
> + .params = "command [stats_level]",
> + .help = "Control tb statistics collection:"
> + "tb_stats (start|pause|stop|filter)
> [all|jit_stats|exec_stats]",
What does filter do?
> + .cmd = hmp_tbstats,
> + },
> +#endif
> +
> +STEXI
> +@item tb_stats
> +@findex
> +Control recording tb statistics
> +
> ETEXI
>
> {
> diff --git a/include/exec/tb-stats.h b/include/exec/tb-stats.h
> index 7d775f2c0d..d1debd3262 100644
> --- a/include/exec/tb-stats.h
> +++ b/include/exec/tb-stats.h
> @@ -6,6 +6,9 @@
> #include "exec/tb-context.h"
> #include "tcg.h"
>
> +enum SortBy { SORT_BY_HOTNESS, SORT_BY_HG /* Host/Guest */, SORT_BY_SPILLS };
> +enum TbstatsCmd { START, PAUSE, STOP, FILTER };
> +
> #define tb_stats_enabled(tb, JIT_STATS) \
> (tb && tb->tb_stats && (tb->tb_stats->stats_enabled & JIT_STATS))
>
> @@ -60,4 +63,14 @@ bool tb_stats_cmp(const void *ap, const void *bp);
>
> void dump_jit_profile_info(TCGProfile *s);
>
> +void set_tbstats_flags(uint32_t flags);
> +void clean_tbstats(void);
> +
> +struct TbstatsCommand {
> + enum TbstatsCmd cmd;
> + uint32_t level;
> +};
> +
> +void do_hmp_tbstats_safe(CPUState *cpu, run_on_cpu_data icmd);
> +
> #endif
> diff --git a/include/qemu/log.h b/include/qemu/log.h
> index 93642603e5..47071d72c7 100644
> --- a/include/qemu/log.h
> +++ b/include/qemu/log.h
> @@ -133,6 +133,7 @@ void qemu_log_close(void);
> #define TB_NOTHING 0
> #define TB_EXEC_STATS (1 << 1)
> #define TB_JIT_STATS (1 << 2)
> +#define TB_PAUSED (1 << 3)
>
> void enable_collect_tb_stats(void);
> void disable_collect_tb_stats(void);
> diff --git a/monitor/misc.c b/monitor/misc.c
> index 00338c002a..aea9b0db4f 100644
> --- a/monitor/misc.c
> +++ b/monitor/misc.c
> @@ -459,6 +459,46 @@ static void hmp_info_registers(Monitor *mon, const QDict *qdict)
> }
>
> #ifdef CONFIG_TCG
> +static void hmp_tbstats(Monitor *mon, const QDict *qdict)
> +{
> + if (!tcg_enabled()) {
> + error_report("TB information is only available with accel=tcg");
> + return;
> + }
> +
> + char *cmd = (char *) qdict_get_try_str(qdict, "command");
> + enum TbstatsCmd icmd = -1;
> +
> + if (strcmp(cmd, "start") == 0) {
> + icmd = START;
> + } else if (strcmp(cmd, "pause") == 0) {
> + icmd = PAUSE;
> + } else if (strcmp(cmd, "stop") == 0) {
> + icmd = STOP;
> + } else if (strcmp(cmd, "filter") == 0) {
> + icmd = FILTER;
> + } else {
> + error_report("invalid command!");
> + }
> +
> + char *slevel = (char *) qdict_get_try_str(qdict, "level");
> + uint32_t level = TB_EXEC_STATS | TB_JIT_STATS;
> + if (slevel) {
> + if (strcmp(slevel, "jit_stats") == 0) {
> + level = TB_JIT_STATS;
> + } else if (strcmp(slevel, "exec_stats") == 0) {
> + level = TB_EXEC_STATS;
> + }
> + }
> +
> + struct TbstatsCommand *tbscommand = g_new0(struct TbstatsCommand, 1);
> + tbscommand->cmd = icmd;
> + tbscommand->level = level;
It might be worth considering squashing these into a single pointer to
avoid the allocation and free?
> + async_safe_run_on_cpu(first_cpu, do_hmp_tbstats_safe,
> + RUN_ON_CPU_HOST_PTR(tbscommand));
> +
> +}
> +
> static void hmp_info_jit(Monitor *mon, const QDict *qdict)
> {
> if (!tcg_enabled()) {
--
Alex Bennée
next prev parent reply other threads:[~2019-07-26 16:57 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-20 1:02 [Qemu-devel] [PATCH v4 0/7] Measure Tiny Code Generation Quality vandersonmr
2019-07-20 1:02 ` [Qemu-devel] [PATCH v4 1/7] accel: introducing TBStatistics structure vandersonmr
2019-07-26 11:56 ` Alex Bennée
2019-07-20 1:02 ` [Qemu-devel] [PATCH v4 2/7] accel: collecting TB execution count vandersonmr
2019-07-26 13:38 ` Alex Bennée
2019-07-20 1:02 ` [Qemu-devel] [PATCH v4 3/7] accel: collecting JIT statistics vandersonmr
2019-07-26 14:46 ` Alex Bennée
2019-07-20 1:02 ` [Qemu-devel] [PATCH v4 4/7] accel: replacing part of CONFIG_PROFILER with TBStats vandersonmr
2019-07-26 15:25 ` Alex Bennée
2019-07-20 1:02 ` [Qemu-devel] [PATCH v4 5/7] log: adding -d tb_stats to control tbstats vandersonmr
2019-07-26 16:20 ` Alex Bennée
2019-07-20 1:02 ` [Qemu-devel] [PATCH v4 6/7] monitor: adding tb_stats hmp command vandersonmr
2019-07-26 16:57 ` Alex Bennée [this message]
2019-07-20 1:02 ` [Qemu-devel] [PATCH v4 7/7] monitor: adding info tbs, tb, and coverset vandersonmr
2019-07-26 18:17 ` Alex Bennée
2019-07-29 11:01 ` Alex Bennée
2019-07-29 15:20 ` Alex Bennée
2019-07-26 12:51 ` [Qemu-devel] [PATCH v4 0/7] Measure Tiny Code Generation Quality Alex Bennée
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=87muh0hgyp.fsf@linaro.org \
--to=alex.bennee@linaro.org \
--cc=armbru@redhat.com \
--cc=dgilbert@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
--cc=vandersonmr2@gmail.com \
/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.