profile_container.cpp

Go to the documentation of this file.
00001 
00012 #include <set>
00013 #include <vector>
00014 #include <string>
00015 #include <iostream>
00016 #include <sstream>
00017 #include <algorithm>
00018 #include <numeric>
00019 
00020 #include "symbol.h"
00021 #include "op_header.h"
00022 #include "profile.h"
00023 #include "symbol_functors.h"
00024 #include "profile_container.h"
00025 #include "sample_container.h"
00026 #include "symbol_container.h"
00027 #include "populate_for_spu.h"
00028 
00029 using namespace std;
00030 
00031 namespace {
00032 
00033 struct filename_by_samples {
00034     filename_by_samples(debug_name_id id, double percent_)
00035         : filename(id), percent(percent_)
00036         {}
00037 
00038     bool operator<(filename_by_samples const & lhs) const {
00039         if (percent != lhs.percent)
00040             return percent < lhs.percent;
00041         return filename < lhs.filename;
00042     }
00043 
00044     debug_name_id filename;
00045     // ratio of samples which belongs to this filename.
00046     double percent;
00047 };
00048 
00049 }  // anon namespace
00050 
00051 
00052 profile_container::profile_container(bool debug_info_, bool need_details_,
00053                      extra_images const & extra_)
00054     :
00055     symbols(new symbol_container),
00056     samples(new sample_container),
00057     debug_info(debug_info_),
00058     need_details(need_details_),
00059     extra_found_images(extra_)
00060 {
00061 }
00062 
00063 
00064 profile_container::~profile_container()
00065 {
00066 }
00067  
00068 
00069 // Post condition:
00070 //  the symbols/samples are sorted by increasing vma.
00071 //  the range of sample_entry inside each symbol entry are valid
00072 //  the samples_by_file_loc member var is correctly setup.
00073 void profile_container::add(profile_t const & profile,
00074                             op_bfd const & abfd, string const & app_name,
00075                             size_t pclass)
00076 {
00077     string const image_name = abfd.get_filename();
00078     opd_header header = profile.get_header();
00079 
00080     for (symbol_index_t i = 0; i < abfd.syms.size(); ++i) {
00081 
00082         unsigned long long start = 0, end = 0;
00083         symbol_entry symb_entry;
00084 
00085         abfd.get_symbol_range(i, start, end);
00086 
00087         profile_t::iterator_pair p_it =
00088             profile.samples_range(start, end);
00089         count_type count = accumulate(p_it.first, p_it.second, 0ull);
00090 
00091         // skip entries with no samples
00092         if (count == 0)
00093             continue;
00094 
00095         symb_entry.sample.counts[pclass] = count;
00096         total_count[pclass] += count;
00097 
00098         symb_entry.size = end - start;
00099 
00100         symb_entry.name = symbol_names.create(abfd.syms[i].name());
00101         symb_entry.sym_index = i;
00102         symb_entry.vma_adj = abfd.get_vma_adj();
00103 
00104         symb_entry.sample.file_loc.linenr = 0;
00105         if (debug_info) {
00106             string filename;
00107             if (abfd.get_linenr(i, start, filename,
00108                 symb_entry.sample.file_loc.linenr)) {
00109                 symb_entry.sample.file_loc.filename =
00110                     debug_names.create(filename);
00111             }
00112         }
00113 
00114         symb_entry.image_name = image_names.create(image_name);
00115         symb_entry.app_name = image_names.create(app_name);
00116 
00117         symb_entry.sample.vma = abfd.syms[i].vma();
00118         if ((header.spu_profile == cell_spu_profile) &&
00119             header.embedded_offset) {
00120             symb_entry.spu_offset = header.embedded_offset;
00121             symb_entry.embedding_filename =
00122                 image_names.create(abfd.get_embedding_filename());
00123         } else {
00124             symb_entry.spu_offset = 0;
00125         }
00126         symbol_entry const * symbol = symbols->insert(symb_entry);
00127 
00128         if (need_details)
00129             add_samples(abfd, i, p_it, symbol, pclass, start);
00130     }
00131 }
00132 
00133 
00134 void
00135 profile_container::add_samples(op_bfd const & abfd, symbol_index_t sym_index,
00136                                profile_t::iterator_pair const & p_it,
00137                                symbol_entry const * symbol, size_t pclass,
00138                    unsigned long start)
00139 {
00140     bfd_vma base_vma = abfd.syms[sym_index].vma();
00141 
00142     profile_t::const_iterator it;
00143     for (it = p_it.first; it != p_it.second ; ++it) {
00144         sample_entry sample;
00145 
00146         sample.counts[pclass] = it.count();
00147 
00148         sample.file_loc.linenr = 0;
00149         if (debug_info) {
00150             string filename;
00151             if (abfd.get_linenr(sym_index, it.vma(), filename,
00152                     sample.file_loc.linenr)) {
00153                 sample.file_loc.filename =
00154                     debug_names.create(filename);
00155             }
00156         }
00157 
00158         sample.vma = (it.vma() - start) + base_vma;
00159 
00160         samples->insert(symbol, sample);
00161     }
00162 }
00163 
00164 
00165 symbol_collection const
00166 profile_container::select_symbols(symbol_choice & choice) const
00167 {
00168     symbol_collection result;
00169 
00170     double const threshold = choice.threshold / 100.0;
00171 
00172     symbol_container::symbols_t::iterator it = symbols->begin();
00173     symbol_container::symbols_t::iterator const end = symbols->end();
00174 
00175     for (; it != end; ++it) {
00176         if (choice.match_image
00177             && (image_names.name(it->image_name) != choice.image_name))
00178             continue;
00179 
00180         double const percent =
00181             op_ratio(it->sample.counts[0], total_count[0]);
00182 
00183         if (percent >= threshold) {
00184             result.push_back(&*it);
00185 
00186             choice.hints = it->output_hint(choice.hints);
00187         }
00188     }
00189 
00190     return result;
00191 }
00192 
00193 
00194 vector<debug_name_id> const
00195 profile_container::select_filename(double threshold) const
00196 {
00197     set<debug_name_id> filename_set;
00198 
00199     threshold /= 100.0;
00200 
00201     // Trying to iterate on symbols to create the set of filenames which
00202     // contain sample does not work: a symbol can contain samples and this
00203     // symbol is in a source file that contain zero sample because only
00204     // inline function in this source file contains samples.
00205     sample_container::samples_iterator sit = samples->begin();
00206     sample_container::samples_iterator const send = samples->end();
00207 
00208     for (; sit != send; ++sit) {
00209         debug_name_id name_id = sit->second.file_loc.filename;
00210         if (name_id.set())
00211             filename_set.insert(name_id);
00212     }
00213 
00214     // Give a sort order on filename for the selected pclass.
00215     vector<filename_by_samples> file_by_samples;
00216 
00217     set<debug_name_id>::const_iterator it = filename_set.begin();
00218     set<debug_name_id>::const_iterator const end = filename_set.end();
00219     for (; it != end; ++it) {
00220         // FIXME: is samples_count() the right interface now ?
00221         count_array_t counts = samples_count(*it);
00222 
00223         double const ratio = op_ratio(counts[0], total_count[0]);
00224         filename_by_samples const f(*it, ratio);
00225 
00226         file_by_samples.push_back(f);
00227     }
00228 
00229     // now sort the file_by_samples entry.
00230     sort(file_by_samples.begin(), file_by_samples.end());
00231 
00232     // 2.91.66 doesn't like const_reverse_iterator in this context
00233     vector<filename_by_samples>::reverse_iterator cit
00234         = file_by_samples.rbegin();
00235     vector<filename_by_samples>::reverse_iterator const cend
00236         = file_by_samples.rend();
00237 
00238     vector<debug_name_id> result;
00239     for (; cit != cend; ++cit) {
00240         if (cit->percent >= threshold)
00241             result.push_back(cit->filename);
00242     }
00243 
00244     return result;
00245 }
00246 
00247 
00248 count_array_t profile_container::samples_count() const
00249 {
00250     return total_count;
00251 }
00252 
00253 
00254 // Rest here are delegated to our private implementation.
00255 
00256 symbol_entry const *
00257 profile_container::find_symbol(string const & image_name, bfd_vma vma) const
00258 {
00259     return symbols->find_by_vma(image_name, vma);
00260 }
00261 
00262 
00263 symbol_collection const
00264 profile_container::find_symbol(debug_name_id filename, size_t linenr) const
00265 {
00266     return symbols->find(filename, linenr);
00267 }
00268 
00269 
00270 symbol_collection const
00271 profile_container::select_symbols(debug_name_id filename) const
00272 {
00273     return symbols->find(filename);
00274 }
00275 
00276 sample_entry const *
00277 profile_container::find_sample(symbol_entry const * symbol, bfd_vma vma) const
00278 {
00279     return samples->find_by_vma(symbol, vma);
00280 }
00281 
00282 
00283 count_array_t profile_container::samples_count(debug_name_id filename_id) const
00284 {
00285     return samples->accumulate_samples(filename_id);
00286 }
00287 
00288 
00289 count_array_t profile_container::samples_count(debug_name_id filename,
00290                     size_t linenr) const
00291 {
00292     return samples->accumulate_samples(filename, linenr);
00293 }
00294 
00295 
00296 sample_container::samples_iterator
00297 profile_container::begin(symbol_entry const * symbol) const
00298 {
00299     return samples->begin(symbol);
00300 }
00301 
00302 
00303 sample_container::samples_iterator
00304 profile_container::end(symbol_entry const * symbol) const
00305 {
00306     return samples->end(symbol);
00307 }
00308 
00309 
00310 sample_container::samples_iterator profile_container::begin() const
00311 {
00312     return samples->begin();
00313 }
00314 
00315 
00316 sample_container::samples_iterator profile_container::end() const
00317 {
00318     return samples->end();
00319 }
00320 
00321 symbol_entry const * profile_container::find(symbol_entry const & symbol) const
00322 {
00323     return symbols->find(symbol);
00324 }
00325 
00326 symbol_container::symbols_t::iterator profile_container::begin_symbol() const
00327 {
00328     return symbols->begin();
00329 }
00330 
00331 symbol_container::symbols_t::iterator profile_container::end_symbol() const
00332 {
00333     return symbols->end();
00334 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1