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