CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ProfParse.cc
Go to the documentation of this file.
1 
2 #include <algorithm>
3 #include <fstream>
4 #include <iostream>
5 #include <map>
6 #include <set>
7 #include <sstream>
8 #include <stdexcept>
9 #include <string>
10 #include <vector>
11 
12 #include <dlfcn.h>
13 #include <unistd.h>
14 
15 #include "VertexTracker.h"
16 
17 //#include "FWCore/Utilities/interface/Algorithms.h"
18 
19 #if 0
20 extern "C" {
21  // options:
22 #define DMGL_AUTO (1 << 8)
23  extern char* cplus_demangle(const char *mangled, int options);
24 }
25 #endif
26 
27 // ----------------- Path tracker class ---------------------
28 
30 {
31  PathTracker(): id_(),total_() { }
32 
33  mutable unsigned int id_;
34  mutable unsigned int total_;
36 
37  bool operator<(const PathTracker& a) const;
38  void setID() const { id_=next_id_++; }
39  void incTotal() const { ++total_; }
40 
41  static unsigned int next_id_;
42 };
43 
44 unsigned int PathTracker::next_id_ = 0;
45 
47 {
48  return tree_ < a.tree_;
49 }
50 
51 std::ostream& operator<<(std::ostream& ost, const PathTracker& a)
52 {
53  ost << a.id_ << " " << a.total_ << " ";
54  ULVec::const_iterator i(a.tree_.begin()),e(a.tree_.end());
55  while(i!=e) { ost << (unsigned int)*i << " "; ++i; }
56  return ost;
57 }
58 
59 // ------------------- utilities --------------------------
60 
61 void verifyFile(std::ostream& ost, const std::string& name)
62 {
63  if(!ost) {
64  std::cerr << "cannot open output file " << name << std::endl;
65  throw std::runtime_error("failed to open output file");
66  }
67 }
68 
69 
70 // ------------- more utilities ----------------
71 
72 static bool symSort(const VertexSet::const_iterator& a,
73  const VertexSet::const_iterator& b)
74 {
75  return a->total_as_leaf_ < b->total_as_leaf_;
76 }
77 
78 static bool idSort(const VertexSet::const_iterator& a,
79  const VertexSet::const_iterator& b)
80 {
81  return a->id_ < b->id_;
82 }
83 
84 static bool idComp(unsigned int id,
85  const VertexSet::const_iterator& b)
86 {
87  return id < b->id_;
88 }
89 
90 static bool pathSort(const PathSet::const_iterator& a,
91  const PathSet::const_iterator& b)
92 {
93  return a->total_ < b->total_;
94 }
95 
96 // ------------------ main routine --------------------
97 
98 class Reader
99 {
100  public:
101  explicit Reader(int fd):fd_(fd) { }
102  bool nextSample(VoidVec& vv);
103  private:
104  int fd_;
105 };
106 
108 {
109  unsigned int cnt;
110  int sz = read(fd_,&cnt,sizeof(unsigned int));
111 
112  if(sz<0) {
113  perror("Reader::nextSample: read count");
114  std::cerr << "could not read next sample from profile data\n";
115  return false;
116  }
117  if(sz == 0) return false;
118  if((unsigned)sz<sizeof(unsigned int)) {
119  std::cerr << "Reader::nextSample: "
120  << "could not read the correct amount of profile data\n";
121  return false;
122  }
123  if(cnt > 1000) {
124  std::cerr << "Reader::nextSample: stack length is nonsense " << cnt << "\n";
125  return false;
126  }
127 
128  vv.resize(cnt);
129  void** pos = &vv[0];
130  int byte_cnt = cnt*sizeof(void*);
131 
132  while((sz = read(fd_,pos,byte_cnt)) < byte_cnt) {
133  if(sz < 0) {
134  perror("Reader::nextSample: read stack");
135  std::cerr << "could not read stack\n";
136  return false;
137  }
138  byte_cnt -= sz;
139  pos += sz;
140  }
141  return true;
142 }
143 
144 std::string make_name(Dl_info const& info, void* where,
145  std::string const& prefix)
146 {
147  std::string object_name;
148  if (info.dli_fname == 0 || info.dli_fname[0] == 0x0) {
149  std::ostringstream oss;
150  oss << "no_object_" << where;
151  return oss.str();
152  }
153  if (info.dli_saddr) return info.dli_sname;
154  std::ostringstream oss;
155  oss << prefix << where;
156  return oss.str();
157 }
158 
159 void writeProfileData(int fd, const std::string& prefix)
160 {
161  std::string output_tree(prefix+"_paths");
162  std::string output_names(prefix+"_names");
163  std::string output_totals(prefix+"_totals");
164 
165  std::ofstream nost(output_names.c_str());
166  std::ofstream tost(output_tree.c_str());
167  std::ofstream sost(output_totals.c_str());
168 
169  verifyFile(nost,output_names);
170  verifyFile(tost,output_tree);
171  verifyFile(sost,output_totals);
172 
173  VertexSet symset;
174  PathSet pathset;
175  std::pair<VertexSet::iterator,bool> irc,prev_irc;
176  std::pair<PathSet::iterator,bool> prc;
177 
178  VoidVec v;
179  int len=0;
180  int total=0;
181  int total_failed=0;
182  int total_missing=0;
183  // int failure_count=0;
184  Sym last_none_entry;
185  Sym last_good_entry;
186  Reader r(fd);
187  std::string unk("unknown_name");
188 
189  while (r.nextSample(v)) {
190  PathTracker ptrack;
191  ++total;
192  len = v.size();
193  if(len==0) continue; // should never happen!
194  VoidVec::reverse_iterator c(v.rbegin()),e(v.rend());
195  bool first_pass=true;
196 
197  while(c != e) {
198  Sym::address_type value = reinterpret_cast<Sym::address_type>(*c);
199 
200  const Sym* entry = 0;
201  Dl_info info;
202  void* addr = static_cast<void*>(value);
203 
204  if(dladdr(addr,&info) != 0) {
205  std::string name = make_name(info, addr, "unknown_");
206 
207  last_good_entry.name_ = name;
208  last_good_entry.library_ = info.dli_fname;
209  last_good_entry.id_ = 0;
210  void* function_address = info.dli_saddr;
211 
212  // If we find the address of this function, we make a
213  // unique VertexTracker for that function. If not, we
214  // make a unique VertexTracker for this exact address.
215  last_good_entry.addr_ =
216  function_address ? function_address : value;
217 
218  entry = &last_good_entry;
219  } else { // dladdr has failed
220  /*
221  std::cerr << "sample " << total
222  << ": dladdr failed for address: " << *c
223  << std::endl;
224  */
225  ++total_failed;
226  std::ostringstream oss;
227  oss << "lookup_failure_" << addr;
228  last_none_entry.name_ = oss.str();
229  last_none_entry.library_ = "unknown";
230  last_none_entry.id_ = Sym::next_id_++;
231  last_none_entry.addr_ = value;
232 
233  entry = &last_none_entry;
234  }
235 
236  irc = symset.insert(VertexTracker(*entry));
237  if(irc.second) {
238  irc.first->setID();
239  }
240  irc.first->incTotal();
241  ptrack.tree_.push_back(irc.first->id_);
242 
243  if(!first_pass) ++prev_irc.first->edges_[irc.first->id_];
244  else first_pass=false;
245 
246  prev_irc = irc;
247  ++c;
248  }
249 
250  irc.first->incLeaf();
251  prc = pathset.insert(ptrack);
252  if(prc.second) {
253  prc.first->setID();
254  }
255  prc.first->incTotal();
256  }
257 
258  // ------------------ copy the vertices for sorting and searching ------
259 
260  int setsize = symset.size();
261  int edgesize = 0;
262  Viter vsyms;
263  vsyms.reserve(setsize);
264 
265  //cout << "------ symset -----" << std::endl;
266  VertexSet::const_iterator isym(symset.begin()),esym(symset.end());
267  while(isym!=esym) {
268  //cout << " " << *isym << std::endl;
269  vsyms.push_back(isym);
270  ++isym;
271  }
272 
273  // ------ calculate samples for parents and percentages in vertices ------
274 
275  //edm::sort_all(vsyms,idSort);
276  std::sort(vsyms.begin(), vsyms.end(), idSort);
277  //Viter::iterator Vib(vsyms.begin()),Vie(vsyms.end());
278  //std::cout << "sorted table --------------" << std::endl;
279  //while(Vib!=Vie) { std::cout << " " << *(*Vib) << std::endl; ++Vib; }
280 
281  PathSet::const_iterator pat_it_beg(pathset.begin()),
282  pat_it_end(pathset.end());
283 
284  while(pat_it_beg!=pat_it_end) {
285  // get set of unique IDs from the path
286  ULVec pathcopy(pat_it_beg->tree_);
287  //edm::sort_all(pathcopy);
288  std::sort(pathcopy.begin(), pathcopy.end());
289  ULVec::iterator iter = unique(pathcopy.begin(),pathcopy.end());
290  ULVec::iterator cop_beg(pathcopy.begin());
291  //cout << "length of unique = " << distance(cop_beg,iter) << std::endl;
292  while(cop_beg!=iter) {
293  //cout << " entry " << *cop_beg << std::endl;
294  Viter::iterator sym_iter = upper_bound(vsyms.begin(),vsyms.end(),
295  *cop_beg,idComp);
296  if(sym_iter==vsyms.begin()) {
297  ++total_missing;
298  /*
299  std::cerr << "found a missing sym entry for address " << *cop_beg
300  << std::endl;
301  */
302  } else {
303  --sym_iter;
304  //cout << " symiter " << *(*sym_iter) << std::endl;
305  (*sym_iter)->incPath(pat_it_beg->total_);
306  }
307  ++cop_beg;
308  }
309 
310  ++pat_it_beg;
311  }
312 
313  VertexSet::iterator ver_iter(symset.begin()),ver_iter_end(symset.end());
314  float ftotal = (total != 0 ? (float)total : 1.0); // Avoids possible divide by zero.
315  while(ver_iter != ver_iter_end) {
316  ver_iter->percent_leaf_ = (float)ver_iter->total_as_leaf_ / ftotal;
317  ver_iter->percent_path_ = (float)ver_iter->in_path_ / ftotal;
318  ++ver_iter;
319  }
320 
321  // -------------- write out the vertices ----------------
322 
323 
324  //edm::sort_all(vsyms,symSort);
325  std::sort(vsyms.begin(), vsyms.end(), symSort);
326  Viter::reverse_iterator vvi(vsyms.rbegin()),vve(vsyms.rend());
327  while(vvi != vve) {
328  nost << *(*vvi) << "\n";
329  ++vvi;
330  }
331 
332 
333  // --------------- write out the paths ------------------
334 
335  int pathsize = pathset.size();
336  Piter vpaths;
337  vpaths.reserve(pathsize);
338 
339  PathSet::const_iterator ipath(pathset.begin()),epath(pathset.end());
340  while(ipath != epath) {
341  vpaths.push_back(ipath);
342  ++ipath;
343  }
344 
345  //edm::sort_all(vpaths,pathSort);
346  std::sort(vpaths.begin(),vpaths.end(),pathSort);
347 
348  Piter::reverse_iterator ppi(vpaths.rbegin()),ppe(vpaths.rend());
349  while(ppi != ppe) {
350  tost << *(*ppi) << "\n";
351  ++ppi;
352  }
353 
354  // ------------ totals --------------------
355  sost << "total_samples " << total << "\n"
356  << "total_functions " << setsize << "\n"
357  << "total_paths " << pathsize << "\n"
358  << "total_edges " << edgesize << std::endl
359  << "total_failed_lookups " << total_failed << std::endl
360  << "total_missing_sym_entries " << total_missing << std::endl;
361 
362 }
363 
364 extern "C" {
365  void writeProfileDataC(int fd, const std::string& prefix)
366  {
367  writeProfileData(fd,prefix);
368  }
369 }
370 
371 
372 
Definition: Sym.h:9
int i
Definition: DBlmapReader.cc:9
static bool idSort(const VertexSet::const_iterator &a, const VertexSet::const_iterator &b)
Definition: ProfParse.cc:78
std::vector< VertexSet::const_iterator > Viter
static bool idComp(unsigned int id, const VertexSet::const_iterator &b)
Definition: ProfParse.cc:84
std::ostream & operator<<(std::ostream &out, const ALILine &li)
Definition: ALILine.cc:187
static bool symSort(const VertexSet::const_iterator &a, const VertexSet::const_iterator &b)
Definition: ProfParse.cc:72
Reader(int fd)
Definition: ProfParse.cc:101
void * address_type
Definition: Sym.h:10
int fd_
Definition: ProfParse.cc:104
ULVec tree_
Definition: ProfParse.cc:35
std::pair< std::string, MonitorElement * > entry
Definition: ME_MAP.h:8
std::string make_name(Dl_info const &info, void *where, std::string const &prefix)
Definition: ProfParse.cc:144
std::string library_
Definition: Sym.h:34
unsigned int total_
Definition: ProfParse.cc:34
bool operator<(const PathTracker &a) const
Definition: ProfParse.cc:46
std::string name_
Definition: Sym.h:33
std::vector< void * > VoidVec
std::vector< PathSet::const_iterator > Piter
unsigned int id_
Definition: ProfParse.cc:33
double b
Definition: hdecay.h:120
std::vector< unsigned int > ULVec
void incTotal() const
Definition: ProfParse.cc:39
address_type addr_
Definition: Sym.h:36
static int next_id_
Definition: Sym.h:38
void writeProfileDataC(int fd, const std::string &prefix)
Definition: ProfParse.cc:365
bool nextSample(VoidVec &vv)
Definition: ProfParse.cc:107
static unsigned int next_id_
Definition: ProfParse.cc:41
double a
Definition: hdecay.h:121
void writeProfileData(int fd, const std::string &prefix)
Definition: ProfParse.cc:159
void verifyFile(std::ostream &ost, const std::string &name)
Definition: ProfParse.cc:61
void setID() const
Definition: ProfParse.cc:38
std::set< VertexTracker > VertexSet
static bool pathSort(const PathSet::const_iterator &a, const PathSet::const_iterator &b)
Definition: ProfParse.cc:90
std::set< PathTracker > PathSet
int id_
Definition: Sym.h:35