~arosales/test/oprofile

« back to all changes in this revision

Viewing changes to libpp/diff_container.cpp

  • Committer: Antonio Rosales
  • Date: 2013-03-28 08:40:26 UTC
  • Revision ID: antonio.rosales@canonical.com-20130328084026-gpqns1mkqd7cnr05
Move files up one directory.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
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
 
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
 
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
 
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
 
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
 
 
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
 
116
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
 
 
156
count_array_t const diff_container::samples_count() const
 
157
{
 
158
        return total2;
 
159
}