• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * @file diff_container.cpp
3  * Container for diffed symbols
4  *
5  * @remark Copyright 2005 OProfile authors
6  * @remark Read the file COPYING
7  *
8  * @author Philippe Elie
9  * @author John Levon
10  */
11 
12 /* older glibc has C99 INFINITY in _GNU_SOURCE */
13 #ifndef _GNU_SOURCE
14 #define _GNU_SOURCE
15 #endif
16 
17 #include "diff_container.h"
18 
19 #include <cmath>
20 
21 using namespace std;
22 
23 
24 namespace {
25 
26 
27 /// a comparator suitable for diffing symbols
rough_less(symbol_entry const & lhs,symbol_entry const & rhs)28 bool rough_less(symbol_entry const & lhs, symbol_entry const & rhs)
29 {
30 	if (lhs.image_name != rhs.image_name)
31 		return lhs.image_name < rhs.image_name;
32 
33 	if (lhs.app_name != rhs.app_name)
34 		return lhs.app_name < rhs.app_name;
35 
36 	if (lhs.name != rhs.name)
37 		return lhs.name < rhs.name;
38 
39 	return false;
40 }
41 
42 
43 /// possibly add a diff sym
44 void
add_sym(diff_collection & syms,diff_symbol const & sym,profile_container::symbol_choice & choice)45 add_sym(diff_collection & syms, diff_symbol const & sym,
46         profile_container::symbol_choice & choice)
47 {
48 	if (choice.match_image
49 	    && (image_names.name(sym.image_name) != choice.image_name))
50 		return;
51 
52 	if (fabs(sym.diffs[0]) < choice.threshold)
53 		return;
54 
55 	choice.hints = sym.output_hint(choice.hints);
56 	syms.push_back(sym);
57 }
58 
59 
60 /// add a symbol not present in the new profile
61 void
symbol_old(diff_collection & syms,symbol_entry const & sym,profile_container::symbol_choice & choice)62 symbol_old(diff_collection & syms, symbol_entry const & sym,
63            profile_container::symbol_choice & choice)
64 {
65 	diff_symbol symbol(sym);
66 	symbol.diffs.fill(sym.sample.counts.size(), -INFINITY);
67 	add_sym(syms, symbol, choice);
68 }
69 
70 
71 /// add a symbol not present in the old profile
72 void
symbol_new(diff_collection & syms,symbol_entry const & sym,profile_container::symbol_choice & choice)73 symbol_new(diff_collection & syms, symbol_entry const & sym,
74            profile_container::symbol_choice & choice)
75 {
76 	diff_symbol symbol(sym);
77 	symbol.diffs.fill(sym.sample.counts.size(), INFINITY);
78 	add_sym(syms, symbol, choice);
79 }
80 
81 
82 /// add a diffed symbol
symbol_diff(diff_collection & syms,symbol_entry const & sym1,count_array_t const & total1,symbol_entry const & sym2,count_array_t const & total2,profile_container::symbol_choice & choice)83 void symbol_diff(diff_collection & syms,
84                  symbol_entry const & sym1, count_array_t const & total1,
85                  symbol_entry const & sym2, count_array_t const & total2,
86                  profile_container::symbol_choice & choice)
87 {
88 	diff_symbol symbol(sym2);
89 
90 	size_t size = sym2.sample.counts.size();
91 	for (size_t i = 0; i != size; ++i) {
92 		double percent1;
93 		double percent2;
94 		percent1 = op_ratio(sym1.sample.counts[i], total1[i]);
95 		percent2 = op_ratio(sym2.sample.counts[i], total2[i]);
96 		symbol.diffs[i] = op_ratio(percent2 - percent1, percent1);
97 		symbol.diffs[i] *= 100.0;
98 	}
99 
100 	add_sym(syms, symbol, choice);
101 }
102 
103 
104 }; // namespace anon
105 
106 
diff_container(profile_container const & c1,profile_container const & c2)107 diff_container::diff_container(profile_container const & c1,
108                                profile_container const & c2)
109 	: pc1(c1), pc2(c2),
110 	  total1(pc1.samples_count()), total2(pc2.samples_count())
111 {
112 }
113 
114 
115 diff_collection const
get_symbols(profile_container::symbol_choice & choice) const116 diff_container::get_symbols(profile_container::symbol_choice & choice) const
117 {
118 	diff_collection syms;
119 
120 	/*
121 	 * Do a pairwise comparison of the two symbol sets. We're
122 	 * relying here on the symbol container being sorted such
123 	 * that rough_less() is suitable for iterating through the
124 	 * two lists (see less_symbol).
125 	 */
126 
127 	symbol_container::symbols_t::iterator it1 = pc1.begin_symbol();
128 	symbol_container::symbols_t::iterator end1 = pc1.end_symbol();
129 	symbol_container::symbols_t::iterator it2 = pc2.begin_symbol();
130 	symbol_container::symbols_t::iterator end2 = pc2.end_symbol();
131 
132 	while (it1 != end1 && it2 != end2) {
133 		if (rough_less(*it1, *it2)) {
134 			symbol_old(syms, *it1, choice);
135 			++it1;
136 		} else if (rough_less(*it2, *it1)) {
137 			symbol_new(syms, *it2, choice);
138 			++it2;
139 		} else {
140 			symbol_diff(syms, *it1, total1, *it2, total2, choice);
141 			++it1;
142 			++it2;
143 		}
144 	}
145 
146 	for (; it1 != end1; ++it1)
147 		symbol_old(syms, *it1, choice);
148 
149 	for (; it2 != end2; ++it2)
150 		symbol_new(syms, *it2, choice);
151 
152 	return syms;
153 }
154 
155 
samples_count() const156 count_array_t const diff_container::samples_count() const
157 {
158 	return total2;
159 }
160