]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
perf streams: Report hot streams
authorJin Yao <yao.jin@linux.intel.com>
Fri, 9 Oct 2020 02:28:44 +0000 (10:28 +0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 14 Oct 2020 16:34:26 +0000 (13:34 -0300)
We show the streams separately. They are divided into different sections.

1. "Matched hot streams"

2. "Hot streams in old perf data only"

3. "Hot streams in new perf data only".

For each stream, we report the cycles and hot percent (hits%).

For example,

     cycles: 2, hits: 4.08%
 --------------------------
              main div.c:42
      compute_flag div.c:28

Signed-off-by: Jin Yao <yao.jin@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20201009022845.13141-7-yao.jin@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/callchain.c
tools/perf/util/callchain.h
tools/perf/util/stream.c
tools/perf/util/stream.h

index 4f824bfcc072b4e6f744686114e26364d52a306b..1b60985690bba31333e99e0892cc40c31f0592cd 100644 (file)
@@ -1699,3 +1699,16 @@ u64 callchain_total_hits(struct hists *hists)
 
        return chain_hits;
 }
+
+s64 callchain_avg_cycles(struct callchain_node *cnode)
+{
+       struct callchain_list *chain;
+       s64 cycles = 0;
+
+       list_for_each_entry(chain, &cnode->val, list) {
+               if (chain->srcline && chain->branch_count)
+                       cycles += chain->cycles_count / chain->branch_count;
+       }
+
+       return cycles;
+}
index ac5bea9c1eb789ef138ed46cbf2c78de42df7124..5824134f983b001cfe38474122c1bfbc41ccbbde 100644 (file)
@@ -305,4 +305,6 @@ bool callchain_cnode_matched(struct callchain_node *base_cnode,
 
 u64 callchain_total_hits(struct hists *hists);
 
+s64 callchain_avg_cycles(struct callchain_node *cnode);
+
 #endif /* __PERF_CALLCHAIN_H */
index 47c5956b3378c500ecc0f0b55a6310faaefb9b9a..4bd5e5a00aa5ee8a5a90a347582a7e261d4d46d3 100644 (file)
@@ -217,3 +217,126 @@ void evsel_streams__match(struct evsel_streams *es_base,
                        stream__link(base_stream, pair_stream);
        }
 }
+
+static void print_callchain_pair(struct stream *base_stream, int idx,
+                                struct evsel_streams *es_base,
+                                struct evsel_streams *es_pair)
+{
+       struct callchain_node *base_cnode = base_stream->cnode;
+       struct callchain_node *pair_cnode = base_stream->pair_cnode;
+       struct callchain_list *base_chain, *pair_chain;
+       char buf1[512], buf2[512], cbuf1[256], cbuf2[256];
+       char *s1, *s2;
+       double pct;
+
+       printf("\nhot chain pair %d:\n", idx);
+
+       pct = (double)base_cnode->hit / (double)es_base->streams_hits;
+       scnprintf(buf1, sizeof(buf1), "cycles: %ld, hits: %.2f%%",
+                 callchain_avg_cycles(base_cnode), pct * 100.0);
+
+       pct = (double)pair_cnode->hit / (double)es_pair->streams_hits;
+       scnprintf(buf2, sizeof(buf2), "cycles: %ld, hits: %.2f%%",
+                 callchain_avg_cycles(pair_cnode), pct * 100.0);
+
+       printf("%35s\t%35s\n", buf1, buf2);
+
+       printf("%35s\t%35s\n",
+              "---------------------------",
+              "--------------------------");
+
+       pair_chain = list_first_entry(&pair_cnode->val,
+                                     struct callchain_list,
+                                     list);
+
+       list_for_each_entry(base_chain, &base_cnode->val, list) {
+               if (&pair_chain->list == &pair_cnode->val)
+                       return;
+
+               s1 = callchain_list__sym_name(base_chain, cbuf1, sizeof(cbuf1),
+                                             false);
+               s2 = callchain_list__sym_name(pair_chain, cbuf2, sizeof(cbuf2),
+                                             false);
+
+               scnprintf(buf1, sizeof(buf1), "%35s\t%35s", s1, s2);
+               printf("%s\n", buf1);
+               pair_chain = list_next_entry(pair_chain, list);
+       }
+}
+
+static void print_stream_callchain(struct stream *stream, int idx,
+                                  struct evsel_streams *es, bool pair)
+{
+       struct callchain_node *cnode = stream->cnode;
+       struct callchain_list *chain;
+       char buf[512], cbuf[256], *s;
+       double pct;
+
+       printf("\nhot chain %d:\n", idx);
+
+       pct = (double)cnode->hit / (double)es->streams_hits;
+       scnprintf(buf, sizeof(buf), "cycles: %ld, hits: %.2f%%",
+                 callchain_avg_cycles(cnode), pct * 100.0);
+
+       if (pair) {
+               printf("%35s\t%35s\n", "", buf);
+               printf("%35s\t%35s\n",
+                      "", "--------------------------");
+       } else {
+               printf("%35s\n", buf);
+               printf("%35s\n", "--------------------------");
+       }
+
+       list_for_each_entry(chain, &cnode->val, list) {
+               s = callchain_list__sym_name(chain, cbuf, sizeof(cbuf), false);
+
+               if (pair)
+                       scnprintf(buf, sizeof(buf), "%35s\t%35s", "", s);
+               else
+                       scnprintf(buf, sizeof(buf), "%35s", s);
+
+               printf("%s\n", buf);
+       }
+}
+
+static void callchain_streams_report(struct evsel_streams *es_base,
+                                    struct evsel_streams *es_pair)
+{
+       struct stream *base_stream;
+       int i, idx = 0;
+
+       printf("[ Matched hot streams ]\n");
+       for (i = 0; i < es_base->nr_streams; i++) {
+               base_stream = &es_base->streams[i];
+               if (base_stream->pair_cnode) {
+                       print_callchain_pair(base_stream, ++idx,
+                                            es_base, es_pair);
+               }
+       }
+
+       idx = 0;
+       printf("\n[ Hot streams in old perf data only ]\n");
+       for (i = 0; i < es_base->nr_streams; i++) {
+               base_stream = &es_base->streams[i];
+               if (!base_stream->pair_cnode) {
+                       print_stream_callchain(base_stream, ++idx,
+                                              es_base, false);
+               }
+       }
+
+       idx = 0;
+       printf("\n[ Hot streams in new perf data only ]\n");
+       for (i = 0; i < es_pair->nr_streams; i++) {
+               base_stream = &es_pair->streams[i];
+               if (!base_stream->pair_cnode) {
+                       print_stream_callchain(base_stream, ++idx,
+                                              es_pair, true);
+               }
+       }
+}
+
+void evsel_streams__report(struct evsel_streams *es_base,
+                          struct evsel_streams *es_pair)
+{
+       return callchain_streams_report(es_base, es_pair);
+}
index a61072eda64db028767c7bef7ae85aed2a208618..bee768874feaa65787966fa24972a03472371c4a 100644 (file)
@@ -35,4 +35,7 @@ struct evsel_streams *evsel_streams__entry(struct evlist_streams *els,
 void evsel_streams__match(struct evsel_streams *es_base,
                          struct evsel_streams *es_pair);
 
+void evsel_streams__report(struct evsel_streams *es_base,
+                          struct evsel_streams *es_pair);
+
 #endif /* __PERF_STREAM_H */