HPCToolkit
Flat-ObjCorrelation.cpp
Go to the documentation of this file.
1 // -*-Mode: C++;-*-
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 //***************************************************************************
48 //
49 // File:
50 // $HeadURL$
51 //
52 // Purpose:
53 // [The purpose of this file]
54 //
55 // Description:
56 // [The set of functions, macros, etc. defined in the file]
57 //
58 //***************************************************************************
59 
60 //************************* System Include Files ****************************
61 
62 #include <iostream>
63 using std::ostream;
64 
65 #include <iomanip>
66 
67 #include <string>
68 using std::string;
69 
70 #include <vector>
71 using std::vector;
72 
73 //*************************** User Include Files ****************************
74 
75 #include "Flat-ObjCorrelation.hpp"
76 #include "TextUtil.hpp"
78 
80 
81 #include <lib/binutils/LM.hpp>
82 #include <lib/binutils/Seg.hpp>
83 #include <lib/binutils/Proc.hpp>
84 #include <lib/binutils/Insn.hpp>
86 
88 #include <lib/support/FileUtil.hpp>
89 #include <lib/support/StrUtil.hpp>
90 
91 //*************************** Forward Declarations ***************************
92 
93 //****************************************************************************
94 
95 namespace Analysis {
96 
97 namespace Flat {
98 
99 
100 //****************************************************************************
101 //
102 //****************************************************************************
103 
105 public:
106  MetricCursor(const Prof::Metric::Mgr& metricMgr,
107  const Prof::Flat::LM& proflm,
108  const BinUtil::LM& lm);
109  ~MetricCursor();
110 
111  const vector<const Prof::Flat::EventData*>&
112  metricDescs() const {
113  return m_metricDescs;
114  }
115  const vector<uint64_t>&
116  metricTots() const {
117  return m_metricTots;
118  }
119 
120  // Assumptions:
121  // - vma's are unrelocated
122  // - over successsive calls, VMA ranges are ascending
123  // Result is stored is metricValAtVMA()
124  const vector<uint64_t>&
126  return computeMetricVals(VMAInterval(vma, vma + 1), true);
127  }
128 
129  // Assumptions:
130  // - same as above
131  // - vmaint: [beg_vma, end_vma), where vmaint is a region
132  const vector<uint64_t>&
133  computeMetricVals(const VMAInterval vmaint, bool advanceIndices);
134 
135  const vector<uint64_t>&
136  metricValAtVMA() const { return m_metricValAtVMA; }
137 
138  static bool
139  hasNonZeroMetricVal(const vector<uint64_t>& metricVal) {
140  return hasMetricValGE(metricVal, 1);
141  }
142 
143  static bool
144  hasMetricValGE(const vector<uint64_t>& metricVal, uint64_t val);
145 
146 private:
147  VMA unrelocate(VMA vma) const {
148  VMA ur_vma = (m_doUnrelocate) ? (vma - m_loadAddr) : vma;
149  return ur_vma;
150  }
151 
152 
153 private:
156 
157  vector<const Prof::Flat::EventData*> m_metricDescs;
158  vector<uint64_t> m_metricTots;
159 
160  vector<uint> m_curMetricIdx;
161  vector<uint64_t> m_metricValAtVMA;
162 };
163 
164 
166  const Prof::Flat::LM& proflm,
167  const BinUtil::LM& lm)
168 {
169  m_loadAddr = (VMA)proflm.load_addr();
171 
172  // --------------------------------------------------------
173  // Find all metrics for load module and compute totals for each metric
174  // For now we have one metric per sampled event.
175  // --------------------------------------------------------
176 
177  // NOTE: only handles raw events
178 
179  for (uint i = 0; i < metricMgr.size(); ++i) {
180  const Prof::Metric::ADesc* m = metricMgr.metric(i);
181  const Prof::Metric::SampledDesc* mm =
182  dynamic_cast<const Prof::Metric::SampledDesc*>(m);
183  if (mm) {
184  uint mIdx = (uint)StrUtil::toUInt64(mm->profileRelId());
185  const Prof::Flat::EventData& profevent = proflm.event(mIdx);
186  m_metricDescs.push_back(&profevent);
187  }
188  }
189 
190  m_metricTots.resize(m_metricDescs.size());
191  for (uint i = 0; i < m_metricDescs.size(); ++i) {
192  const Prof::Flat::EventData& profevent = *(m_metricDescs[i]);
193  uint64_t& metricTotal = m_metricTots[i];
194  metricTotal = 0;
195 
196  for (uint j = 0; j < profevent.num_data(); ++j) {
197  const Prof::Flat::Datum& evdat = profevent.datum(j);
198  uint32_t count = evdat.second;
199  metricTotal += count;
200  }
201  }
202 
203  m_curMetricIdx.resize(m_metricDescs.size());
204  for (uint i = 0; i < m_curMetricIdx.size(); ++i) {
205  m_curMetricIdx[i] = 0;
206  }
207 
208  m_metricValAtVMA.resize(m_metricDescs.size());
209 }
210 
211 
213 {
214 }
215 
216 
217 const vector<uint64_t>&
219  bool advanceCounters)
220 {
221  // NOTE: An instruction may overlap multiple buckets. However,
222  // because only the bucket corresponding to the beginning of the
223  // instruction is charged, we only have to consult one bucket.
224  // However, it may be the case that a bucket contains results for
225  // more than one instruction.
226 
227  for (uint i = 0; i < m_metricValAtVMA.size(); ++i) {
228  m_metricValAtVMA[i] = 0;
229  }
230 
231  // For each event, determine if a count exists at vma_beg
232  for (uint i = 0; i < m_metricDescs.size(); ++i) {
233  const Prof::Flat::EventData& profevent = *(m_metricDescs[i]);
234 
235  // advance ith bucket until it arrives at vmaint region:
236  // (bucket overlaps beg_vma) || (bucket is beyond beg_vma)
237  for (uint& j = m_curMetricIdx[i]; j < profevent.num_data(); ++j) {
238  const Prof::Flat::Datum& evdat = profevent.datum(j);
239  VMA ev_vma = evdat.first;
240  VMA ev_ur_vma = unrelocate(ev_vma);
241  VMA ev_ur_vma_ub = ev_ur_vma + profevent.bucket_size();
242 
243  if ((ev_ur_vma <= vmaint.beg() && vmaint.beg() < ev_ur_vma_ub)
244  || (ev_ur_vma > vmaint.beg())) {
245  break;
246  }
247  }
248 
249  // count until bucket moves beyond vmaint region
250  // INVARIANT: upon entry, bucket overlaps or is beyond region
251  for (uint j = m_curMetricIdx[i]; j < profevent.num_data(); ++j) {
252  const Prof::Flat::Datum& evdat = profevent.datum(j);
253  VMA ev_vma = evdat.first;
254  VMA ev_ur_vma = unrelocate(ev_vma);
255  VMA ev_ur_vma_ub = ev_ur_vma + profevent.bucket_size();
256 
257  if (ev_ur_vma >= vmaint.end()) {
258  // bucket is now beyond region
259  break;
260  }
261  else {
262  // bucket overlaps region (by INVARIANT)
263  uint32_t count = evdat.second;
264  m_metricValAtVMA[i] += count;
265 
266  // if the vmaint region extends beyond the current bucket,
267  // advance bucket
268  if (advanceCounters && (vmaint.end() > ev_ur_vma_ub)) {
269  m_curMetricIdx[i]++;
270  }
271  }
272  }
273  }
274 
275  return m_metricValAtVMA;
276 }
277 
278 
279 bool
280 MetricCursor::hasMetricValGE(const vector<uint64_t>& metricVal, uint64_t val)
281 {
282  for (uint i = 0; i < metricVal.size(); ++i) {
283  if (metricVal[i] >= val) {
284  return true;
285  }
286  }
287  return false;
288 }
289 
290 
291 //****************************************************************************
292 //
293 //****************************************************************************
294 
295 static void
297  const vector<uint64_t>& metricVal,
298  const vector<uint64_t>& metricTot,
299  ColumnFormatter::Flag flg = ColumnFormatter::Flag_NULL);
300 
301 static void
303  const Prof::Flat::LM& proflm,
304  const BinUtil::LM& lm,
305  // ----------------------------------------------
306  std::ostream& os,
307  bool srcCode,
308  const std::vector<std::string>& procPruneGlobs,
309  uint64_t procPruneThreshold);
310 
311 
312 void
314  // ----------------------------------------------
315  std::ostream& os,
316  bool srcCode,
317  const std::vector<std::string>& procPruneGlobs,
318  uint64_t procPruneThreshold)
319 {
320  using Prof::Metric::Mgr;
321 
322  const Mgr::StringToADescVecMap& fnameToFMetricMap =
323  metricMgr.fnameToFMetricMap();
324  DIAG_Assert(fnameToFMetricMap.size() == 1, DIAG_UnexpectedInput);
325 
326  const string& profileFile = fnameToFMetricMap.begin()->first;
327 
329  try {
330  prof.openread(profileFile.c_str());
331  }
332  catch (...) {
333  DIAG_EMsg("While reading '" << profileFile << "'");
334  throw;
335  }
336 
337  // --------------------------------------------------------
338  // For each load module, dump metrics and object code instructions
339  // --------------------------------------------------------
340  for (Prof::Flat::ProfileData::const_iterator it = prof.begin();
341  it != prof.end(); ++it) {
342  const Prof::Flat::LM* proflm = it->second;
343 
344  // 1. Open and read the load module
345  BinUtil::LM* lm = new BinUtil::LM();
346  try {
347  lm->open(proflm->name().c_str());
348 
349  std::set<std::string> dir; // empty set of measurement directories
350  lm->read(dir, BinUtil::LM::ReadFlg_ALL);
351  }
352  catch (...) {
353  DIAG_EMsg("While reading " << proflm->name());
354  throw;
355  }
356 
357  correlateWithObject_LM(metricMgr, *proflm, *lm,
358  os, srcCode, procPruneGlobs, procPruneThreshold);
359  delete lm;
360  }
361 }
362 
363 
364 void
366  const Prof::Flat::LM& proflm,
367  const BinUtil::LM& lm,
368  // ----------------------------------------------
369  ostream& os,
370  bool srcCode,
371  const std::vector<std::string>& procPruneGlobs,
372  uint64_t procPruneThreshold)
373 {
374  // INVARIANT: metricMgr only contains metrics related to 'proflm'
375 
376  MetricCursor metricCursor(metricMgr, proflm, lm);
377  ColumnFormatter colFmt(metricMgr, os, 2, 0);
378 
379  bool hasProcGlobs = !procPruneGlobs.empty();
380 
381  // --------------------------------------------------------
382  // 0. Metric summary for load module
383  // --------------------------------------------------------
384 
385  os << std::setfill('=') << std::setw(77) << "=" << std::endl
386  << "Load module: " << proflm.name() << std::endl
387  << std::setfill('-') << std::setw(77) << "-" << std::endl;
388 
389  const vector<uint64_t>& metricTots = metricCursor.metricTots();
390 
391  os << std::endl;
392  colFmt.genColHeaderSummary();
393  os << std::endl
394  << "Metric summary for load module (totals):\n"
395  << " ";
396  writeMetricVals(colFmt, metricTots, metricTots,
397  ColumnFormatter::Flag_ForceVal);
398 
399  // --------------------------------------------------------
400  // 1. For each procedure in the load module
401  // --------------------------------------------------------
402 
403  for (BinUtil::LM::ProcMap::const_iterator it = lm.procs().begin();
404  it != lm.procs().end(); ++it) {
405  const BinUtil::Proc* p = it->second;
406 
407  // obtain name (and prune if necessary)
408  string bestName = BinUtil::canonicalizeProcName(p->name());
409  if (hasProcGlobs && !FileUtil::fnmatch(procPruneGlobs, bestName.c_str())) {
410  continue;
411  }
412 
413  BinUtil::Insn* endInsn = p->endInsn();
414  VMAInterval procint(p->begVMA(), p->endVMA() + endInsn->size());
415 
416  // obtain counts (and prune if necessary)
417  const vector<uint64_t> metricTotsProc =
418  metricCursor.computeMetricVals(procint, false);
419  if (!metricCursor.hasMetricValGE(metricTotsProc, procPruneThreshold)) {
420  continue;
421  }
422 
423  // --------------------------------------------------------
424  // Metric summary for procedure
425  // --------------------------------------------------------
426 
427  os << std::endl << std::endl
428  << "Procedure: " << p->name() << " (" << bestName << ")\n"
429  << std::setfill('-') << std::setw(60) << "-" << std::endl;
430 
431  os << std::endl;
432  colFmt.genColHeaderSummary();
433  os << std::endl
434  << "Metric summary for procedure (percents relative to load module):\n"
435  << " ";
436  writeMetricVals(colFmt, metricTotsProc, metricTots,
437  ColumnFormatter::Flag_ForceVal);
438  os << std::endl << " ";
439  writeMetricVals(colFmt, metricTotsProc, metricTots,
440  ColumnFormatter::Flag_ForcePct);
441  os << std::endl;
442 
443  // --------------------------------------------------------
444  // Metric summary for instructions
445  // --------------------------------------------------------
446  os << std::endl
447  << "Metric details for procedure (percents relative to procedure):\n";
448 
449  string the_file;
450  SrcFile::ln the_line = SrcFile::ln_NULL;
451 
452  for (BinUtil::ProcInsnIterator it1(*p); it1.isValid(); ++it1) {
453  BinUtil::Insn* insn = it1.current();
454  VMA vma = insn->vma();
455  VMA opVMA = BinUtil::LM::isa->convertVMAToOpVMA(vma, insn->opIndex());
456 
457  // 1. Collect metric annotations
458  const vector<uint64_t>& metricValVMA =
459  metricCursor.computeMetricForVMA(opVMA);
460 
461  // 2. Print source line information (if necessary)
462  if (srcCode) {
463  string func, file;
464  SrcFile::ln line;
465  p->findSrcCodeInfo(vma, insn->opIndex(), func, file, line);
466 
467  if (file != the_file || line != the_line) {
468  the_file = file;
469  the_line = line;
470  os << the_file << ":" << the_line << std::endl;
471  }
472  }
473 
474  // 3. Print annotated instruction
475  os << std::hex << opVMA << std::dec << ": ";
476 
477  if (metricCursor.hasNonZeroMetricVal(metricValVMA)) {
478  writeMetricVals(colFmt, metricValVMA, metricTotsProc);
479  }
480  else {
481  colFmt.genBlankCols();
482  }
483 
484  insn->decode(os);
485  os << std::endl;
486  }
487  }
488 
489  os << std::endl << std::endl;
490 }
491 
492 
493 static void
495  const vector<uint64_t>& metricVal,
496  const vector<uint64_t>& metricTot,
497  ColumnFormatter::Flag flg)
498 {
499  for (uint i = 0; i < metricVal.size(); ++i) {
500  colFmt.genCol(i, (double)metricVal[i], (double)metricTot[i], flg);
501  }
502 }
503 
504 
505 } // namespace Flat
506 
507 } // namespace Analysis
ProcMap & procs()
Definition: LM.hpp:273
const vector< uint64_t > & computeMetricForVMA(VMA vma)
virtual VMA convertVMAToOpVMA(VMA vma, ushort GCC_ATTR_UNUSED opIndex) const
Definition: ISA.hpp:471
void genCol(uint mid, double metricVal, double metricTot, Flag flg=Flag_NULL)
Definition: TextUtil.cpp:183
const EventData & event(uint i) const
const vector< uint64_t > & metricValAtVMA() const
static bool hasMetricValGE(const vector< uint64_t > &metricVal, uint64_t val)
unsigned int ln
Definition: SrcFile.hpp:66
uint64_t load_addr() const
MetricCursor(const Prof::Metric::Mgr &metricMgr, const Prof::Flat::LM &proflm, const BinUtil::LM &lm)
string canonicalizeProcName(const std::string &name, ProcNameMgr *procNameMgr)
Definition: BinUtils.cpp:69
bfd_vma VMA
Definition: ISATypes.hpp:79
VMA begVMA() const
Definition: Proc.hpp:148
const vector< const Prof::Flat::EventData * > & metricDescs() const
uint64_t toUInt64(const char *str, unsigned *endidx)
Definition: StrUtil.cpp:189
#define DIAG_EMsg(...)
Definition: diagnostics.h:251
const std::string & name() const
Definition: Proc.hpp:122
bool isValid() const
Definition: Proc.hpp:397
bool doUnrelocate(VMA loadAddr) const
Definition: LM.hpp:227
const std::string & profileRelId() const
bool fnmatch(const std::vector< std::string > &patternVec, const char *string, int flags)
Definition: FileUtil.cpp:147
virtual void read(const std::set< std::string > &directorySet, ReadFlg readflg)
Definition: LM.cpp:460
VMA beg() const
void openread(const char *filename=NULL)
virtual ushort opIndex() const =0
bool findSrcCodeInfo(VMA vma, ushort opIndex, std::string &func, std::string &file, SrcFile::ln &line) const
Definition: Proc.hpp:242
virtual void decode(std::ostream &os)
Definition: Insn.hpp:183
std::pair< VMA, bucketsz_t > Datum
const vector< uint64_t > & metricTots() const
uint size() const
Definition: Metric-Mgr.hpp:153
static void correlateWithObject_LM(const Prof::Metric::Mgr &metricMgr, const Prof::Flat::LM &proflm, const BinUtil::LM &lm, std::ostream &os, bool srcCode, const std::vector< std::string > &procPruneGlobs, uint64_t procPruneThreshold)
void correlateWithObject(const Prof::Metric::Mgr &metricMgr, std::ostream &os, bool srcCode, const std::vector< std::string > &procPruneGlobs, uint64_t procPruneThreshold)
const vector< uint64_t > & computeMetricVals(const VMAInterval vmaint, bool advanceIndices)
const StringToADescVecMap & fnameToFMetricMap() const
Definition: Metric-Mgr.hpp:217
unsigned int uint
Definition: uint.h:124
vector< const Prof::Flat::EventData * > m_metricDescs
virtual ushort size() const =0
VMA end() const
My_t::const_iterator const_iterator
VMA endVMA() const
Definition: Proc.hpp:152
const char * DIAG_UnexpectedInput
static bool hasNonZeroMetricVal(const vector< uint64_t > &metricVal)
Insn * endInsn() const
Definition: Proc.cpp:109
const std::string & name() const
VMA vma() const
Definition: Insn.hpp:125
const Datum & datum(uint i) const
Metric::ADesc * metric(uint i)
Definition: Metric-Mgr.hpp:131
static ISA * isa
Definition: LM.hpp:493
static void writeMetricVals(ColumnFormatter &colFmt, const vector< uint64_t > &metricVal, const vector< uint64_t > &metricTot, ColumnFormatter::Flag flg=ColumnFormatter::Flag_NULL)
const ln ln_NULL
Definition: SrcFile.hpp:67
virtual void open(const char *filenm)
Definition: LM.cpp:395