Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf streams: Report hot streams

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>

authored by

Jin Yao and committed by
Arnaldo Carvalho de Melo
5bbd6bad 28904f4d

+141
+13
tools/perf/util/callchain.c
··· 1699 1699 1700 1700 return chain_hits; 1701 1701 } 1702 + 1703 + s64 callchain_avg_cycles(struct callchain_node *cnode) 1704 + { 1705 + struct callchain_list *chain; 1706 + s64 cycles = 0; 1707 + 1708 + list_for_each_entry(chain, &cnode->val, list) { 1709 + if (chain->srcline && chain->branch_count) 1710 + cycles += chain->cycles_count / chain->branch_count; 1711 + } 1712 + 1713 + return cycles; 1714 + }
+2
tools/perf/util/callchain.h
··· 305 305 306 306 u64 callchain_total_hits(struct hists *hists); 307 307 308 + s64 callchain_avg_cycles(struct callchain_node *cnode); 309 + 308 310 #endif /* __PERF_CALLCHAIN_H */
+123
tools/perf/util/stream.c
··· 217 217 stream__link(base_stream, pair_stream); 218 218 } 219 219 } 220 + 221 + static void print_callchain_pair(struct stream *base_stream, int idx, 222 + struct evsel_streams *es_base, 223 + struct evsel_streams *es_pair) 224 + { 225 + struct callchain_node *base_cnode = base_stream->cnode; 226 + struct callchain_node *pair_cnode = base_stream->pair_cnode; 227 + struct callchain_list *base_chain, *pair_chain; 228 + char buf1[512], buf2[512], cbuf1[256], cbuf2[256]; 229 + char *s1, *s2; 230 + double pct; 231 + 232 + printf("\nhot chain pair %d:\n", idx); 233 + 234 + pct = (double)base_cnode->hit / (double)es_base->streams_hits; 235 + scnprintf(buf1, sizeof(buf1), "cycles: %ld, hits: %.2f%%", 236 + callchain_avg_cycles(base_cnode), pct * 100.0); 237 + 238 + pct = (double)pair_cnode->hit / (double)es_pair->streams_hits; 239 + scnprintf(buf2, sizeof(buf2), "cycles: %ld, hits: %.2f%%", 240 + callchain_avg_cycles(pair_cnode), pct * 100.0); 241 + 242 + printf("%35s\t%35s\n", buf1, buf2); 243 + 244 + printf("%35s\t%35s\n", 245 + "---------------------------", 246 + "--------------------------"); 247 + 248 + pair_chain = list_first_entry(&pair_cnode->val, 249 + struct callchain_list, 250 + list); 251 + 252 + list_for_each_entry(base_chain, &base_cnode->val, list) { 253 + if (&pair_chain->list == &pair_cnode->val) 254 + return; 255 + 256 + s1 = callchain_list__sym_name(base_chain, cbuf1, sizeof(cbuf1), 257 + false); 258 + s2 = callchain_list__sym_name(pair_chain, cbuf2, sizeof(cbuf2), 259 + false); 260 + 261 + scnprintf(buf1, sizeof(buf1), "%35s\t%35s", s1, s2); 262 + printf("%s\n", buf1); 263 + pair_chain = list_next_entry(pair_chain, list); 264 + } 265 + } 266 + 267 + static void print_stream_callchain(struct stream *stream, int idx, 268 + struct evsel_streams *es, bool pair) 269 + { 270 + struct callchain_node *cnode = stream->cnode; 271 + struct callchain_list *chain; 272 + char buf[512], cbuf[256], *s; 273 + double pct; 274 + 275 + printf("\nhot chain %d:\n", idx); 276 + 277 + pct = (double)cnode->hit / (double)es->streams_hits; 278 + scnprintf(buf, sizeof(buf), "cycles: %ld, hits: %.2f%%", 279 + callchain_avg_cycles(cnode), pct * 100.0); 280 + 281 + if (pair) { 282 + printf("%35s\t%35s\n", "", buf); 283 + printf("%35s\t%35s\n", 284 + "", "--------------------------"); 285 + } else { 286 + printf("%35s\n", buf); 287 + printf("%35s\n", "--------------------------"); 288 + } 289 + 290 + list_for_each_entry(chain, &cnode->val, list) { 291 + s = callchain_list__sym_name(chain, cbuf, sizeof(cbuf), false); 292 + 293 + if (pair) 294 + scnprintf(buf, sizeof(buf), "%35s\t%35s", "", s); 295 + else 296 + scnprintf(buf, sizeof(buf), "%35s", s); 297 + 298 + printf("%s\n", buf); 299 + } 300 + } 301 + 302 + static void callchain_streams_report(struct evsel_streams *es_base, 303 + struct evsel_streams *es_pair) 304 + { 305 + struct stream *base_stream; 306 + int i, idx = 0; 307 + 308 + printf("[ Matched hot streams ]\n"); 309 + for (i = 0; i < es_base->nr_streams; i++) { 310 + base_stream = &es_base->streams[i]; 311 + if (base_stream->pair_cnode) { 312 + print_callchain_pair(base_stream, ++idx, 313 + es_base, es_pair); 314 + } 315 + } 316 + 317 + idx = 0; 318 + printf("\n[ Hot streams in old perf data only ]\n"); 319 + for (i = 0; i < es_base->nr_streams; i++) { 320 + base_stream = &es_base->streams[i]; 321 + if (!base_stream->pair_cnode) { 322 + print_stream_callchain(base_stream, ++idx, 323 + es_base, false); 324 + } 325 + } 326 + 327 + idx = 0; 328 + printf("\n[ Hot streams in new perf data only ]\n"); 329 + for (i = 0; i < es_pair->nr_streams; i++) { 330 + base_stream = &es_pair->streams[i]; 331 + if (!base_stream->pair_cnode) { 332 + print_stream_callchain(base_stream, ++idx, 333 + es_pair, true); 334 + } 335 + } 336 + } 337 + 338 + void evsel_streams__report(struct evsel_streams *es_base, 339 + struct evsel_streams *es_pair) 340 + { 341 + return callchain_streams_report(es_base, es_pair); 342 + }
+3
tools/perf/util/stream.h
··· 35 35 void evsel_streams__match(struct evsel_streams *es_base, 36 36 struct evsel_streams *es_pair); 37 37 38 + void evsel_streams__report(struct evsel_streams *es_base, 39 + struct evsel_streams *es_pair); 40 + 38 41 #endif /* __PERF_STREAM_H */