Received: by 2002:a05:6358:45e:b0:b5:b6eb:e1f9 with SMTP id 30csp1019442rwe; Fri, 26 Aug 2022 21:38:12 -0700 (PDT) X-Google-Smtp-Source: AA6agR79Ys3ThUVoZq0ZfvEMRPOvfPq59Tg6h9UZgiwirQJyA4X31E0IEj1SrI6aPOHgysI8AeEN X-Received: by 2002:aa7:d759:0:b0:447:b08b:6d00 with SMTP id a25-20020aa7d759000000b00447b08b6d00mr8363414eds.413.1661575092522; Fri, 26 Aug 2022 21:38:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1661575092; cv=none; d=google.com; s=arc-20160816; b=bZ4dtBoAMTQHhZiK1Z7GZeio65YWAeAKyquznTqqj/auDoiIyfKJWXGNiR/0sjGC9V l7v9eP/3DF/bqYl2Bsf9O/qY1zuvepL3wu4mQX/jZ8opCf1SMUpYWQzUqawoNdkCuyaW ryJvp6jn/kUVT2RMkUtXxkMgMJc73AhEOeG5yHkf+yzF8WrMndcQulKJUVVJKelNAe1f v/E56zmChWz/mBQ96xG1t1TW8zK+A0HcJnnh5WWXqdJaZ9OWkOW0COTuVQwvY2gWe32w GQBMeaAruq9zTy6xNyn+dMk1r8s2NInw7SJbf7BQG9+frJ7iw8I+tboU7gS+nkc/CoTA Si8g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=QsgRUoap7VQ4e3k2RJO75npUxzQM0WBwase44FYliLM=; b=kHw/iLhzu99YI3VSbn5R2qOrmoHtehMHiQDIhTpzLQSCjlr4qsg3otPG3jpMCB8u7k JzGbjnoHJxbcAvpb+lFc+N03/0OqBGBYvWR9mik4YmEJyrBqUrOMzLaeNvxgW7FAldnn 4Nm5TpdqKnmlongUIUVnTnaVQMZpQFs9pUIAMSRfz4qshUHk9rgU+QtYfEcPx63GSdFg fJHp6VBKVhwKkZojis5LW5LcjfGYfpUg0Mpn5et6EB27LAd63WFvyVhZqiq8SR7UCDYF 15Ls+NiWztJTelzbRYgeac3m8rhonNrlXpuWE6zcJCX7BubYRYEgneYZcBDXKfqxd5lQ Eflg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="uSv3u/R8"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id x4-20020a170906148400b0073b8c5f9fcbsi2019825ejc.61.2022.08.26.21.37.46; Fri, 26 Aug 2022 21:38:12 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b="uSv3u/R8"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234440AbiH0EDz (ORCPT + 99 others); Sat, 27 Aug 2022 00:03:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32956 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232408AbiH0EDw (ORCPT ); Sat, 27 Aug 2022 00:03:52 -0400 Received: from sin.source.kernel.org (sin.source.kernel.org [145.40.73.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E9F6BE3C05 for ; Fri, 26 Aug 2022 21:03:50 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sin.source.kernel.org (Postfix) with ESMTPS id 21C49CE29C0 for ; Sat, 27 Aug 2022 04:03:49 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C4566C433D6; Sat, 27 Aug 2022 04:03:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1661573027; bh=OOmpaaDy9ShZc/kMESeHiG2wVIE56UJPU3LZ7EpPjls=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uSv3u/R8ZwpqM+tn3ceEmJptDLmcGihQuX0qHw9xuuWvLo70s3gHwDxSKaZ07t11m hRlVxKZwedI4XqF3wO6BR53NC0FS/d4Gh1WLEF+3dJ+oBjo3GFLeQM1AmaK3Tmo7Sm zigKlcf1UvwQStvqvU98r1rG4uPtSb9wvXuUTjmN5855Vx9R8bF9ILquOUonPF3X7O S355ryvTo/CwMAtHqFnlEc8IqHMHeIrAZw7Hx+U9ZP74CXWoUgBGS2IkxQbR9rNe6h L0zfbrlpc4nxHiCY57UbCLe+NxXYy/urZpjI4ncbnK1rZWh6uFcEkEx6y7PIyvgiH3 tljYkrzskNyOQ== From: "Masami Hiramatsu (Google)" To: Steven Rostedt Cc: Tom Zanussi , Ingo Molnar , linux-kernel@vger.kernel.org Subject: [PATCH v4 4/5] tracing: Add .graph suffix option to histogram value Date: Sat, 27 Aug 2022 13:03:43 +0900 Message-Id: <166157302302.348924.9998983489821621084.stgit@devnote2> X-Mailer: git-send-email 2.25.1 In-Reply-To: <166157298537.348924.2537162090505397377.stgit@devnote2> References: <166157298537.348924.2537162090505397377.stgit@devnote2> User-Agent: StGit/0.19 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Masami Hiramatsu (Google) Add the .graph suffix which shows the bar graph of the histogram value. For example, the below example shows that the bar graph of the histogram of the runtime for each tasks. ------ # cd /sys/kernel/debug/tracing/ # echo hist:keys=pid:vals=runtime.graph:sort=pid > \ events/sched/sched_stat_runtime/trigger # sleep 10 # cat events/sched/sched_stat_runtime/hist # event histogram # # trigger info: hist:keys=pid:vals=hitcount,runtime.graph:sort=pid:size=2048 [active] # { pid: 14 } hitcount: 2 runtime: { pid: 16 } hitcount: 8 runtime: { pid: 26 } hitcount: 1 runtime: { pid: 57 } hitcount: 3 runtime: { pid: 61 } hitcount: 20 runtime: ### { pid: 66 } hitcount: 2 runtime: { pid: 70 } hitcount: 3 runtime: { pid: 72 } hitcount: 2 runtime: { pid: 145 } hitcount: 14 runtime: #################### { pid: 152 } hitcount: 5 runtime: ####### { pid: 153 } hitcount: 2 runtime: #### Totals: Hits: 62 Entries: 11 Dropped: 0 ------- Signed-off-by: Masami Hiramatsu (Google) --- Changes in v3: - Show hitcount.graph in trigger info correctly. - Show both hitcount.percent and hitcount.graph on the same histogram. Changes in v2: - Show an error when failing to calculate the percentage. --- kernel/trace/trace_events_hist.c | 82 +++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index af6c140f85e6..fceea784fded 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -507,6 +507,7 @@ enum hist_field_flags { HIST_FIELD_FL_BUCKET = 1 << 17, HIST_FIELD_FL_CONST = 1 << 18, HIST_FIELD_FL_PERCENT = 1 << 19, + HIST_FIELD_FL_GRAPH = 1 << 20, }; struct var_defs { @@ -1710,6 +1711,8 @@ static const char *get_hist_field_flags(struct hist_field *hist_field) flags_str = "usecs"; else if (hist_field->flags & HIST_FIELD_FL_PERCENT) flags_str = "percent"; + else if (hist_field->flags & HIST_FIELD_FL_GRAPH) + flags_str = "graph"; return flags_str; } @@ -2322,6 +2325,10 @@ parse_field(struct hist_trigger_data *hist_data, struct trace_event_file *file, if (*flags & (HIST_FIELD_FL_VAR | HIST_FIELD_FL_KEY)) goto error; *flags |= HIST_FIELD_FL_PERCENT; + } else if (strncmp(modifier, "graph", 5) == 0) { + if (*flags & (HIST_FIELD_FL_VAR | HIST_FIELD_FL_KEY)) + goto error; + *flags |= HIST_FIELD_FL_GRAPH; } else { error: hist_err(tr, HIST_ERR_BAD_FIELD_MODIFIER, errpos(modifier)); @@ -4362,6 +4369,9 @@ static int create_val_fields(struct hist_trigger_data *hist_data, if (strncmp(field_str + 8, ".percent", 8) == 0) hist_data->fields[HITCOUNT_IDX]->flags |= HIST_FIELD_FL_PERCENT; + if (strncmp(field_str + 8, ".graph", 8) == 0) + hist_data->fields[HITCOUNT_IDX]->flags |= + HIST_FIELD_FL_GRAPH; continue; } @@ -5316,20 +5326,52 @@ static inline unsigned int __get_percentage(u64 val, u64 total) return val ? UINT_MAX : 0; } +#define BAR_CHAR '#' + +static inline const char *__fill_bar_str(char *buf, int size, u64 val, u64 max) +{ + unsigned int len = __get_percentage(val, max); + int i; + + if (len == UINT_MAX) { + snprintf(buf, size, "[ERROR]"); + return buf; + } + + len = len * size / 10000; + for (i = 0; i < len && i < size; i++) + buf[i] = BAR_CHAR; + while (i < size) + buf[i++] = ' '; + buf[size] = '\0'; + + return buf; +} + +struct hist_val_stat { + u64 max; + u64 total; +}; + static void hist_trigger_print_val(struct seq_file *m, unsigned int idx, const char *field_name, unsigned long flags, - u64 *totals, struct tracing_map_elt *elt) + struct hist_val_stat *stats, + struct tracing_map_elt *elt) { u64 val = tracing_map_read_sum(elt, idx); unsigned int pc; + char bar[21]; if (flags & HIST_FIELD_FL_PERCENT) { - pc = __get_percentage(val, totals[idx]); + pc = __get_percentage(val, stats[idx].total); if (pc == UINT_MAX) seq_printf(m, " %s (%%):[ERROR]", field_name); else seq_printf(m, " %s (%%): %3u.%02u", field_name, pc / 100, pc % 100); + } else if (flags & HIST_FIELD_FL_GRAPH) { + seq_printf(m, " %s: %20s", field_name, + __fill_bar_str(bar, 20, val, stats[idx].max)); } else if (flags & HIST_FIELD_FL_HEX) { seq_printf(m, " %s: %10llx", field_name, val); } else { @@ -5339,7 +5381,7 @@ static void hist_trigger_print_val(struct seq_file *m, unsigned int idx, static void hist_trigger_entry_print(struct seq_file *m, struct hist_trigger_data *hist_data, - u64 *totals, + struct hist_val_stat *stats, void *key, struct tracing_map_elt *elt) { @@ -5350,7 +5392,7 @@ static void hist_trigger_entry_print(struct seq_file *m, hist_trigger_print_key(m, hist_data, key, elt); flags = hist_data->fields[i]->flags; - hist_trigger_print_val(m, i, "hitcount", flags, totals, elt); + hist_trigger_print_val(m, i, "hitcount", flags, stats, elt); for (i = 1; i < hist_data->n_vals; i++) { field_name = hist_field_name(hist_data->fields[i], 0); @@ -5360,7 +5402,7 @@ static void hist_trigger_entry_print(struct seq_file *m, continue; seq_puts(m, " "); - hist_trigger_print_val(m, i, field_name, flags, totals, elt); + hist_trigger_print_val(m, i, field_name, flags, stats, elt); } print_actions(m, hist_data, elt); @@ -5374,7 +5416,8 @@ static int print_entries(struct seq_file *m, struct tracing_map_sort_entry **sort_entries = NULL; struct tracing_map *map = hist_data->map; int i, j, n_entries; - u64 *totals = NULL; + struct hist_val_stat *stats = NULL; + u64 val; n_entries = tracing_map_sort_entries(map, hist_data->sort_keys, hist_data->n_sort_keys, @@ -5382,28 +5425,33 @@ static int print_entries(struct seq_file *m, if (n_entries < 0) return n_entries; + /* Calculate the max and the total for each field if needed. */ for (j = 0; j < hist_data->n_vals; j++) { - if (!(hist_data->fields[j]->flags & HIST_FIELD_FL_PERCENT)) + if (!(hist_data->fields[j]->flags & + (HIST_FIELD_FL_PERCENT | HIST_FIELD_FL_GRAPH))) continue; - if (!totals) { - totals = kcalloc(hist_data->n_vals, sizeof(u64), - GFP_KERNEL); - if (!totals) { + if (!stats) { + stats = kcalloc(hist_data->n_vals, sizeof(*stats), + GFP_KERNEL); + if (!stats) { n_entries = -ENOMEM; goto out; } } - for (i = 0; i < n_entries; i++) - totals[j] += tracing_map_read_sum( - sort_entries[i]->elt, j); + for (i = 0; i < n_entries; i++) { + val = tracing_map_read_sum(sort_entries[i]->elt, j); + stats[j].total += val; + if (stats[j].max < val) + stats[j].max = val; + } } for (i = 0; i < n_entries; i++) - hist_trigger_entry_print(m, hist_data, totals, + hist_trigger_entry_print(m, hist_data, stats, sort_entries[i]->key, sort_entries[i]->elt); - kfree(totals); + kfree(stats); out: tracing_map_destroy_sort_entries(sort_entries, n_entries); @@ -5828,6 +5876,8 @@ static int event_hist_trigger_print(struct seq_file *m, seq_puts(m, "hitcount"); if (field->flags & HIST_FIELD_FL_PERCENT) seq_puts(m, ".percent"); + else if (field->flags & HIST_FIELD_FL_GRAPH) + seq_puts(m, ".graph"); } else { seq_puts(m, ","); hist_field_print(m, field);