hist.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. #include "util.h"
  2. #include "hist.h"
  3. #include "session.h"
  4. #include "sort.h"
  5. #include <math.h>
  6. struct callchain_param callchain_param = {
  7. .mode = CHAIN_GRAPH_REL,
  8. .min_percent = 0.5
  9. };
  10. static void hist_entry__add_cpumode_count(struct hist_entry *self,
  11. unsigned int cpumode, u64 count)
  12. {
  13. switch (cpumode) {
  14. case PERF_RECORD_MISC_KERNEL:
  15. self->count_sys += count;
  16. break;
  17. case PERF_RECORD_MISC_USER:
  18. self->count_us += count;
  19. break;
  20. case PERF_RECORD_MISC_GUEST_KERNEL:
  21. self->count_guest_sys += count;
  22. break;
  23. case PERF_RECORD_MISC_GUEST_USER:
  24. self->count_guest_us += count;
  25. break;
  26. default:
  27. break;
  28. }
  29. }
  30. /*
  31. * histogram, sorted on item, collects counts
  32. */
  33. static struct hist_entry *hist_entry__new(struct hist_entry *template)
  34. {
  35. size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_node) : 0;
  36. struct hist_entry *self = malloc(sizeof(*self) + callchain_size);
  37. if (self != NULL) {
  38. *self = *template;
  39. if (symbol_conf.use_callchain)
  40. callchain_init(self->callchain);
  41. }
  42. return self;
  43. }
  44. static void hists__inc_nr_entries(struct hists *self, struct hist_entry *entry)
  45. {
  46. if (entry->ms.sym && self->max_sym_namelen < entry->ms.sym->namelen)
  47. self->max_sym_namelen = entry->ms.sym->namelen;
  48. ++self->nr_entries;
  49. }
  50. struct hist_entry *__hists__add_entry(struct hists *self,
  51. struct addr_location *al,
  52. struct symbol *sym_parent, u64 count)
  53. {
  54. struct rb_node **p = &self->entries.rb_node;
  55. struct rb_node *parent = NULL;
  56. struct hist_entry *he;
  57. struct hist_entry entry = {
  58. .thread = al->thread,
  59. .ms = {
  60. .map = al->map,
  61. .sym = al->sym,
  62. },
  63. .ip = al->addr,
  64. .level = al->level,
  65. .count = count,
  66. .parent = sym_parent,
  67. };
  68. int cmp;
  69. while (*p != NULL) {
  70. parent = *p;
  71. he = rb_entry(parent, struct hist_entry, rb_node);
  72. cmp = hist_entry__cmp(&entry, he);
  73. if (!cmp) {
  74. he->count += count;
  75. goto out;
  76. }
  77. if (cmp < 0)
  78. p = &(*p)->rb_left;
  79. else
  80. p = &(*p)->rb_right;
  81. }
  82. he = hist_entry__new(&entry);
  83. if (!he)
  84. return NULL;
  85. rb_link_node(&he->rb_node, parent, p);
  86. rb_insert_color(&he->rb_node, &self->entries);
  87. hists__inc_nr_entries(self, he);
  88. out:
  89. hist_entry__add_cpumode_count(he, al->cpumode, count);
  90. return he;
  91. }
  92. int64_t
  93. hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
  94. {
  95. struct sort_entry *se;
  96. int64_t cmp = 0;
  97. list_for_each_entry(se, &hist_entry__sort_list, list) {
  98. cmp = se->se_cmp(left, right);
  99. if (cmp)
  100. break;
  101. }
  102. return cmp;
  103. }
  104. int64_t
  105. hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
  106. {
  107. struct sort_entry *se;
  108. int64_t cmp = 0;
  109. list_for_each_entry(se, &hist_entry__sort_list, list) {
  110. int64_t (*f)(struct hist_entry *, struct hist_entry *);
  111. f = se->se_collapse ?: se->se_cmp;
  112. cmp = f(left, right);
  113. if (cmp)
  114. break;
  115. }
  116. return cmp;
  117. }
  118. void hist_entry__free(struct hist_entry *he)
  119. {
  120. free(he);
  121. }
  122. /*
  123. * collapse the histogram
  124. */
  125. static bool collapse__insert_entry(struct rb_root *root, struct hist_entry *he)
  126. {
  127. struct rb_node **p = &root->rb_node;
  128. struct rb_node *parent = NULL;
  129. struct hist_entry *iter;
  130. int64_t cmp;
  131. while (*p != NULL) {
  132. parent = *p;
  133. iter = rb_entry(parent, struct hist_entry, rb_node);
  134. cmp = hist_entry__collapse(iter, he);
  135. if (!cmp) {
  136. iter->count += he->count;
  137. hist_entry__free(he);
  138. return false;
  139. }
  140. if (cmp < 0)
  141. p = &(*p)->rb_left;
  142. else
  143. p = &(*p)->rb_right;
  144. }
  145. rb_link_node(&he->rb_node, parent, p);
  146. rb_insert_color(&he->rb_node, root);
  147. return true;
  148. }
  149. void hists__collapse_resort(struct hists *self)
  150. {
  151. struct rb_root tmp;
  152. struct rb_node *next;
  153. struct hist_entry *n;
  154. if (!sort__need_collapse)
  155. return;
  156. tmp = RB_ROOT;
  157. next = rb_first(&self->entries);
  158. self->nr_entries = 0;
  159. self->max_sym_namelen = 0;
  160. while (next) {
  161. n = rb_entry(next, struct hist_entry, rb_node);
  162. next = rb_next(&n->rb_node);
  163. rb_erase(&n->rb_node, &self->entries);
  164. if (collapse__insert_entry(&tmp, n))
  165. hists__inc_nr_entries(self, n);
  166. }
  167. self->entries = tmp;
  168. }
  169. /*
  170. * reverse the map, sort on count.
  171. */
  172. static void __hists__insert_output_entry(struct rb_root *entries,
  173. struct hist_entry *he,
  174. u64 min_callchain_hits)
  175. {
  176. struct rb_node **p = &entries->rb_node;
  177. struct rb_node *parent = NULL;
  178. struct hist_entry *iter;
  179. if (symbol_conf.use_callchain)
  180. callchain_param.sort(&he->sorted_chain, he->callchain,
  181. min_callchain_hits, &callchain_param);
  182. while (*p != NULL) {
  183. parent = *p;
  184. iter = rb_entry(parent, struct hist_entry, rb_node);
  185. if (he->count > iter->count)
  186. p = &(*p)->rb_left;
  187. else
  188. p = &(*p)->rb_right;
  189. }
  190. rb_link_node(&he->rb_node, parent, p);
  191. rb_insert_color(&he->rb_node, entries);
  192. }
  193. void hists__output_resort(struct hists *self)
  194. {
  195. struct rb_root tmp;
  196. struct rb_node *next;
  197. struct hist_entry *n;
  198. u64 min_callchain_hits;
  199. min_callchain_hits = self->stats.total_period * (callchain_param.min_percent / 100);
  200. tmp = RB_ROOT;
  201. next = rb_first(&self->entries);
  202. self->nr_entries = 0;
  203. self->max_sym_namelen = 0;
  204. while (next) {
  205. n = rb_entry(next, struct hist_entry, rb_node);
  206. next = rb_next(&n->rb_node);
  207. rb_erase(&n->rb_node, &self->entries);
  208. __hists__insert_output_entry(&tmp, n, min_callchain_hits);
  209. hists__inc_nr_entries(self, n);
  210. }
  211. self->entries = tmp;
  212. }
  213. static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin)
  214. {
  215. int i;
  216. int ret = fprintf(fp, " ");
  217. for (i = 0; i < left_margin; i++)
  218. ret += fprintf(fp, " ");
  219. return ret;
  220. }
  221. static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
  222. int left_margin)
  223. {
  224. int i;
  225. size_t ret = callchain__fprintf_left_margin(fp, left_margin);
  226. for (i = 0; i < depth; i++)
  227. if (depth_mask & (1 << i))
  228. ret += fprintf(fp, "| ");
  229. else
  230. ret += fprintf(fp, " ");
  231. ret += fprintf(fp, "\n");
  232. return ret;
  233. }
  234. static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
  235. int depth, int depth_mask, int count,
  236. u64 total_samples, int hits,
  237. int left_margin)
  238. {
  239. int i;
  240. size_t ret = 0;
  241. ret += callchain__fprintf_left_margin(fp, left_margin);
  242. for (i = 0; i < depth; i++) {
  243. if (depth_mask & (1 << i))
  244. ret += fprintf(fp, "|");
  245. else
  246. ret += fprintf(fp, " ");
  247. if (!count && i == depth - 1) {
  248. double percent;
  249. percent = hits * 100.0 / total_samples;
  250. ret += percent_color_fprintf(fp, "--%2.2f%%-- ", percent);
  251. } else
  252. ret += fprintf(fp, "%s", " ");
  253. }
  254. if (chain->ms.sym)
  255. ret += fprintf(fp, "%s\n", chain->ms.sym->name);
  256. else
  257. ret += fprintf(fp, "%p\n", (void *)(long)chain->ip);
  258. return ret;
  259. }
  260. static struct symbol *rem_sq_bracket;
  261. static struct callchain_list rem_hits;
  262. static void init_rem_hits(void)
  263. {
  264. rem_sq_bracket = malloc(sizeof(*rem_sq_bracket) + 6);
  265. if (!rem_sq_bracket) {
  266. fprintf(stderr, "Not enough memory to display remaining hits\n");
  267. return;
  268. }
  269. strcpy(rem_sq_bracket->name, "[...]");
  270. rem_hits.ms.sym = rem_sq_bracket;
  271. }
  272. static size_t __callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
  273. u64 total_samples, int depth,
  274. int depth_mask, int left_margin)
  275. {
  276. struct rb_node *node, *next;
  277. struct callchain_node *child;
  278. struct callchain_list *chain;
  279. int new_depth_mask = depth_mask;
  280. u64 new_total;
  281. u64 remaining;
  282. size_t ret = 0;
  283. int i;
  284. uint entries_printed = 0;
  285. if (callchain_param.mode == CHAIN_GRAPH_REL)
  286. new_total = self->children_hit;
  287. else
  288. new_total = total_samples;
  289. remaining = new_total;
  290. node = rb_first(&self->rb_root);
  291. while (node) {
  292. u64 cumul;
  293. child = rb_entry(node, struct callchain_node, rb_node);
  294. cumul = cumul_hits(child);
  295. remaining -= cumul;
  296. /*
  297. * The depth mask manages the output of pipes that show
  298. * the depth. We don't want to keep the pipes of the current
  299. * level for the last child of this depth.
  300. * Except if we have remaining filtered hits. They will
  301. * supersede the last child
  302. */
  303. next = rb_next(node);
  304. if (!next && (callchain_param.mode != CHAIN_GRAPH_REL || !remaining))
  305. new_depth_mask &= ~(1 << (depth - 1));
  306. /*
  307. * But we keep the older depth mask for the line separator
  308. * to keep the level link until we reach the last child
  309. */
  310. ret += ipchain__fprintf_graph_line(fp, depth, depth_mask,
  311. left_margin);
  312. i = 0;
  313. list_for_each_entry(chain, &child->val, list) {
  314. ret += ipchain__fprintf_graph(fp, chain, depth,
  315. new_depth_mask, i++,
  316. new_total,
  317. cumul,
  318. left_margin);
  319. }
  320. ret += __callchain__fprintf_graph(fp, child, new_total,
  321. depth + 1,
  322. new_depth_mask | (1 << depth),
  323. left_margin);
  324. node = next;
  325. if (++entries_printed == callchain_param.print_limit)
  326. break;
  327. }
  328. if (callchain_param.mode == CHAIN_GRAPH_REL &&
  329. remaining && remaining != new_total) {
  330. if (!rem_sq_bracket)
  331. return ret;
  332. new_depth_mask &= ~(1 << (depth - 1));
  333. ret += ipchain__fprintf_graph(fp, &rem_hits, depth,
  334. new_depth_mask, 0, new_total,
  335. remaining, left_margin);
  336. }
  337. return ret;
  338. }
  339. static size_t callchain__fprintf_graph(FILE *fp, struct callchain_node *self,
  340. u64 total_samples, int left_margin)
  341. {
  342. struct callchain_list *chain;
  343. bool printed = false;
  344. int i = 0;
  345. int ret = 0;
  346. u32 entries_printed = 0;
  347. list_for_each_entry(chain, &self->val, list) {
  348. if (!i++ && sort__first_dimension == SORT_SYM)
  349. continue;
  350. if (!printed) {
  351. ret += callchain__fprintf_left_margin(fp, left_margin);
  352. ret += fprintf(fp, "|\n");
  353. ret += callchain__fprintf_left_margin(fp, left_margin);
  354. ret += fprintf(fp, "---");
  355. left_margin += 3;
  356. printed = true;
  357. } else
  358. ret += callchain__fprintf_left_margin(fp, left_margin);
  359. if (chain->ms.sym)
  360. ret += fprintf(fp, " %s\n", chain->ms.sym->name);
  361. else
  362. ret += fprintf(fp, " %p\n", (void *)(long)chain->ip);
  363. if (++entries_printed == callchain_param.print_limit)
  364. break;
  365. }
  366. ret += __callchain__fprintf_graph(fp, self, total_samples, 1, 1, left_margin);
  367. return ret;
  368. }
  369. static size_t callchain__fprintf_flat(FILE *fp, struct callchain_node *self,
  370. u64 total_samples)
  371. {
  372. struct callchain_list *chain;
  373. size_t ret = 0;
  374. if (!self)
  375. return 0;
  376. ret += callchain__fprintf_flat(fp, self->parent, total_samples);
  377. list_for_each_entry(chain, &self->val, list) {
  378. if (chain->ip >= PERF_CONTEXT_MAX)
  379. continue;
  380. if (chain->ms.sym)
  381. ret += fprintf(fp, " %s\n", chain->ms.sym->name);
  382. else
  383. ret += fprintf(fp, " %p\n",
  384. (void *)(long)chain->ip);
  385. }
  386. return ret;
  387. }
  388. static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
  389. u64 total_samples, int left_margin)
  390. {
  391. struct rb_node *rb_node;
  392. struct callchain_node *chain;
  393. size_t ret = 0;
  394. u32 entries_printed = 0;
  395. rb_node = rb_first(&self->sorted_chain);
  396. while (rb_node) {
  397. double percent;
  398. chain = rb_entry(rb_node, struct callchain_node, rb_node);
  399. percent = chain->hit * 100.0 / total_samples;
  400. switch (callchain_param.mode) {
  401. case CHAIN_FLAT:
  402. ret += percent_color_fprintf(fp, " %6.2f%%\n",
  403. percent);
  404. ret += callchain__fprintf_flat(fp, chain, total_samples);
  405. break;
  406. case CHAIN_GRAPH_ABS: /* Falldown */
  407. case CHAIN_GRAPH_REL:
  408. ret += callchain__fprintf_graph(fp, chain, total_samples,
  409. left_margin);
  410. case CHAIN_NONE:
  411. default:
  412. break;
  413. }
  414. ret += fprintf(fp, "\n");
  415. if (++entries_printed == callchain_param.print_limit)
  416. break;
  417. rb_node = rb_next(rb_node);
  418. }
  419. return ret;
  420. }
  421. int hist_entry__snprintf(struct hist_entry *self, char *s, size_t size,
  422. struct hists *pair_hists, bool show_displacement,
  423. long displacement, bool color, u64 session_total)
  424. {
  425. struct sort_entry *se;
  426. u64 count, total, count_sys, count_us, count_guest_sys, count_guest_us;
  427. const char *sep = symbol_conf.field_sep;
  428. int ret;
  429. if (symbol_conf.exclude_other && !self->parent)
  430. return 0;
  431. if (pair_hists) {
  432. count = self->pair ? self->pair->count : 0;
  433. total = pair_hists->stats.total_period;
  434. count_sys = self->pair ? self->pair->count_sys : 0;
  435. count_us = self->pair ? self->pair->count_us : 0;
  436. count_guest_sys = self->pair ? self->pair->count_guest_sys : 0;
  437. count_guest_us = self->pair ? self->pair->count_guest_us : 0;
  438. } else {
  439. count = self->count;
  440. total = session_total;
  441. count_sys = self->count_sys;
  442. count_us = self->count_us;
  443. count_guest_sys = self->count_guest_sys;
  444. count_guest_us = self->count_guest_us;
  445. }
  446. if (total) {
  447. if (color)
  448. ret = percent_color_snprintf(s, size,
  449. sep ? "%.2f" : " %6.2f%%",
  450. (count * 100.0) / total);
  451. else
  452. ret = snprintf(s, size, sep ? "%.2f" : " %6.2f%%",
  453. (count * 100.0) / total);
  454. if (symbol_conf.show_cpu_utilization) {
  455. ret += percent_color_snprintf(s + ret, size - ret,
  456. sep ? "%.2f" : " %6.2f%%",
  457. (count_sys * 100.0) / total);
  458. ret += percent_color_snprintf(s + ret, size - ret,
  459. sep ? "%.2f" : " %6.2f%%",
  460. (count_us * 100.0) / total);
  461. if (perf_guest) {
  462. ret += percent_color_snprintf(s + ret,
  463. size - ret,
  464. sep ? "%.2f" : " %6.2f%%",
  465. (count_guest_sys * 100.0) /
  466. total);
  467. ret += percent_color_snprintf(s + ret,
  468. size - ret,
  469. sep ? "%.2f" : " %6.2f%%",
  470. (count_guest_us * 100.0) /
  471. total);
  472. }
  473. }
  474. } else
  475. ret = snprintf(s, size, sep ? "%lld" : "%12lld ", count);
  476. if (symbol_conf.show_nr_samples) {
  477. if (sep)
  478. ret += snprintf(s + ret, size - ret, "%c%lld", *sep, count);
  479. else
  480. ret += snprintf(s + ret, size - ret, "%11lld", count);
  481. }
  482. if (pair_hists) {
  483. char bf[32];
  484. double old_percent = 0, new_percent = 0, diff;
  485. if (total > 0)
  486. old_percent = (count * 100.0) / total;
  487. if (session_total > 0)
  488. new_percent = (self->count * 100.0) / session_total;
  489. diff = new_percent - old_percent;
  490. if (fabs(diff) >= 0.01)
  491. snprintf(bf, sizeof(bf), "%+4.2F%%", diff);
  492. else
  493. snprintf(bf, sizeof(bf), " ");
  494. if (sep)
  495. ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf);
  496. else
  497. ret += snprintf(s + ret, size - ret, "%11.11s", bf);
  498. if (show_displacement) {
  499. if (displacement)
  500. snprintf(bf, sizeof(bf), "%+4ld", displacement);
  501. else
  502. snprintf(bf, sizeof(bf), " ");
  503. if (sep)
  504. ret += snprintf(s + ret, size - ret, "%c%s", *sep, bf);
  505. else
  506. ret += snprintf(s + ret, size - ret, "%6.6s", bf);
  507. }
  508. }
  509. list_for_each_entry(se, &hist_entry__sort_list, list) {
  510. if (se->elide)
  511. continue;
  512. ret += snprintf(s + ret, size - ret, "%s", sep ?: " ");
  513. ret += se->se_snprintf(self, s + ret, size - ret,
  514. se->se_width ? *se->se_width : 0);
  515. }
  516. return ret;
  517. }
  518. int hist_entry__fprintf(struct hist_entry *self, struct hists *pair_hists,
  519. bool show_displacement, long displacement, FILE *fp,
  520. u64 session_total)
  521. {
  522. char bf[512];
  523. hist_entry__snprintf(self, bf, sizeof(bf), pair_hists,
  524. show_displacement, displacement,
  525. true, session_total);
  526. return fprintf(fp, "%s\n", bf);
  527. }
  528. static size_t hist_entry__fprintf_callchain(struct hist_entry *self, FILE *fp,
  529. u64 session_total)
  530. {
  531. int left_margin = 0;
  532. if (sort__first_dimension == SORT_COMM) {
  533. struct sort_entry *se = list_first_entry(&hist_entry__sort_list,
  534. typeof(*se), list);
  535. left_margin = se->se_width ? *se->se_width : 0;
  536. left_margin -= thread__comm_len(self->thread);
  537. }
  538. return hist_entry_callchain__fprintf(fp, self, session_total,
  539. left_margin);
  540. }
  541. size_t hists__fprintf(struct hists *self, struct hists *pair,
  542. bool show_displacement, FILE *fp)
  543. {
  544. struct sort_entry *se;
  545. struct rb_node *nd;
  546. size_t ret = 0;
  547. unsigned long position = 1;
  548. long displacement = 0;
  549. unsigned int width;
  550. const char *sep = symbol_conf.field_sep;
  551. char *col_width = symbol_conf.col_width_list_str;
  552. init_rem_hits();
  553. fprintf(fp, "# %s", pair ? "Baseline" : "Overhead");
  554. if (symbol_conf.show_nr_samples) {
  555. if (sep)
  556. fprintf(fp, "%cSamples", *sep);
  557. else
  558. fputs(" Samples ", fp);
  559. }
  560. if (symbol_conf.show_cpu_utilization) {
  561. if (sep) {
  562. ret += fprintf(fp, "%csys", *sep);
  563. ret += fprintf(fp, "%cus", *sep);
  564. if (perf_guest) {
  565. ret += fprintf(fp, "%cguest sys", *sep);
  566. ret += fprintf(fp, "%cguest us", *sep);
  567. }
  568. } else {
  569. ret += fprintf(fp, " sys ");
  570. ret += fprintf(fp, " us ");
  571. if (perf_guest) {
  572. ret += fprintf(fp, " guest sys ");
  573. ret += fprintf(fp, " guest us ");
  574. }
  575. }
  576. }
  577. if (pair) {
  578. if (sep)
  579. ret += fprintf(fp, "%cDelta", *sep);
  580. else
  581. ret += fprintf(fp, " Delta ");
  582. if (show_displacement) {
  583. if (sep)
  584. ret += fprintf(fp, "%cDisplacement", *sep);
  585. else
  586. ret += fprintf(fp, " Displ");
  587. }
  588. }
  589. list_for_each_entry(se, &hist_entry__sort_list, list) {
  590. if (se->elide)
  591. continue;
  592. if (sep) {
  593. fprintf(fp, "%c%s", *sep, se->se_header);
  594. continue;
  595. }
  596. width = strlen(se->se_header);
  597. if (se->se_width) {
  598. if (symbol_conf.col_width_list_str) {
  599. if (col_width) {
  600. *se->se_width = atoi(col_width);
  601. col_width = strchr(col_width, ',');
  602. if (col_width)
  603. ++col_width;
  604. }
  605. }
  606. width = *se->se_width = max(*se->se_width, width);
  607. }
  608. fprintf(fp, " %*s", width, se->se_header);
  609. }
  610. fprintf(fp, "\n");
  611. if (sep)
  612. goto print_entries;
  613. fprintf(fp, "# ........");
  614. if (symbol_conf.show_nr_samples)
  615. fprintf(fp, " ..........");
  616. if (pair) {
  617. fprintf(fp, " ..........");
  618. if (show_displacement)
  619. fprintf(fp, " .....");
  620. }
  621. list_for_each_entry(se, &hist_entry__sort_list, list) {
  622. unsigned int i;
  623. if (se->elide)
  624. continue;
  625. fprintf(fp, " ");
  626. if (se->se_width)
  627. width = *se->se_width;
  628. else
  629. width = strlen(se->se_header);
  630. for (i = 0; i < width; i++)
  631. fprintf(fp, ".");
  632. }
  633. fprintf(fp, "\n#\n");
  634. print_entries:
  635. for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
  636. struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
  637. if (show_displacement) {
  638. if (h->pair != NULL)
  639. displacement = ((long)h->pair->position -
  640. (long)position);
  641. else
  642. displacement = 0;
  643. ++position;
  644. }
  645. ret += hist_entry__fprintf(h, pair, show_displacement,
  646. displacement, fp, self->stats.total_period);
  647. if (symbol_conf.use_callchain)
  648. ret += hist_entry__fprintf_callchain(h, fp, self->stats.total_period);
  649. if (h->ms.map == NULL && verbose > 1) {
  650. __map_groups__fprintf_maps(&h->thread->mg,
  651. MAP__FUNCTION, verbose, fp);
  652. fprintf(fp, "%.10s end\n", graph_dotted_line);
  653. }
  654. }
  655. free(rem_sq_bracket);
  656. return ret;
  657. }
  658. enum hist_filter {
  659. HIST_FILTER__DSO,
  660. HIST_FILTER__THREAD,
  661. };
  662. void hists__filter_by_dso(struct hists *self, const struct dso *dso)
  663. {
  664. struct rb_node *nd;
  665. self->nr_entries = self->stats.total_period = 0;
  666. self->max_sym_namelen = 0;
  667. for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
  668. struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
  669. if (symbol_conf.exclude_other && !h->parent)
  670. continue;
  671. if (dso != NULL && (h->ms.map == NULL || h->ms.map->dso != dso)) {
  672. h->filtered |= (1 << HIST_FILTER__DSO);
  673. continue;
  674. }
  675. h->filtered &= ~(1 << HIST_FILTER__DSO);
  676. if (!h->filtered) {
  677. ++self->nr_entries;
  678. self->stats.total_period += h->count;
  679. if (h->ms.sym &&
  680. self->max_sym_namelen < h->ms.sym->namelen)
  681. self->max_sym_namelen = h->ms.sym->namelen;
  682. }
  683. }
  684. }
  685. void hists__filter_by_thread(struct hists *self, const struct thread *thread)
  686. {
  687. struct rb_node *nd;
  688. self->nr_entries = self->stats.total_period = 0;
  689. self->max_sym_namelen = 0;
  690. for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
  691. struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
  692. if (thread != NULL && h->thread != thread) {
  693. h->filtered |= (1 << HIST_FILTER__THREAD);
  694. continue;
  695. }
  696. h->filtered &= ~(1 << HIST_FILTER__THREAD);
  697. if (!h->filtered) {
  698. ++self->nr_entries;
  699. self->stats.total_period += h->count;
  700. if (h->ms.sym &&
  701. self->max_sym_namelen < h->ms.sym->namelen)
  702. self->max_sym_namelen = h->ms.sym->namelen;
  703. }
  704. }
  705. }
  706. static int symbol__alloc_hist(struct symbol *self)
  707. {
  708. struct sym_priv *priv = symbol__priv(self);
  709. const int size = (sizeof(*priv->hist) +
  710. (self->end - self->start) * sizeof(u64));
  711. priv->hist = zalloc(size);
  712. return priv->hist == NULL ? -1 : 0;
  713. }
  714. int hist_entry__inc_addr_samples(struct hist_entry *self, u64 ip)
  715. {
  716. unsigned int sym_size, offset;
  717. struct symbol *sym = self->ms.sym;
  718. struct sym_priv *priv;
  719. struct sym_hist *h;
  720. if (!sym || !self->ms.map)
  721. return 0;
  722. priv = symbol__priv(sym);
  723. if (priv->hist == NULL && symbol__alloc_hist(sym) < 0)
  724. return -ENOMEM;
  725. sym_size = sym->end - sym->start;
  726. offset = ip - sym->start;
  727. pr_debug3("%s: ip=%#Lx\n", __func__, self->ms.map->unmap_ip(self->ms.map, ip));
  728. if (offset >= sym_size)
  729. return 0;
  730. h = priv->hist;
  731. h->sum++;
  732. h->ip[offset]++;
  733. pr_debug3("%#Lx %s: count++ [ip: %#Lx, %#Lx] => %Ld\n", self->ms.sym->start,
  734. self->ms.sym->name, ip, ip - self->ms.sym->start, h->ip[offset]);
  735. return 0;
  736. }
  737. static struct objdump_line *objdump_line__new(s64 offset, char *line)
  738. {
  739. struct objdump_line *self = malloc(sizeof(*self));
  740. if (self != NULL) {
  741. self->offset = offset;
  742. self->line = line;
  743. }
  744. return self;
  745. }
  746. void objdump_line__free(struct objdump_line *self)
  747. {
  748. free(self->line);
  749. free(self);
  750. }
  751. static void objdump__add_line(struct list_head *head, struct objdump_line *line)
  752. {
  753. list_add_tail(&line->node, head);
  754. }
  755. struct objdump_line *objdump__get_next_ip_line(struct list_head *head,
  756. struct objdump_line *pos)
  757. {
  758. list_for_each_entry_continue(pos, head, node)
  759. if (pos->offset >= 0)
  760. return pos;
  761. return NULL;
  762. }
  763. static int hist_entry__parse_objdump_line(struct hist_entry *self, FILE *file,
  764. struct list_head *head)
  765. {
  766. struct symbol *sym = self->ms.sym;
  767. struct objdump_line *objdump_line;
  768. char *line = NULL, *tmp, *tmp2, *c;
  769. size_t line_len;
  770. s64 line_ip, offset = -1;
  771. if (getline(&line, &line_len, file) < 0)
  772. return -1;
  773. if (!line)
  774. return -1;
  775. while (line_len != 0 && isspace(line[line_len - 1]))
  776. line[--line_len] = '\0';
  777. c = strchr(line, '\n');
  778. if (c)
  779. *c = 0;
  780. line_ip = -1;
  781. /*
  782. * Strip leading spaces:
  783. */
  784. tmp = line;
  785. while (*tmp) {
  786. if (*tmp != ' ')
  787. break;
  788. tmp++;
  789. }
  790. if (*tmp) {
  791. /*
  792. * Parse hexa addresses followed by ':'
  793. */
  794. line_ip = strtoull(tmp, &tmp2, 16);
  795. if (*tmp2 != ':')
  796. line_ip = -1;
  797. }
  798. if (line_ip != -1) {
  799. u64 start = map__rip_2objdump(self->ms.map, sym->start);
  800. offset = line_ip - start;
  801. }
  802. objdump_line = objdump_line__new(offset, line);
  803. if (objdump_line == NULL) {
  804. free(line);
  805. return -1;
  806. }
  807. objdump__add_line(head, objdump_line);
  808. return 0;
  809. }
  810. int hist_entry__annotate(struct hist_entry *self, struct list_head *head)
  811. {
  812. struct symbol *sym = self->ms.sym;
  813. struct map *map = self->ms.map;
  814. struct dso *dso = map->dso;
  815. const char *filename = dso->long_name;
  816. char command[PATH_MAX * 2];
  817. FILE *file;
  818. u64 len;
  819. if (!filename)
  820. return -1;
  821. if (dso->origin == DSO__ORIG_KERNEL) {
  822. if (dso->annotate_warned)
  823. return 0;
  824. dso->annotate_warned = 1;
  825. pr_err("Can't annotate %s: No vmlinux file was found in the "
  826. "path:\n", sym->name);
  827. vmlinux_path__fprintf(stderr);
  828. return -1;
  829. }
  830. pr_debug("%s: filename=%s, sym=%s, start=%#Lx, end=%#Lx\n", __func__,
  831. filename, sym->name, map->unmap_ip(map, sym->start),
  832. map->unmap_ip(map, sym->end));
  833. len = sym->end - sym->start;
  834. pr_debug("annotating [%p] %30s : [%p] %30s\n",
  835. dso, dso->long_name, sym, sym->name);
  836. snprintf(command, sizeof(command),
  837. "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s|grep -v %s|expand",
  838. map__rip_2objdump(map, sym->start),
  839. map__rip_2objdump(map, sym->end),
  840. filename, filename);
  841. pr_debug("Executing: %s\n", command);
  842. file = popen(command, "r");
  843. if (!file)
  844. return -1;
  845. while (!feof(file))
  846. if (hist_entry__parse_objdump_line(self, file, head) < 0)
  847. break;
  848. pclose(file);
  849. return 0;
  850. }
  851. void hists__inc_nr_events(struct hists *self, u32 type)
  852. {
  853. ++self->stats.nr_events[0];
  854. ++self->stats.nr_events[type];
  855. }
  856. size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
  857. {
  858. int i;
  859. size_t ret = 0;
  860. for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
  861. if (!event__name[i])
  862. continue;
  863. ret += fprintf(fp, "%10s events: %10d\n",
  864. event__name[i], self->stats.nr_events[i]);
  865. }
  866. return ret;
  867. }