hist.c 3.7 KB

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