^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Compare and figure out the top N hottest streams
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2020, Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Jin Yao
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "hist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "sort.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "stream.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "evlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static void evsel_streams__delete(struct evsel_streams *es, int nr_evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) for (int i = 0; i < nr_evsel; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) zfree(&es[i].streams);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) free(es);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) void evlist_streams__delete(struct evlist_streams *els)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) evsel_streams__delete(els->ev_streams, els->nr_evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) free(els);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static struct evlist_streams *evlist_streams__new(int nr_evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int nr_streams_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct evlist_streams *els;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct evsel_streams *es;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) els = zalloc(sizeof(*els));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (!els)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) es = calloc(nr_evsel, sizeof(struct evsel_streams));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (!es) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) free(els);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) for (int i = 0; i < nr_evsel; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct evsel_streams *s = &es[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) s->streams = calloc(nr_streams_max, sizeof(struct stream));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (!s->streams)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) s->nr_streams_max = nr_streams_max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) s->evsel_idx = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) els->ev_streams = es;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) els->nr_evsel = nr_evsel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return els;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) evsel_streams__delete(es, nr_evsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * The cnodes with high hit number are hot callchains.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static void evsel_streams__set_hot_cnode(struct evsel_streams *es,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) struct callchain_node *cnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int i, idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u64 hit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (es->nr_streams < es->nr_streams_max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) i = es->nr_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) es->streams[i].cnode = cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) es->nr_streams++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * Considering a few number of hot streams, only use simple
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * way to find the cnode with smallest hit number and replace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) hit = (es->streams[0].cnode)->hit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) for (i = 1; i < es->nr_streams; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if ((es->streams[i].cnode)->hit < hit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) hit = (es->streams[i].cnode)->hit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) idx = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (cnode->hit > hit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) es->streams[idx].cnode = cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static void update_hot_callchain(struct hist_entry *he,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct evsel_streams *es)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct rb_root *root = &he->sorted_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct rb_node *rb_node = rb_first(root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) struct callchain_node *cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) while (rb_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) cnode = rb_entry(rb_node, struct callchain_node, rb_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) evsel_streams__set_hot_cnode(es, cnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) rb_node = rb_next(rb_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static void init_hot_callchain(struct hists *hists, struct evsel_streams *es)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct rb_node *next = rb_first_cached(&hists->entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) while (next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct hist_entry *he;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) he = rb_entry(next, struct hist_entry, rb_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) update_hot_callchain(he, es);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) next = rb_next(&he->rb_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) es->streams_hits = callchain_total_hits(hists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int evlist__init_callchain_streams(struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) struct evlist_streams *els)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct evsel_streams *es = els->ev_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct evsel *pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) BUG_ON(els->nr_evsel < evlist->core.nr_entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) evlist__for_each_entry(evlist, pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) struct hists *hists = evsel__hists(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) hists__output_resort(hists, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) init_hot_callchain(hists, &es[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) es[i].evsel_idx = pos->idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct evlist_streams *evlist__create_streams(struct evlist *evlist,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int nr_streams_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int nr_evsel = evlist->core.nr_entries, ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct evlist_streams *els = evlist_streams__new(nr_evsel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) nr_streams_max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (!els)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) ret = evlist__init_callchain_streams(evlist, els);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) evlist_streams__delete(els);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return els;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct evsel_streams *evsel_streams__entry(struct evlist_streams *els,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) int evsel_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct evsel_streams *es = els->ev_streams;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) for (int i = 0; i < els->nr_evsel; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (es[i].evsel_idx == evsel_idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return &es[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static struct stream *stream__callchain_match(struct stream *base_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct evsel_streams *es_pair)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) for (int i = 0; i < es_pair->nr_streams; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) struct stream *pair_stream = &es_pair->streams[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (callchain_cnode_matched(base_stream->cnode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) pair_stream->cnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) return pair_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static struct stream *stream__match(struct stream *base_stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct evsel_streams *es_pair)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return stream__callchain_match(base_stream, es_pair);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static void stream__link(struct stream *base_stream, struct stream *pair_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) base_stream->pair_cnode = pair_stream->cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) pair_stream->pair_cnode = base_stream->cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) void evsel_streams__match(struct evsel_streams *es_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct evsel_streams *es_pair)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) for (int i = 0; i < es_base->nr_streams; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct stream *base_stream = &es_base->streams[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct stream *pair_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) pair_stream = stream__match(base_stream, es_pair);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (pair_stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) stream__link(base_stream, pair_stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static void print_callchain_pair(struct stream *base_stream, int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct evsel_streams *es_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct evsel_streams *es_pair)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) struct callchain_node *base_cnode = base_stream->cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct callchain_node *pair_cnode = base_stream->pair_cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct callchain_list *base_chain, *pair_chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) char buf1[512], buf2[512], cbuf1[256], cbuf2[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) char *s1, *s2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) double pct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) printf("\nhot chain pair %d:\n", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) pct = (double)base_cnode->hit / (double)es_base->streams_hits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) scnprintf(buf1, sizeof(buf1), "cycles: %ld, hits: %.2f%%",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) callchain_avg_cycles(base_cnode), pct * 100.0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) pct = (double)pair_cnode->hit / (double)es_pair->streams_hits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) scnprintf(buf2, sizeof(buf2), "cycles: %ld, hits: %.2f%%",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) callchain_avg_cycles(pair_cnode), pct * 100.0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) printf("%35s\t%35s\n", buf1, buf2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) printf("%35s\t%35s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) "---------------------------",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) "--------------------------");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) pair_chain = list_first_entry(&pair_cnode->val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct callchain_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) list_for_each_entry(base_chain, &base_cnode->val, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (&pair_chain->list == &pair_cnode->val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) s1 = callchain_list__sym_name(base_chain, cbuf1, sizeof(cbuf1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) s2 = callchain_list__sym_name(pair_chain, cbuf2, sizeof(cbuf2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) scnprintf(buf1, sizeof(buf1), "%35s\t%35s", s1, s2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) printf("%s\n", buf1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) pair_chain = list_next_entry(pair_chain, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static void print_stream_callchain(struct stream *stream, int idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct evsel_streams *es, bool pair)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct callchain_node *cnode = stream->cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct callchain_list *chain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) char buf[512], cbuf[256], *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) double pct;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) printf("\nhot chain %d:\n", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) pct = (double)cnode->hit / (double)es->streams_hits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) scnprintf(buf, sizeof(buf), "cycles: %ld, hits: %.2f%%",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) callchain_avg_cycles(cnode), pct * 100.0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (pair) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) printf("%35s\t%35s\n", "", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) printf("%35s\t%35s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) "", "--------------------------");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) printf("%35s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) printf("%35s\n", "--------------------------");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) list_for_each_entry(chain, &cnode->val, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) s = callchain_list__sym_name(chain, cbuf, sizeof(cbuf), false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (pair)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) scnprintf(buf, sizeof(buf), "%35s\t%35s", "", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) scnprintf(buf, sizeof(buf), "%35s", s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) printf("%s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) static void callchain_streams_report(struct evsel_streams *es_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct evsel_streams *es_pair)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) struct stream *base_stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) int i, idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) printf("[ Matched hot streams ]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) for (i = 0; i < es_base->nr_streams; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) base_stream = &es_base->streams[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (base_stream->pair_cnode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) print_callchain_pair(base_stream, ++idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) es_base, es_pair);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) printf("\n[ Hot streams in old perf data only ]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) for (i = 0; i < es_base->nr_streams; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) base_stream = &es_base->streams[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (!base_stream->pair_cnode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) print_stream_callchain(base_stream, ++idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) es_base, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) printf("\n[ Hot streams in new perf data only ]\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) for (i = 0; i < es_pair->nr_streams; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) base_stream = &es_pair->streams[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (!base_stream->pair_cnode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) print_stream_callchain(base_stream, ++idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) es_pair, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) void evsel_streams__report(struct evsel_streams *es_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct evsel_streams *es_pair)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return callchain_streams_report(es_base, es_pair);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }