hist.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #include "hist.h"
  2. struct rb_root hist;
  3. struct rb_root collapse_hists;
  4. struct rb_root output_hists;
  5. int callchain;
  6. struct callchain_param callchain_param = {
  7. .mode = CHAIN_GRAPH_REL,
  8. .min_percent = 0.5
  9. };
  10. unsigned long total;
  11. unsigned long total_mmap;
  12. unsigned long total_comm;
  13. unsigned long total_fork;
  14. unsigned long total_unknown;
  15. unsigned long total_lost;
  16. /*
  17. * histogram, sorted on item, collects counts
  18. */
  19. struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map,
  20. struct symbol *sym,
  21. struct symbol *sym_parent,
  22. u64 ip, u64 count, char level, bool *hit)
  23. {
  24. struct rb_node **p = &hist.rb_node;
  25. struct rb_node *parent = NULL;
  26. struct hist_entry *he;
  27. struct hist_entry entry = {
  28. .thread = thread,
  29. .map = map,
  30. .sym = sym,
  31. .ip = ip,
  32. .level = level,
  33. .count = count,
  34. .parent = sym_parent,
  35. };
  36. int cmp;
  37. while (*p != NULL) {
  38. parent = *p;
  39. he = rb_entry(parent, struct hist_entry, rb_node);
  40. cmp = hist_entry__cmp(&entry, he);
  41. if (!cmp) {
  42. *hit = true;
  43. return he;
  44. }
  45. if (cmp < 0)
  46. p = &(*p)->rb_left;
  47. else
  48. p = &(*p)->rb_right;
  49. }
  50. he = malloc(sizeof(*he));
  51. if (!he)
  52. return NULL;
  53. *he = entry;
  54. rb_link_node(&he->rb_node, parent, p);
  55. rb_insert_color(&he->rb_node, &hist);
  56. *hit = false;
  57. return he;
  58. }
  59. int64_t
  60. hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
  61. {
  62. struct sort_entry *se;
  63. int64_t cmp = 0;
  64. list_for_each_entry(se, &hist_entry__sort_list, list) {
  65. cmp = se->cmp(left, right);
  66. if (cmp)
  67. break;
  68. }
  69. return cmp;
  70. }
  71. int64_t
  72. hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
  73. {
  74. struct sort_entry *se;
  75. int64_t cmp = 0;
  76. list_for_each_entry(se, &hist_entry__sort_list, list) {
  77. int64_t (*f)(struct hist_entry *, struct hist_entry *);
  78. f = se->collapse ?: se->cmp;
  79. cmp = f(left, right);
  80. if (cmp)
  81. break;
  82. }
  83. return cmp;
  84. }
  85. void hist_entry__free(struct hist_entry *he)
  86. {
  87. free(he);
  88. }
  89. /*
  90. * collapse the histogram
  91. */
  92. void collapse__insert_entry(struct hist_entry *he)
  93. {
  94. struct rb_node **p = &collapse_hists.rb_node;
  95. struct rb_node *parent = NULL;
  96. struct hist_entry *iter;
  97. int64_t cmp;
  98. while (*p != NULL) {
  99. parent = *p;
  100. iter = rb_entry(parent, struct hist_entry, rb_node);
  101. cmp = hist_entry__collapse(iter, he);
  102. if (!cmp) {
  103. iter->count += he->count;
  104. hist_entry__free(he);
  105. return;
  106. }
  107. if (cmp < 0)
  108. p = &(*p)->rb_left;
  109. else
  110. p = &(*p)->rb_right;
  111. }
  112. rb_link_node(&he->rb_node, parent, p);
  113. rb_insert_color(&he->rb_node, &collapse_hists);
  114. }
  115. void collapse__resort(void)
  116. {
  117. struct rb_node *next;
  118. struct hist_entry *n;
  119. if (!sort__need_collapse)
  120. return;
  121. next = rb_first(&hist);
  122. while (next) {
  123. n = rb_entry(next, struct hist_entry, rb_node);
  124. next = rb_next(&n->rb_node);
  125. rb_erase(&n->rb_node, &hist);
  126. collapse__insert_entry(n);
  127. }
  128. }
  129. /*
  130. * reverse the map, sort on count.
  131. */
  132. void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
  133. {
  134. struct rb_node **p = &output_hists.rb_node;
  135. struct rb_node *parent = NULL;
  136. struct hist_entry *iter;
  137. if (callchain)
  138. callchain_param.sort(&he->sorted_chain, &he->callchain,
  139. min_callchain_hits, &callchain_param);
  140. while (*p != NULL) {
  141. parent = *p;
  142. iter = rb_entry(parent, struct hist_entry, rb_node);
  143. if (he->count > iter->count)
  144. p = &(*p)->rb_left;
  145. else
  146. p = &(*p)->rb_right;
  147. }
  148. rb_link_node(&he->rb_node, parent, p);
  149. rb_insert_color(&he->rb_node, &output_hists);
  150. }
  151. void output__resort(u64 total_samples)
  152. {
  153. struct rb_node *next;
  154. struct hist_entry *n;
  155. struct rb_root *tree = &hist;
  156. u64 min_callchain_hits;
  157. min_callchain_hits =
  158. total_samples * (callchain_param.min_percent / 100);
  159. if (sort__need_collapse)
  160. tree = &collapse_hists;
  161. next = rb_first(tree);
  162. while (next) {
  163. n = rb_entry(next, struct hist_entry, rb_node);
  164. next = rb_next(&n->rb_node);
  165. rb_erase(&n->rb_node, tree);
  166. output__insert_entry(n, min_callchain_hits);
  167. }
  168. }