hist.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. #include <math.h>
  2. #include "../util/hist.h"
  3. #include "../util/util.h"
  4. #include "../util/sort.h"
  5. /* hist period print (hpp) functions */
  6. static int hpp__header_overhead(struct perf_hpp *hpp)
  7. {
  8. return scnprintf(hpp->buf, hpp->size, "Overhead");
  9. }
  10. static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused)
  11. {
  12. return 8;
  13. }
  14. static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he)
  15. {
  16. struct hists *hists = he->hists;
  17. double percent = 100.0 * he->stat.period / hists->stats.total_period;
  18. return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
  19. }
  20. static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he)
  21. {
  22. struct hists *hists = he->hists;
  23. double percent = 100.0 * he->stat.period / hists->stats.total_period;
  24. const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
  25. return scnprintf(hpp->buf, hpp->size, fmt, percent);
  26. }
  27. static int hpp__header_overhead_sys(struct perf_hpp *hpp)
  28. {
  29. const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
  30. return scnprintf(hpp->buf, hpp->size, fmt, "sys");
  31. }
  32. static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused)
  33. {
  34. return 7;
  35. }
  36. static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
  37. {
  38. struct hists *hists = he->hists;
  39. double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
  40. return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
  41. }
  42. static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he)
  43. {
  44. struct hists *hists = he->hists;
  45. double percent = 100.0 * he->stat.period_sys / hists->stats.total_period;
  46. const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
  47. return scnprintf(hpp->buf, hpp->size, fmt, percent);
  48. }
  49. static int hpp__header_overhead_us(struct perf_hpp *hpp)
  50. {
  51. const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
  52. return scnprintf(hpp->buf, hpp->size, fmt, "user");
  53. }
  54. static int hpp__width_overhead_us(struct perf_hpp *hpp __maybe_unused)
  55. {
  56. return 7;
  57. }
  58. static int hpp__color_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
  59. {
  60. struct hists *hists = he->hists;
  61. double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
  62. return percent_color_snprintf(hpp->buf, hpp->size, "%6.2f%%", percent);
  63. }
  64. static int hpp__entry_overhead_us(struct perf_hpp *hpp, struct hist_entry *he)
  65. {
  66. struct hists *hists = he->hists;
  67. double percent = 100.0 * he->stat.period_us / hists->stats.total_period;
  68. const char *fmt = symbol_conf.field_sep ? "%.2f" : "%6.2f%%";
  69. return scnprintf(hpp->buf, hpp->size, fmt, percent);
  70. }
  71. static int hpp__header_overhead_guest_sys(struct perf_hpp *hpp)
  72. {
  73. return scnprintf(hpp->buf, hpp->size, "guest sys");
  74. }
  75. static int hpp__width_overhead_guest_sys(struct perf_hpp *hpp __maybe_unused)
  76. {
  77. return 9;
  78. }
  79. static int hpp__color_overhead_guest_sys(struct perf_hpp *hpp,
  80. struct hist_entry *he)
  81. {
  82. struct hists *hists = he->hists;
  83. double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
  84. return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
  85. }
  86. static int hpp__entry_overhead_guest_sys(struct perf_hpp *hpp,
  87. struct hist_entry *he)
  88. {
  89. struct hists *hists = he->hists;
  90. double percent = 100.0 * he->stat.period_guest_sys / hists->stats.total_period;
  91. const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
  92. return scnprintf(hpp->buf, hpp->size, fmt, percent);
  93. }
  94. static int hpp__header_overhead_guest_us(struct perf_hpp *hpp)
  95. {
  96. return scnprintf(hpp->buf, hpp->size, "guest usr");
  97. }
  98. static int hpp__width_overhead_guest_us(struct perf_hpp *hpp __maybe_unused)
  99. {
  100. return 9;
  101. }
  102. static int hpp__color_overhead_guest_us(struct perf_hpp *hpp,
  103. struct hist_entry *he)
  104. {
  105. struct hists *hists = he->hists;
  106. double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
  107. return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%% ", percent);
  108. }
  109. static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp,
  110. struct hist_entry *he)
  111. {
  112. struct hists *hists = he->hists;
  113. double percent = 100.0 * he->stat.period_guest_us / hists->stats.total_period;
  114. const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%% ";
  115. return scnprintf(hpp->buf, hpp->size, fmt, percent);
  116. }
  117. static int hpp__header_baseline(struct perf_hpp *hpp)
  118. {
  119. return scnprintf(hpp->buf, hpp->size, "Baseline");
  120. }
  121. static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused)
  122. {
  123. return 8;
  124. }
  125. static double baseline_percent(struct hist_entry *he)
  126. {
  127. struct hist_entry *pair = he->pair;
  128. struct hists *pair_hists = pair ? pair->hists : NULL;
  129. double percent = 0.0;
  130. if (pair) {
  131. u64 total_period = pair_hists->stats.total_period;
  132. u64 base_period = pair->stat.period;
  133. percent = 100.0 * base_period / total_period;
  134. }
  135. return percent;
  136. }
  137. static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
  138. {
  139. double percent = baseline_percent(he);
  140. return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
  141. }
  142. static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
  143. {
  144. double percent = baseline_percent(he);
  145. const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";
  146. return scnprintf(hpp->buf, hpp->size, fmt, percent);
  147. }
  148. static int hpp__header_samples(struct perf_hpp *hpp)
  149. {
  150. const char *fmt = symbol_conf.field_sep ? "%s" : "%11s";
  151. return scnprintf(hpp->buf, hpp->size, fmt, "Samples");
  152. }
  153. static int hpp__width_samples(struct perf_hpp *hpp __maybe_unused)
  154. {
  155. return 11;
  156. }
  157. static int hpp__entry_samples(struct perf_hpp *hpp, struct hist_entry *he)
  158. {
  159. const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%11" PRIu64;
  160. return scnprintf(hpp->buf, hpp->size, fmt, he->stat.nr_events);
  161. }
  162. static int hpp__header_period(struct perf_hpp *hpp)
  163. {
  164. const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
  165. return scnprintf(hpp->buf, hpp->size, fmt, "Period");
  166. }
  167. static int hpp__width_period(struct perf_hpp *hpp __maybe_unused)
  168. {
  169. return 12;
  170. }
  171. static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
  172. {
  173. const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
  174. return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
  175. }
  176. static int hpp__header_delta(struct perf_hpp *hpp)
  177. {
  178. const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
  179. return scnprintf(hpp->buf, hpp->size, fmt, "Delta");
  180. }
  181. static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)
  182. {
  183. return 7;
  184. }
  185. static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
  186. {
  187. struct hist_entry *pair = he->pair;
  188. struct hists *pair_hists = pair ? pair->hists : NULL;
  189. struct hists *hists = he->hists;
  190. u64 old_total, new_total;
  191. double old_percent = 0, new_percent = 0;
  192. double diff;
  193. const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
  194. char buf[32] = " ";
  195. old_total = pair_hists ? pair_hists->stats.total_period : 0;
  196. if (old_total > 0 && pair)
  197. old_percent = 100.0 * pair->stat.period / old_total;
  198. new_total = hists->stats.total_period;
  199. if (new_total > 0)
  200. new_percent = 100.0 * he->stat.period / new_total;
  201. diff = new_percent - old_percent;
  202. if (fabs(diff) >= 0.01)
  203. scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);
  204. return scnprintf(hpp->buf, hpp->size, fmt, buf);
  205. }
  206. static int hpp__header_displ(struct perf_hpp *hpp)
  207. {
  208. return scnprintf(hpp->buf, hpp->size, "Displ.");
  209. }
  210. static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused)
  211. {
  212. return 6;
  213. }
  214. static int hpp__entry_displ(struct perf_hpp *hpp,
  215. struct hist_entry *he)
  216. {
  217. struct hist_entry *pair = he->pair;
  218. long displacement = pair ? pair->position - he->position : 0;
  219. const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s";
  220. char buf[32] = " ";
  221. if (displacement)
  222. scnprintf(buf, sizeof(buf), "%+4ld", displacement);
  223. return scnprintf(hpp->buf, hpp->size, fmt, buf);
  224. }
  225. #define HPP__COLOR_PRINT_FNS(_name) \
  226. .header = hpp__header_ ## _name, \
  227. .width = hpp__width_ ## _name, \
  228. .color = hpp__color_ ## _name, \
  229. .entry = hpp__entry_ ## _name
  230. #define HPP__PRINT_FNS(_name) \
  231. .header = hpp__header_ ## _name, \
  232. .width = hpp__width_ ## _name, \
  233. .entry = hpp__entry_ ## _name
  234. struct perf_hpp_fmt perf_hpp__format[] = {
  235. { .cond = false, HPP__COLOR_PRINT_FNS(baseline) },
  236. { .cond = true, HPP__COLOR_PRINT_FNS(overhead) },
  237. { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) },
  238. { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) },
  239. { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_sys) },
  240. { .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
  241. { .cond = false, HPP__PRINT_FNS(samples) },
  242. { .cond = false, HPP__PRINT_FNS(period) },
  243. { .cond = false, HPP__PRINT_FNS(delta) },
  244. { .cond = false, HPP__PRINT_FNS(displ) }
  245. };
  246. #undef HPP__COLOR_PRINT_FNS
  247. #undef HPP__PRINT_FNS
  248. void perf_hpp__init(void)
  249. {
  250. if (symbol_conf.show_cpu_utilization) {
  251. perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true;
  252. perf_hpp__format[PERF_HPP__OVERHEAD_US].cond = true;
  253. if (perf_guest) {
  254. perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_SYS].cond = true;
  255. perf_hpp__format[PERF_HPP__OVERHEAD_GUEST_US].cond = true;
  256. }
  257. }
  258. if (symbol_conf.show_nr_samples)
  259. perf_hpp__format[PERF_HPP__SAMPLES].cond = true;
  260. if (symbol_conf.show_total_period)
  261. perf_hpp__format[PERF_HPP__PERIOD].cond = true;
  262. }
  263. void perf_hpp__column_enable(unsigned col, bool enable)
  264. {
  265. BUG_ON(col >= PERF_HPP__MAX_INDEX);
  266. perf_hpp__format[col].cond = enable;
  267. }
  268. static inline void advance_hpp(struct perf_hpp *hpp, int inc)
  269. {
  270. hpp->buf += inc;
  271. hpp->size -= inc;
  272. }
  273. int hist_entry__period_snprintf(struct perf_hpp *hpp, struct hist_entry *he,
  274. bool color)
  275. {
  276. const char *sep = symbol_conf.field_sep;
  277. char *start = hpp->buf;
  278. int i, ret;
  279. bool first = true;
  280. if (symbol_conf.exclude_other && !he->parent)
  281. return 0;
  282. for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
  283. if (!perf_hpp__format[i].cond)
  284. continue;
  285. if (!sep || !first) {
  286. ret = scnprintf(hpp->buf, hpp->size, "%s", sep ?: " ");
  287. advance_hpp(hpp, ret);
  288. first = false;
  289. }
  290. if (color && perf_hpp__format[i].color)
  291. ret = perf_hpp__format[i].color(hpp, he);
  292. else
  293. ret = perf_hpp__format[i].entry(hpp, he);
  294. advance_hpp(hpp, ret);
  295. }
  296. return hpp->buf - start;
  297. }
  298. int hist_entry__sort_snprintf(struct hist_entry *he, char *s, size_t size,
  299. struct hists *hists)
  300. {
  301. const char *sep = symbol_conf.field_sep;
  302. struct sort_entry *se;
  303. int ret = 0;
  304. list_for_each_entry(se, &hist_entry__sort_list, list) {
  305. if (se->elide)
  306. continue;
  307. ret += scnprintf(s + ret, size - ret, "%s", sep ?: " ");
  308. ret += se->se_snprintf(he, s + ret, size - ret,
  309. hists__col_len(hists, se->se_width_idx));
  310. }
  311. return ret;
  312. }
  313. /*
  314. * See hists__fprintf to match the column widths
  315. */
  316. unsigned int hists__sort_list_width(struct hists *hists)
  317. {
  318. struct sort_entry *se;
  319. int i, ret = 0;
  320. for (i = 0; i < PERF_HPP__MAX_INDEX; i++) {
  321. if (!perf_hpp__format[i].cond)
  322. continue;
  323. if (i)
  324. ret += 2;
  325. ret += perf_hpp__format[i].width(NULL);
  326. }
  327. list_for_each_entry(se, &hist_entry__sort_list, list)
  328. if (!se->elide)
  329. ret += 2 + hists__col_len(hists, se->se_width_idx);
  330. if (verbose) /* Addr + origin */
  331. ret += 3 + BITS_PER_LONG / 4;
  332. return ret;
  333. }