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

perf report: Add latency output field

Latency output field is similar to overhead, but represents overhead for
latency rather than CPU consumption. It's re-scaled from overhead by dividing
weight by the current parallelism level at the time of the sample.
It effectively models profiling with 1 sample taken per unit of wall-clock
time rather than unit of CPU time.

Signed-off-by: Dmitry Vyukov <dvyukov@google.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Link: https://lore.kernel.org/r/b6269518758c2166e6ffdc2f0e24cfdecc8ef9c1.1739437531.git.dvyukov@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Dmitry Vyukov and committed by
Namhyung Kim
ee1cffbe 61b6b31c

+120 -55
+17 -10
tools/perf/ui/browsers/hists.c
··· 1226 1226 return ret; 1227 1227 } 1228 1228 1229 - #define __HPP_COLOR_PERCENT_FN(_type, _field) \ 1229 + #define __HPP_COLOR_PERCENT_FN(_type, _field, _fmttype) \ 1230 1230 static u64 __hpp_get_##_field(struct hist_entry *he) \ 1231 1231 { \ 1232 1232 return he->stat._field; \ ··· 1238 1238 struct hist_entry *he) \ 1239 1239 { \ 1240 1240 return hpp__fmt(fmt, hpp, he, __hpp_get_##_field, " %*.2f%%", \ 1241 - __hpp__slsmg_color_printf, true); \ 1241 + __hpp__slsmg_color_printf, _fmttype); \ 1242 1242 } 1243 1243 1244 - #define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 1244 + #define __HPP_COLOR_ACC_PERCENT_FN(_type, _field, _fmttype) \ 1245 1245 static u64 __hpp_get_acc_##_field(struct hist_entry *he) \ 1246 1246 { \ 1247 1247 return he->stat_acc->_field; \ ··· 1262 1262 return ret; \ 1263 1263 } \ 1264 1264 return hpp__fmt(fmt, hpp, he, __hpp_get_acc_##_field, \ 1265 - " %*.2f%%", __hpp__slsmg_color_printf, true); \ 1265 + " %*.2f%%", __hpp__slsmg_color_printf, \ 1266 + _fmttype); \ 1266 1267 } 1267 1268 1268 - __HPP_COLOR_PERCENT_FN(overhead, period) 1269 - __HPP_COLOR_PERCENT_FN(overhead_sys, period_sys) 1270 - __HPP_COLOR_PERCENT_FN(overhead_us, period_us) 1271 - __HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys) 1272 - __HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us) 1273 - __HPP_COLOR_ACC_PERCENT_FN(overhead_acc, period) 1269 + __HPP_COLOR_PERCENT_FN(overhead, period, PERF_HPP_FMT_TYPE__PERCENT) 1270 + __HPP_COLOR_PERCENT_FN(latency, latency, PERF_HPP_FMT_TYPE__LATENCY) 1271 + __HPP_COLOR_PERCENT_FN(overhead_sys, period_sys, PERF_HPP_FMT_TYPE__PERCENT) 1272 + __HPP_COLOR_PERCENT_FN(overhead_us, period_us, PERF_HPP_FMT_TYPE__PERCENT) 1273 + __HPP_COLOR_PERCENT_FN(overhead_guest_sys, period_guest_sys, PERF_HPP_FMT_TYPE__PERCENT) 1274 + __HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us, PERF_HPP_FMT_TYPE__PERCENT) 1275 + __HPP_COLOR_ACC_PERCENT_FN(overhead_acc, period, PERF_HPP_FMT_TYPE__PERCENT) 1276 + __HPP_COLOR_ACC_PERCENT_FN(latency_acc, latency, PERF_HPP_FMT_TYPE__LATENCY) 1274 1277 1275 1278 #undef __HPP_COLOR_PERCENT_FN 1276 1279 #undef __HPP_COLOR_ACC_PERCENT_FN ··· 1282 1279 { 1283 1280 perf_hpp__format[PERF_HPP__OVERHEAD].color = 1284 1281 hist_browser__hpp_color_overhead; 1282 + perf_hpp__format[PERF_HPP__LATENCY].color = 1283 + hist_browser__hpp_color_latency; 1285 1284 perf_hpp__format[PERF_HPP__OVERHEAD_SYS].color = 1286 1285 hist_browser__hpp_color_overhead_sys; 1287 1286 perf_hpp__format[PERF_HPP__OVERHEAD_US].color = ··· 1294 1289 hist_browser__hpp_color_overhead_guest_us; 1295 1290 perf_hpp__format[PERF_HPP__OVERHEAD_ACC].color = 1296 1291 hist_browser__hpp_color_overhead_acc; 1292 + perf_hpp__format[PERF_HPP__LATENCY_ACC].color = 1293 + hist_browser__hpp_color_latency_acc; 1297 1294 1298 1295 res_sample_init(); 1299 1296 }
+38 -31
tools/perf/ui/hist.c
··· 27 27 int nr_samples, const char *fmt, int len, 28 28 hpp_snprint_fn print_fn, enum perf_hpp_fmt_type fmtype) 29 29 { 30 - if (fmtype == PERF_HPP_FMT_TYPE__PERCENT) { 30 + if (fmtype == PERF_HPP_FMT_TYPE__PERCENT || fmtype == PERF_HPP_FMT_TYPE__LATENCY) { 31 31 double percent = 0.0; 32 - u64 total = hists__total_period(hists); 32 + u64 total = fmtype == PERF_HPP_FMT_TYPE__PERCENT ? hists__total_period(hists) : 33 + hists__total_latency(hists); 33 34 34 35 if (total) 35 36 percent = 100.0 * val / total; ··· 129 128 print_fn, fmtype); 130 129 } 131 130 132 - if (fmtype == PERF_HPP_FMT_TYPE__PERCENT) 131 + if (fmtype == PERF_HPP_FMT_TYPE__PERCENT || fmtype == PERF_HPP_FMT_TYPE__LATENCY) 133 132 len -= 2; /* 2 for a space and a % sign */ 134 133 else 135 134 len -= 1; ··· 357 356 return (ret >= ssize) ? (ssize - 1) : ret; 358 357 } 359 358 360 - #define __HPP_COLOR_PERCENT_FN(_type, _field) \ 359 + #define __HPP_COLOR_PERCENT_FN(_type, _field, _fmttype) \ 361 360 static u64 he_get_##_field(struct hist_entry *he) \ 362 361 { \ 363 362 return he->stat._field; \ ··· 367 366 struct perf_hpp *hpp, struct hist_entry *he) \ 368 367 { \ 369 368 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \ 370 - hpp_color_scnprintf, PERF_HPP_FMT_TYPE__PERCENT); \ 369 + hpp_color_scnprintf, _fmttype); \ 371 370 } 372 371 373 - #define __HPP_ENTRY_PERCENT_FN(_type, _field) \ 372 + #define __HPP_ENTRY_PERCENT_FN(_type, _field, _fmttype) \ 374 373 static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \ 375 374 struct perf_hpp *hpp, struct hist_entry *he) \ 376 375 { \ 377 376 return hpp__fmt(fmt, hpp, he, he_get_##_field, " %*.2f%%", \ 378 - hpp_entry_scnprintf, PERF_HPP_FMT_TYPE__PERCENT); \ 377 + hpp_entry_scnprintf, _fmttype); \ 379 378 } 380 379 381 380 #define __HPP_SORT_FN(_type, _field) \ ··· 385 384 return __hpp__sort(a, b, he_get_##_field); \ 386 385 } 387 386 388 - #define __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 387 + #define __HPP_COLOR_ACC_PERCENT_FN(_type, _field, _fmttype) \ 389 388 static u64 he_get_acc_##_field(struct hist_entry *he) \ 390 389 { \ 391 390 return he->stat_acc->_field; \ ··· 395 394 struct perf_hpp *hpp, struct hist_entry *he) \ 396 395 { \ 397 396 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \ 398 - hpp_color_scnprintf, PERF_HPP_FMT_TYPE__PERCENT); \ 397 + hpp_color_scnprintf, _fmttype); \ 399 398 } 400 399 401 - #define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 400 + #define __HPP_ENTRY_ACC_PERCENT_FN(_type, _field, _fmttype) \ 402 401 static int hpp__entry_##_type(struct perf_hpp_fmt *fmt, \ 403 402 struct perf_hpp *hpp, struct hist_entry *he) \ 404 403 { \ 405 404 return hpp__fmt_acc(fmt, hpp, he, he_get_acc_##_field, " %*.2f%%", \ 406 - hpp_entry_scnprintf, PERF_HPP_FMT_TYPE__PERCENT); \ 405 + hpp_entry_scnprintf, _fmttype); \ 407 406 } 408 407 409 408 #define __HPP_SORT_ACC_FN(_type, _field) \ ··· 454 453 } 455 454 456 455 457 - #define HPP_PERCENT_FNS(_type, _field) \ 458 - __HPP_COLOR_PERCENT_FN(_type, _field) \ 459 - __HPP_ENTRY_PERCENT_FN(_type, _field) \ 456 + #define HPP_PERCENT_FNS(_type, _field, _fmttype) \ 457 + __HPP_COLOR_PERCENT_FN(_type, _field, _fmttype) \ 458 + __HPP_ENTRY_PERCENT_FN(_type, _field, _fmttype) \ 460 459 __HPP_SORT_FN(_type, _field) 461 460 462 - #define HPP_PERCENT_ACC_FNS(_type, _field) \ 463 - __HPP_COLOR_ACC_PERCENT_FN(_type, _field) \ 464 - __HPP_ENTRY_ACC_PERCENT_FN(_type, _field) \ 461 + #define HPP_PERCENT_ACC_FNS(_type, _field, _fmttype) \ 462 + __HPP_COLOR_ACC_PERCENT_FN(_type, _field, _fmttype) \ 463 + __HPP_ENTRY_ACC_PERCENT_FN(_type, _field, _fmttype) \ 465 464 __HPP_SORT_ACC_FN(_type, _field) 466 465 467 466 #define HPP_RAW_FNS(_type, _field) \ ··· 472 471 __HPP_ENTRY_AVERAGE_FN(_type, _field) \ 473 472 __HPP_SORT_AVERAGE_FN(_type, _field) 474 473 475 - HPP_PERCENT_FNS(overhead, period) 476 - HPP_PERCENT_FNS(overhead_sys, period_sys) 477 - HPP_PERCENT_FNS(overhead_us, period_us) 478 - HPP_PERCENT_FNS(overhead_guest_sys, period_guest_sys) 479 - HPP_PERCENT_FNS(overhead_guest_us, period_guest_us) 480 - HPP_PERCENT_ACC_FNS(overhead_acc, period) 474 + HPP_PERCENT_FNS(overhead, period, PERF_HPP_FMT_TYPE__PERCENT) 475 + HPP_PERCENT_FNS(latency, latency, PERF_HPP_FMT_TYPE__LATENCY) 476 + HPP_PERCENT_FNS(overhead_sys, period_sys, PERF_HPP_FMT_TYPE__PERCENT) 477 + HPP_PERCENT_FNS(overhead_us, period_us, PERF_HPP_FMT_TYPE__PERCENT) 478 + HPP_PERCENT_FNS(overhead_guest_sys, period_guest_sys, PERF_HPP_FMT_TYPE__PERCENT) 479 + HPP_PERCENT_FNS(overhead_guest_us, period_guest_us, PERF_HPP_FMT_TYPE__PERCENT) 480 + HPP_PERCENT_ACC_FNS(overhead_acc, period, PERF_HPP_FMT_TYPE__PERCENT) 481 + HPP_PERCENT_ACC_FNS(latency_acc, latency, PERF_HPP_FMT_TYPE__LATENCY) 481 482 482 483 HPP_RAW_FNS(samples, nr_events) 483 484 HPP_RAW_FNS(period, period) ··· 551 548 552 549 struct perf_hpp_fmt perf_hpp__format[] = { 553 550 HPP__COLOR_PRINT_FNS("Overhead", overhead, OVERHEAD), 551 + HPP__COLOR_PRINT_FNS("Latency", latency, LATENCY), 554 552 HPP__COLOR_PRINT_FNS("sys", overhead_sys, OVERHEAD_SYS), 555 553 HPP__COLOR_PRINT_FNS("usr", overhead_us, OVERHEAD_US), 556 554 HPP__COLOR_PRINT_FNS("guest sys", overhead_guest_sys, OVERHEAD_GUEST_SYS), 557 555 HPP__COLOR_PRINT_FNS("guest usr", overhead_guest_us, OVERHEAD_GUEST_US), 558 556 HPP__COLOR_ACC_PRINT_FNS("Children", overhead_acc, OVERHEAD_ACC), 557 + HPP__COLOR_ACC_PRINT_FNS("Latency", latency_acc, LATENCY_ACC), 559 558 HPP__PRINT_FNS("Samples", samples, SAMPLES), 560 559 HPP__PRINT_FNS("Period", period, PERIOD), 561 560 HPP__PRINT_FNS("Weight1", weight1, WEIGHT1), ··· 604 599 605 600 if (fmt->free) 606 601 fmt->free(fmt); 602 + } 603 + 604 + static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) 605 + { 606 + return a->equal && a->equal(a, b); 607 607 } 608 608 609 609 void perf_hpp__init(void) ··· 681 671 682 672 void perf_hpp__cancel_cumulate(void) 683 673 { 684 - struct perf_hpp_fmt *fmt, *acc, *ovh, *tmp; 674 + struct perf_hpp_fmt *fmt, *acc, *ovh, *acc_lat, *tmp; 685 675 686 676 if (is_strict_order(field_order)) 687 677 return; 688 678 689 679 ovh = &perf_hpp__format[PERF_HPP__OVERHEAD]; 690 680 acc = &perf_hpp__format[PERF_HPP__OVERHEAD_ACC]; 681 + acc_lat = &perf_hpp__format[PERF_HPP__LATENCY_ACC]; 691 682 692 683 perf_hpp_list__for_each_format_safe(&perf_hpp_list, fmt, tmp) { 693 - if (acc->equal(acc, fmt)) { 684 + if (fmt_equal(acc, fmt) || fmt_equal(acc_lat, fmt)) { 694 685 perf_hpp__column_unregister(fmt); 695 686 continue; 696 687 } 697 688 698 - if (ovh->equal(ovh, fmt)) 689 + if (fmt_equal(ovh, fmt)) 699 690 fmt->name = "Overhead"; 700 691 } 701 - } 702 - 703 - static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) 704 - { 705 - return a->equal && a->equal(a, b); 706 692 } 707 693 708 694 void perf_hpp__setup_output_field(struct perf_hpp_list *list) ··· 825 819 826 820 switch (fmt->idx) { 827 821 case PERF_HPP__OVERHEAD: 822 + case PERF_HPP__LATENCY: 828 823 case PERF_HPP__OVERHEAD_SYS: 829 824 case PERF_HPP__OVERHEAD_US: 830 825 case PERF_HPP__OVERHEAD_ACC:
+2
tools/perf/util/addr_location.h
··· 23 23 s32 socket; 24 24 /* Same as machine.parallelism but within [1, nr_cpus]. */ 25 25 int parallelism; 26 + /* See he_stat.latency. */ 27 + u64 latency; 26 28 }; 27 29 28 30 void addr_location__init(struct addr_location *al);
+6
tools/perf/util/event.c
··· 771 771 al->parallelism = max(1, min(machine->parallelism, machine__nr_cpus_avail(machine))); 772 772 if (test_bit(al->parallelism, symbol_conf.parallelism_filter)) 773 773 al->filtered |= (1 << HIST_FILTER__PARALLELISM); 774 + /* 775 + * Multiply it by some const to avoid precision loss or dealing 776 + * with floats. The multiplier does not matter otherwise since 777 + * we only print it as percents. 778 + */ 779 + al->latency = sample->period * 1000 / al->parallelism; 774 780 775 781 if (al->map) { 776 782 if (symbol_conf.dso_list &&
+2
tools/perf/util/events_stats.h
··· 57 57 struct hists_stats { 58 58 u64 total_period; 59 59 u64 total_non_filtered_period; 60 + u64 total_latency; 61 + u64 total_non_filtered_latency; 60 62 u32 nr_samples; 61 63 u32 nr_non_filtered_samples; 62 64 u32 nr_lost_samples;
+41 -14
tools/perf/util/hist.c
··· 305 305 return htime; 306 306 } 307 307 308 - static void he_stat__add_period(struct he_stat *he_stat, u64 period) 308 + static void he_stat__add_period(struct he_stat *he_stat, u64 period, u64 latency) 309 309 { 310 310 he_stat->period += period; 311 + he_stat->latency += latency; 311 312 he_stat->nr_events += 1; 312 313 } 313 314 ··· 323 322 dest->weight2 += src->weight2; 324 323 dest->weight3 += src->weight3; 325 324 dest->nr_events += src->nr_events; 325 + dest->latency += src->latency; 326 326 } 327 327 328 328 static void he_stat__decay(struct he_stat *he_stat) ··· 333 331 he_stat->weight1 = (he_stat->weight1 * 7) / 8; 334 332 he_stat->weight2 = (he_stat->weight2 * 7) / 8; 335 333 he_stat->weight3 = (he_stat->weight3 * 7) / 8; 334 + he_stat->latency = (he_stat->latency * 7) / 8; 336 335 } 337 336 338 337 static void hists__delete_entry(struct hists *hists, struct hist_entry *he); ··· 341 338 static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) 342 339 { 343 340 u64 prev_period = he->stat.period; 344 - u64 diff; 341 + u64 prev_latency = he->stat.latency; 345 342 346 343 if (prev_period == 0) 347 344 return true; ··· 351 348 he_stat__decay(he->stat_acc); 352 349 decay_callchain(he->callchain); 353 350 354 - diff = prev_period - he->stat.period; 355 - 356 351 if (!he->depth) { 357 - hists->stats.total_period -= diff; 358 - if (!he->filtered) 359 - hists->stats.total_non_filtered_period -= diff; 352 + u64 period_diff = prev_period - he->stat.period; 353 + u64 latency_diff = prev_latency - he->stat.latency; 354 + 355 + hists->stats.total_period -= period_diff; 356 + hists->stats.total_latency -= latency_diff; 357 + if (!he->filtered) { 358 + hists->stats.total_non_filtered_period -= period_diff; 359 + hists->stats.total_non_filtered_latency -= latency_diff; 360 + } 360 361 } 361 362 362 363 if (!he->leaf) { ··· 375 368 } 376 369 } 377 370 378 - return he->stat.period == 0; 371 + return he->stat.period == 0 && he->stat.latency == 0; 379 372 } 380 373 381 374 static void hists__delete_entry(struct hists *hists, struct hist_entry *he) ··· 601 594 return 0; 602 595 } 603 596 604 - static void hist_entry__add_callchain_period(struct hist_entry *he, u64 period) 597 + static void hist_entry__add_callchain_period(struct hist_entry *he, u64 period, u64 latency) 605 598 { 606 599 if (!hist_entry__has_callchains(he) || !symbol_conf.use_callchain) 607 600 return; 608 601 609 602 he->hists->callchain_period += period; 610 - if (!he->filtered) 603 + he->hists->callchain_latency += latency; 604 + if (!he->filtered) { 611 605 he->hists->callchain_non_filtered_period += period; 606 + he->hists->callchain_non_filtered_latency += latency; 607 + } 612 608 } 613 609 614 610 static struct hist_entry *hists__findnew_entry(struct hists *hists, ··· 624 614 struct hist_entry *he; 625 615 int64_t cmp; 626 616 u64 period = entry->stat.period; 617 + u64 latency = entry->stat.latency; 627 618 bool leftmost = true; 628 619 629 620 p = &hists->entries_in->rb_root.rb_node; ··· 643 632 if (!cmp) { 644 633 if (sample_self) { 645 634 he_stat__add_stat(&he->stat, &entry->stat); 646 - hist_entry__add_callchain_period(he, period); 635 + hist_entry__add_callchain_period(he, period, latency); 647 636 } 648 637 if (symbol_conf.cumulate_callchain) 649 - he_stat__add_period(he->stat_acc, period); 638 + he_stat__add_period(he->stat_acc, period, latency); 650 639 651 640 block_info__delete(entry->block_info); 652 641 ··· 683 672 return NULL; 684 673 685 674 if (sample_self) 686 - hist_entry__add_callchain_period(he, period); 675 + hist_entry__add_callchain_period(he, period, latency); 687 676 hists->nr_entries++; 688 677 689 678 rb_link_node(&he->rb_node_in, parent, p); ··· 762 751 .weight1 = sample->weight, 763 752 .weight2 = sample->ins_lat, 764 753 .weight3 = sample->p_stage_cyc, 754 + .latency = al->latency, 765 755 }, 766 756 .parent = sym_parent, 767 757 .filtered = symbol__parent_filter(sym_parent) | al->filtered, ··· 1780 1768 { 1781 1769 hists->nr_non_filtered_entries = 0; 1782 1770 hists->stats.total_non_filtered_period = 0; 1771 + hists->stats.total_non_filtered_latency = 0; 1783 1772 } 1784 1773 1785 1774 void hists__reset_stats(struct hists *hists) 1786 1775 { 1787 1776 hists->nr_entries = 0; 1788 1777 hists->stats.total_period = 0; 1778 + hists->stats.total_latency = 0; 1789 1779 1790 1780 hists__reset_filter_stats(hists); 1791 1781 } ··· 1796 1782 { 1797 1783 hists->nr_non_filtered_entries++; 1798 1784 hists->stats.total_non_filtered_period += h->stat.period; 1785 + hists->stats.total_non_filtered_latency += h->stat.latency; 1799 1786 } 1800 1787 1801 1788 void hists__inc_stats(struct hists *hists, struct hist_entry *h) ··· 1806 1791 1807 1792 hists->nr_entries++; 1808 1793 hists->stats.total_period += h->stat.period; 1794 + hists->stats.total_latency += h->stat.latency; 1809 1795 } 1810 1796 1811 1797 static void hierarchy_recalc_total_periods(struct hists *hists) ··· 1818 1802 1819 1803 hists->stats.total_period = 0; 1820 1804 hists->stats.total_non_filtered_period = 0; 1805 + hists->stats.total_latency = 0; 1806 + hists->stats.total_non_filtered_latency = 0; 1821 1807 1822 1808 /* 1823 1809 * recalculate total period using top-level entries only ··· 1831 1813 node = rb_next(node); 1832 1814 1833 1815 hists->stats.total_period += he->stat.period; 1834 - if (!he->filtered) 1816 + hists->stats.total_latency += he->stat.latency; 1817 + if (!he->filtered) { 1835 1818 hists->stats.total_non_filtered_period += he->stat.period; 1819 + hists->stats.total_non_filtered_latency += he->stat.latency; 1820 + } 1836 1821 } 1837 1822 } 1838 1823 ··· 2810 2789 { 2811 2790 return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period : 2812 2791 hists->stats.total_period; 2792 + } 2793 + 2794 + u64 hists__total_latency(struct hists *hists) 2795 + { 2796 + return symbol_conf.filter_relative ? hists->stats.total_non_filtered_latency : 2797 + hists->stats.total_latency; 2813 2798 } 2814 2799 2815 2800 int __hists__scnprintf_title(struct hists *hists, char *bf, size_t size, bool show_freq)
+12
tools/perf/util/hist.h
··· 109 109 u64 nr_non_filtered_entries; 110 110 u64 callchain_period; 111 111 u64 callchain_non_filtered_period; 112 + u64 callchain_latency; 113 + u64 callchain_non_filtered_latency; 112 114 struct thread *thread_filter; 113 115 const struct dso *dso_filter; 114 116 const char *uid_filter_str; ··· 172 170 173 171 struct he_stat { 174 172 u64 period; 173 + /* 174 + * Period re-scaled from CPU time to wall-clock time (divided by the 175 + * parallelism at the time of the sample). This represents effect of 176 + * the event on latency rather than CPU consumption. 177 + */ 178 + u64 latency; 175 179 u64 period_sys; 176 180 u64 period_us; 177 181 u64 period_guest_sys; ··· 382 374 struct hist_entry *hists__get_entry(struct hists *hists, int idx); 383 375 384 376 u64 hists__total_period(struct hists *hists); 377 + u64 hists__total_latency(struct hists *hists); 385 378 void hists__reset_stats(struct hists *hists); 386 379 void hists__inc_stats(struct hists *hists, struct hist_entry *h); 387 380 void hists__inc_nr_events(struct hists *hists); ··· 564 555 enum { 565 556 /* Matches perf_hpp__format array. */ 566 557 PERF_HPP__OVERHEAD, 558 + PERF_HPP__LATENCY, 567 559 PERF_HPP__OVERHEAD_SYS, 568 560 PERF_HPP__OVERHEAD_US, 569 561 PERF_HPP__OVERHEAD_GUEST_SYS, 570 562 PERF_HPP__OVERHEAD_GUEST_US, 571 563 PERF_HPP__OVERHEAD_ACC, 564 + PERF_HPP__LATENCY_ACC, 572 565 PERF_HPP__SAMPLES, 573 566 PERF_HPP__PERIOD, 574 567 PERF_HPP__WEIGHT1, ··· 626 615 enum perf_hpp_fmt_type { 627 616 PERF_HPP_FMT_TYPE__RAW, 628 617 PERF_HPP_FMT_TYPE__PERCENT, 618 + PERF_HPP_FMT_TYPE__LATENCY, 629 619 PERF_HPP_FMT_TYPE__AVERAGE, 630 620 }; 631 621
+2
tools/perf/util/sort.c
··· 2628 2628 2629 2629 static struct hpp_dimension hpp_sort_dimensions[] = { 2630 2630 DIM(PERF_HPP__OVERHEAD, "overhead"), 2631 + DIM(PERF_HPP__LATENCY, "latency"), 2631 2632 DIM(PERF_HPP__OVERHEAD_SYS, "overhead_sys"), 2632 2633 DIM(PERF_HPP__OVERHEAD_US, "overhead_us"), 2633 2634 DIM(PERF_HPP__OVERHEAD_GUEST_SYS, "overhead_guest_sys"), 2634 2635 DIM(PERF_HPP__OVERHEAD_GUEST_US, "overhead_guest_us"), 2635 2636 DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"), 2637 + DIM(PERF_HPP__LATENCY_ACC, "latency_children"), 2636 2638 DIM(PERF_HPP__SAMPLES, "sample"), 2637 2639 DIM(PERF_HPP__PERIOD, "period"), 2638 2640 DIM(PERF_HPP__WEIGHT1, "weight1"),