HPCToolkit
Flat-SrcCorrelation.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 //************************ System Include Files ******************************
48 
49 #include <iostream>
50 using std::hex;
51 using std::dec;
52 using std::endl;
53 
54 #include <string>
55 using std::string;
56 
57 #include <map>
58 using std::map;
59 
60 #include <vector>
61 using std::vector;
62 
63 #include <climits>
64 
65 //************************* User Include Files *******************************
66 
67 #include <include/gcc-attr.h>
68 #include <include/uint.h>
69 
70 #include "Flat-SrcCorrelation.hpp"
71 #include "TextUtil.hpp"
72 #include "Util.hpp"
73 
75 
76 #include <lib/prof/Struct-Tree.hpp>
78 
79 #include <lib/binutils/LM.hpp>
80 
81 #include <lib/xml/xml.hpp>
82 using namespace xml;
83 
85 #include <lib/support/Trace.hpp>
86 #include <lib/support/FileUtil.hpp>
87 #include <lib/support/IOUtil.hpp>
88 #include <lib/support/StrUtil.hpp>
89 
90 //************************ Forward Declarations ******************************
91 
92 //****************************************************************************
93 
94 namespace Analysis {
95 
96 namespace Flat {
97 
98 uint Driver::profileBatchSz = 16; // UINT_MAX;
99 
100 
101 Driver::Driver(const Analysis::Args& args,
102  Prof::Metric::Mgr& mMgr, Prof::Struct::Tree& structure)
103  : Unique(), m_args(args), m_mMgr(mMgr), m_structure(structure)
104 {
105 }
106 
107 
109 {
110 }
111 
112 
113 int
115 {
116  if (m_mMgr.empty()) {
117  return 0;
118  }
119 
120  //-------------------------------------------------------
121  // 1. Initialize static program structure
122  //-------------------------------------------------------
123  DIAG_Msg(2, "Initializing structure...");
125 
126  DIAG_If(3) {
127  DIAG_Msg(3, "Initial structure:");
128  write_experiment(DIAG_CERR);
129  }
130 
131  //-------------------------------------------------------
132  // 2. Correlate metrics with program structure
133  // (Results in a pruned structure tree)
134  //-------------------------------------------------------
135  DIAG_Msg(2, "Creating and correlating metrics with program structure: ...");
137 
138  DIAG_If(3) {
139  DIAG_Msg(3, "Final structure:");
140  write_experiment(DIAG_CERR);
141  }
142 
143  //-------------------------------------------------------
144  // 3. Generate Experiment database
145  //-------------------------------------------------------
146  string db_dir = m_args.db_dir; // make copy
147  bool db_use = !db_dir.empty() && db_dir != "-";
148  if (db_use) {
149  std::pair<string, bool> ret = FileUtil::mkdirUnique(db_dir.c_str());
150  db_dir = ret.first; // exits on failure...
151  }
152 
153  if (db_use && m_args.db_copySrcFiles) {
154  DIAG_Msg(1, "Copying source files reached by PATH/REPLACE options to " << db_dir);
155  // NOTE: makes file names in m_structure relative to database
157  db_dir);
158  }
159 
160  const string out_path = (db_use) ? (db_dir + "/") : "";
161 
162  if (!m_args.out_db_experiment.empty()) {
163  const string& fnm = m_args.out_db_experiment;
164  DIAG_Msg(1, "Writing final scope tree (in XML) to " << fnm);
165  string fpath = out_path + fnm;
166  const char* osnm = (fnm == "-") ? NULL : fpath.c_str();
167  std::ostream* os = IOUtil::OpenOStream(osnm);
168  write_experiment(*os);
170  }
171 
172  if (!m_args.out_db_csv.empty()) {
173  const string& fnm = m_args.out_db_csv;
174  DIAG_Msg(1, "Writing final scope tree (in CSV) to " << fnm);
175  string fpath = out_path + fnm;
176  const char* osnm = (fnm == "-") ? NULL : fpath.c_str();
177  std::ostream* os = IOUtil::OpenOStream(osnm);
178  write_csv(*os);
180  }
181 
182  if (!m_args.out_txt.empty()) {
183  const string& fnm = m_args.out_txt;
184  string fpath = out_path + fnm;
185  const char* osnm = (fnm == "-") ? NULL : fpath.c_str();
186  std::ostream* os = IOUtil::OpenOStream(osnm);
187  write_txt(*os);
189  }
190 
191  // configuration file
192  if (!m_args.out_db_config.empty()) {
193  const string& fnm = m_args.out_db_config;
194  string fpath = out_path + fnm;
195  DIAG_Msg(1, "Writing configuration file to " << fpath);
196 
197  const char* osnm = (fnm == "-") ? NULL : fpath.c_str();
198  std::ostream* os = IOUtil::OpenOStream(osnm);
199  write_config(*os);
201  }
202 
203  return 0;
204 }
205 
206 
207 string
208 Driver::replacePath(const char* oldpath)
209 {
210  // FIXME: Use PathReplacementMgr!
211 
212  DIAG_Assert(m_args.replaceInPath.size() == m_args.replaceOutPath.size(), "");
213  for (uint i = 0 ; i < m_args.replaceInPath.size() ; i++ ) {
214  uint length = m_args.replaceInPath[i].length();
215  // it makes sense to test for matching only if 'oldpath' is strictly longer
216  // than this replacement inPath.
217  if (strlen(oldpath) > length &&
218  strncmp(oldpath, m_args.replaceInPath[i].c_str(), length) == 0 ) {
219  // it's a match
220  string s = m_args.replaceOutPath[i] + &oldpath[length];
221  DIAG_Msg(3, "replacePath: Found a match! New path: " << s);
222  return s;
223  }
224  }
225  // If nothing matched, return the original path
226  DIAG_Msg(3, "replacePath: Nothing matched! Init path: " << oldpath);
227  return string(oldpath);
228 }
229 
230 
231 void
232 Driver::write_experiment(std::ostream &os) const
233 {
234  static const char* experimentDTD =
236 
237  os << "<?xml version=\"1.0\"?>" << std::endl;
238  os << "<!DOCTYPE HPCToolkitExperiment [\n" << experimentDTD << "]>"
239  << std::endl;
240  os << "<HPCToolkitExperiment version=\"2.0\">\n";
241  os << "<Header n" << MakeAttrStr(m_args.title) << ">\n";
242  os << " <Info/>\n";
243  os << "</Header>\n";
244 
245  os << "<SecFlatProfile i=\"0\" n" << MakeAttrStr(m_args.title) << ">\n";
246 
247  // ------------------------------------------------------------
248  //
249  // ------------------------------------------------------------
250  os << "<SecHeader>\n";
251 
252  os << " <MetricTable>\n";
253  for (uint i = 0; i < m_mMgr.size(); ++i) {
254  const Prof::Metric::ADesc* m = m_mMgr.metric(i);
255 
256  os << " <Metric i" << MakeAttrNum(i)
257  << " n" << MakeAttrStr(m->name())
258  << " v=\"" << m->toValueTyStringXML() << "\""
259  << " t=\"" << Prof::Metric::ADesc::ADescTyToXMLString(m->type()) << "\""
260  << " show=\"" << ((m->isVisible()) ? "1" : "0") << "\">\n";
261  os << " <Info>"
262  << "<NV n=\"units\" v=\"events\"/>" // or "samples" m->isUnitsEvents()
263  << "<NV n=\"percent\" v=\"" << ((m->doDispPercent()) ? "1" : "0") << "\"/>"
264  << "</Info>\n";
265  os << " </Metric>\n";
266  }
267  os << " </MetricTable>\n";
268 
269  os << " <Info n=\"SearchPaths\">\n";
270  const Analysis::PathTupleVec& searchPaths = m_args.searchPathTpls;
271  for (uint i = 0; i < searchPaths.size(); i++) {
272  const string& path = searchPaths[i].first;
273  os << " <NV n" << MakeAttrNum(i) << " v" << MakeAttrStr(path) << "/>\n";
274  }
275  os << " </Info>\n";
276 
277  os << "</SecHeader>\n";
278  os.flush();
279 
280  // ------------------------------------------------------------
281  //
282  // ------------------------------------------------------------
283  int wFlgs = 0; // Prof::Struct::Tree::WFlg_LeafMetricsOnly;
284 
285  os << "<SecFlatProfileData>\n";
286  m_structure.root()->writeXML(os, wFlgs);
287  os << "</SecFlatProfileData>\n";
288 
289  os << "</SecFlatProfile>\n";
290  os << "</HPCToolkitExperiment>\n";
291  os.flush();
292 }
293 
294 
295 void
296 Driver::write_csv(std::ostream &os) const
297 {
298  os << "File name,Routine name,Start line,End line,Loop level";
299  for (uint i = 0; i < m_mMgr.size(); ++i) {
300  const Prof::Metric::ADesc* m = m_mMgr.metric(i);
301  os << "," << m->name();
302  if (m->doDispPercent()) {
303  os << "," << m->name() << " (%)";
304  }
305  }
306  os << endl;
307 
308  // Dump SCOPETREE
310 }
311 
312 
313 void
314 Driver::write_txt(std::ostream &os) const
315 {
318  using namespace Prof;
319 
320  //write_experiment(os);
321 
322  Metric::ADesc* m_sortby = m_mMgr.findSortKey();
323  DIAG_Assert(m_sortby, "INVARIANT: at least on sort-by metric must exist");
324 
325  Struct::Root* rootStrct = m_structure.root();
326 
327  ColumnFormatter colFmt(m_mMgr, os, 2, 0);
328 
329  os << std::setfill('=') << std::setw(77) << "=" << std::endl;
330  colFmt.genColHeaderSummary();
331  os << std::endl;
332 
334  string nm = "Program summary (row 1: sample count for raw metrics): "
335  + rootStrct->name();
336  write_txt_secSummary(os, colFmt, nm, NULL);
337  }
338 
340  string nm = "Load module summary:";
341  write_txt_secSummary(os, colFmt, nm,
342  &ANodeTyFilter[Struct::ANode::TyLM]);
343  }
344 
346  string nm = "File summary:";
347  write_txt_secSummary(os, colFmt, nm,
348  &ANodeTyFilter[Struct::ANode::TyFile]);
349  }
350 
352  string nm = "Procedure summary:";
353  write_txt_secSummary(os, colFmt, nm,
354  &ANodeTyFilter[Struct::ANode::TyProc]);
355  }
356 
358  string nm = "Loop summary (dependent on structure information):";
359  write_txt_secSummary(os, colFmt, nm,
360  &ANodeTyFilter[Struct::ANode::TyLoop]);
361  }
362 
364  string nm = "Statement summary:";
365  write_txt_secSummary(os, colFmt, nm,
366  &ANodeTyFilter[Struct::ANode::TyStmt]);
367  }
368 
370  const std::vector<std::string>& fnmGlobs = m_args.txt_srcFileGlobs;
371  bool hasFnmGlobs = !fnmGlobs.empty();
372 
374  it(m_structure.root(), &ANodeTyFilter[Struct::ANode::TyFile]);
375  for (Struct::ANode* strct = NULL; (strct = it.current()); it++) {
376  Struct::File* fileStrct = dynamic_cast<Struct::File*>(strct);
377  const string& fnm = fileStrct->name();
378  if (fnm != Struct::Tree::UnknownFileNm
379  && (!hasFnmGlobs || FileUtil::fnmatch(fnmGlobs, fnm.c_str()))) {
380  write_txt_annotateFile(os, colFmt, fileStrct);
381  }
382  }
383  }
384 }
385 
386 
387 void
390  const std::string& title,
391  const Prof::Struct::ANodeFilter* filter) const
392 {
394  using namespace Prof;
395 
396  write_txt_hdr(os, title);
397 
398  Struct::Root* rootStrct = m_structure.root();
399  Metric::ADesc* m_sortby = m_mMgr.findSortKey();
400 
401  if (!filter) {
402  // Program *sample* summary
403  for (uint i = 0; i < m_mMgr.size(); ++i) {
404  const Metric::ADesc* m = m_mMgr.metric(i);
405  const Metric::SampledDesc* mm =
406  dynamic_cast<const Metric::SampledDesc*>(m);
407  if (mm) {
408  double smpl = rootStrct->metric(i) / (double)mm->period();
409  colFmt.genCol(i, smpl);
410  }
411  else {
412  colFmt.genBlankCol(i);
413  }
414  }
415  os << std::endl;
416 
417  // Program metric summary
418  for (uint i = 0; i < m_mMgr.size(); ++i) {
419  colFmt.genCol(i, rootStrct->metric(i));
420  }
421  os << std::endl;
422  }
423  else {
424  Struct::ANodeSortedIterator it(rootStrct, Struct::ANodeSortedIterator::cmpByMetric(m_sortby->id()), filter, false/*leavesOnly*/);
425  for (; it.current(); it++) {
426  Struct::ANode* strct = it.current();
427  for (uint i = 0; i < m_mMgr.size(); ++i) {
428  colFmt.genCol(i, strct->metric(i), rootStrct->metric(i));
429  }
430  os << " " << strct->nameQual() << std::endl;
431  }
432  }
433  os << std::endl;
434 }
435 
436 
437 void
440  const Prof::Struct::File* fileStrct) const
441 {
442  const string& fnm = fileStrct->name();
443  const string& fnm_qual = fileStrct->nameQual();
444 
445  string title = "Annotated file (statement/line level): " + fnm_qual;
446  write_txt_hdr(os, title);
447 
448  std::istream* is = NULL;
449  try {
450  is = IOUtil::OpenIStream(fnm.c_str());
451  }
452  catch (const Diagnostics::Exception& /*ex*/) {
453  os << " Cannot open.\n" << std::endl;
454  return;
455  }
456 
457  //-------------------------------------------------------
458  //
459  //-------------------------------------------------------
460 
461  Prof::Struct::Root* rootStrct = m_structure.root();
462  const uint linew = 5;
463  string linetxt;
464  SrcFile::ln ln_file = 1; // line number *after* next getline
465 
467  it(fileStrct,
470  for (Prof::Struct::ANode* node = NULL; (node = it.current()); it++) {
471  Prof::Struct::ACodeNode* strct =
472  dynamic_cast<Prof::Struct::ACodeNode*>(node); // always true
473  SrcFile::ln ln_metric = strct->begLine();
474 
475  // Advance ln_file to just before ln_metric, if necessary
476  while (ln_file < ln_metric && is->good()) {
477  std::getline(*is, linetxt);
478  os << std::setw(linew) << std::setfill(' ') << ln_file;
479  colFmt.genBlankCols();
480  os << " " << linetxt << std::endl;
481  ln_file++;
482  }
483 
484  // INVARIANT: isValid(ln_metric) ==> ln_metric == ln_file
485  //DIAG_Assert(Logic::implies(SrcFile::isValid(ln_metric), ln_metric == ln_file, DIAG_UnexpectedInput);
486 
487  // Generate columns for ln_metric
488  os << std::setw(linew) << std::setfill(' ') << ln_metric;
489  for (uint i = 0; i < m_mMgr.size(); ++i) {
490  colFmt.genCol(i, strct->metric(i), rootStrct->metric(i));
491  }
492 
493  // Generate source file line for ln_metric, if necessary
494  if (SrcFile::isValid(ln_metric)) {
495  std::getline(*is, linetxt);
496  os << " " << linetxt;
497  ln_file++;
498  }
499  os << std::endl;
500  }
501 
502  // Finish generating file, if necessary
503  for ( ; is->good(); ln_file++) {
504  std::getline(*is, linetxt);
505  os << std::setw(linew) << std::setfill(' ') << ln_file;
506  colFmt.genBlankCols();
507  os << " " << linetxt << std::endl;
508  }
509 
510  //-------------------------------------------------------
511  //
512  //-------------------------------------------------------
513  os << std::endl;
515 }
516 
517 
518 void
519 Driver::write_txt_hdr(std::ostream& os, const std::string& hdr) const
520 {
521  os << std::setfill('=') << std::setw(77) << "=" << std::endl
522  << hdr << std::endl
523  << std::setfill('-') << std::setw(77) << "-" << std::endl;
524 }
525 
526 
527 void
528 Driver::write_config(std::ostream &os) const
529 {
530  os << "<HPCPROF>\n\n";
531 
532  // title
533  os << "<TITLE name=\"" << m_args.title << "\"/>\n\n";
534 
535  // search paths
536  for (uint i = 0; i < m_args.searchPathTpls.size(); ++i) {
538  os << "<PATH name=\"" << x.first << "\" viewname=\"" << x.second <<"\"/>\n";
539  }
540  if (!m_args.searchPathTpls.empty()) { os << "\n"; }
541 
542  // structure files
543  for (uint i = 0; i < m_args.structureFiles.size(); ++i) {
544  os << "<STRUCTURE name=\"" << m_args.structureFiles[i] << "\"/>\n";
545  }
546  if (!m_args.structureFiles.empty()) { os << "\n"; }
547 
548  // group files
549  for (uint i = 0; i < m_args.groupFiles.size(); ++i) {
550  os << "<STRUCTURE name=\"" << m_args.groupFiles[i] << "\"/>\n";
551  }
552  if (!m_args.groupFiles.empty()) { os << "\n"; }
553 
554  // metrics
555  for (uint i = 0; i < m_mMgr.size(); i++) {
556  using namespace Prof;
557  const Metric::ADesc* m = m_mMgr.metric(i);
558  const Metric::SampledDesc* mm = dynamic_cast<const Metric::SampledDesc*>(m);
559  if (mm) {
560  const char* sortbystr = ((i == 0) ? " sortBy=\"true\"" : "");
561  os << "<METRIC name=\"" << m->name()
562  << "\" displayName=\"" << m->name() << "\""
563  << sortbystr << ">\n";
564  os << " <FILE name=\"" << mm->profileName()
565  << "\" select=\"" << mm->profileRelId()
566  << "\" type=\"" << mm->profileType() << "\"/>\n";
567  os << "</METRIC>\n\n";
568  }
569  }
570  if (!m_mMgr.empty()) { os << "\n"; }
571 
572  os << "</HPCPROF>\n";
573 }
574 
575 
576 string
578 {
579  string s = string("Driver: " )
580  + "title=" + m_args.title + " " // + "path=" + path;
581  + "\nm_metrics::\n"
582  + m_mMgr.toString();
583  return s;
584 }
585 
586 
587 void
589 {
590  std::cerr << toString() << std::endl;
591 }
592 
593 
594 } // namespace Flat
595 
596 } // namespace Analysis
597 
598 
599 //****************************************************************************
600 
601 namespace Analysis {
602 
603 namespace Flat {
604 
605 
606 void
608 {
609  DriverDocHandlerArgs docargs(this);
610 
611  //-------------------------------------------------------
612  // if Structure has been provided, use it to initialize the
613  // structure of the scope tree
614  //-------------------------------------------------------
616  PGMDocHandler::Doc_STRUCT, docargs);
617 
618  //-------------------------------------------------------
619  // FIXME: OBSOLETE
620  // if a PGM/Group document has been provided, use it to form the
621  // group partitions (as wall as initialize/extend the scope tree)
622  //-------------------------------------------------------
624  PGMDocHandler::Doc_GROUP, docargs);
625 }
626 
627 
628 void
630  Prof::Struct::Tree& structure)
631 {
632  computeRawMetrics(mMgr, structure);
633 
634  // NOTE: Pruning the structure tree now (as opposed to after
635  // computing derived metrics) can significantly speed up the
636  // computation of derived metrics. Technically, this may not be
637  // correct, since a derived metric could simply add a constant to
638  // every value of a raw metric, potentially creating 'unprunable'
639  // nodes from those that would otherwise be prunable. However, any
640  // sane computed metric will not have this property.
641  structure.root()->pruneByMetrics();
642 
643  computeDerivedMetrics(mMgr, structure);
644 }
645 
646 
647 //----------------------------------------------------------------------------
648 
649 void
651 {
652  StringToBoolMap hasStructureTbl;
653 
654  const Prof::Metric::Mgr::StringToADescVecMap& fnameToFMetricMap =
655  mMgr.fnameToFMetricMap();
656 
657  //-------------------------------------------------------
658  // Insert performance data into scope tree leaves. Batch several
659  // profile files to one load module to amortize the overhead of
660  // reading symbol tables and debugging information.
661  //-------------------------------------------------------
662  Prof::Metric::Mgr::StringToADescVecMap::const_iterator it =
663  fnameToFMetricMap.begin();
664 
665  ProfToMetricsTupleVec batchJob;
666  while (getNextRawBatch(batchJob, it, fnameToFMetricMap.end())) {
667 
668  //-------------------------------------------------------
669  // FIXME: Assume that each profile file has an idential epoch.
670  // This will have to change when true dlopen support is available.
671  //-------------------------------------------------------
672 
673  string prev_lmname_orig;
674 
675  // For each load module: process the batch job. A batch job
676  // process a group of profile files (and their associated metrics)
677  // by load module.
678  Prof::Flat::ProfileData* prof = batchJob[0].first;
679  for (Prof::Flat::ProfileData::const_iterator it1 = prof->begin();
680  it1 != prof->end(); ++it1) {
681 
682  const string lmname_orig = it1->first;
683  if (lmname_orig == prev_lmname_orig) {
684  // Skip multiple entries for same LM. This is sufficient
685  // b/c iteration proceeds in sorted fashion.
686  continue;
687  }
688  prev_lmname_orig = lmname_orig;
689 
690  const string lmname = replacePath(lmname_orig);
691 
692  bool useStruct = hasStructure(lmname, structure, hasStructureTbl);
693  computeRawBatchJob_LM(lmname, lmname_orig, structure, batchJob, useStruct);
694  }
695 
696  clearRawBatch(batchJob);
697  }
698 
699  //-------------------------------------------------------
700  // Accumulate leaves to interior nodes, if necessary
701  //-------------------------------------------------------
702 
704  // 1. Compute batch jobs: all raw metrics are independent of each
705  // other and therefore may be computed en masse.
706  VMAIntervalSet ivalset; // cheat using a VMAInterval set
707 
708  for (uint i = 0; i < mMgr.size(); i++) {
709  Prof::Metric::ADesc* m = mMgr.metric(i);
711  dynamic_cast<Prof::Metric::SampledDesc*>(m);
712  if (mm) {
713  ivalset.insert(VMAInterval(m->id(), m->id() + 1)); // [ )
716  }
717  }
718 
719  // 2. Now execute the batch jobs
720  for (VMAIntervalSet::iterator it1 = ivalset.begin();
721  it1 != ivalset.end(); ++it1) {
722  const VMAInterval& ival = *it1;
723  structure.root()->aggregateMetrics((uint)ival.beg(), (uint)ival.end());
724  }
725  }
726 }
727 
728 
729 void
730 Driver::computeRawBatchJob_LM(const string& lmname, const string& lmname_orig,
731  Prof::Struct::Tree& structure,
732  ProfToMetricsTupleVec& profToMetricsVec,
733  bool useStruct)
734 {
735  BinUtil::LM* lm = openLM(lmname);
736  if (!lm) {
737  return;
738  }
739 
740  if (!useStruct) {
741  std::set<std::string> dir; // empty set of measurement directories
742  lm->read(dir, BinUtil::LM::ReadFlg_Seg);
743  }
744 
745  Prof::Struct::LM* lmStrct =
746  Prof::Struct::LM::demand(structure.root(), lmname);
747 
748  for (uint i = 0; i < profToMetricsVec.size(); ++i) {
749 
750  Prof::Flat::ProfileData* prof = profToMetricsVec[i].first;
751  Prof::Metric::ADescVec* metrics = profToMetricsVec[i].second;
752 
753 
755  std::pair<ProfileData::iterator, ProfileData::iterator> fnd =
756  prof->equal_range(lmname_orig);
757  if (fnd.first == prof->end()) {
758  DIAG_WMsg(1, "Cannot find LM " << lmname_orig << " within "
759  << prof->name() << ".");
760  continue;
761  }
762 
763  //-------------------------------------------------------
764  // For each Prof::Flat::LM that matches lmname_orig
765  //-------------------------------------------------------
766  for (ProfileData::iterator it = fnd.first; it != fnd.second; ++it) {
767  Prof::Flat::LM* proflm = it->second;
768 
769  //-------------------------------------------------------
770  // For each metric, insert performance data into scope tree
771  //-------------------------------------------------------
772  using namespace Prof;
773  for (Metric::ADescVec::iterator it1 = metrics->begin();
774  it1 != metrics->end(); ++it1) {
775  Metric::SampledDesc* m = dynamic_cast<Metric::SampledDesc*>(*it1);
776  DIAG_Assert(m->isUnitsEvents(), "Assume metric's units is events!");
777  uint mIdx = (uint)StrUtil::toUInt64(m->profileRelId());
778  const Prof::Flat::EventData& profevent = proflm->event(mIdx);
779  if (!m->period()) {
780  // N.B.: 'period' is missing when metric's provenance is config file
781  m->period(profevent.mdesc().period());
782  }
783 
784  correlateRaw(m, profevent, proflm->load_addr(),
785  structure, lmStrct, lm, useStruct);
786  }
787  }
788  }
789 
790  delete lm;
791 }
792 
793 
794 // With structure information (an object code to source structure
795 // map), correlation is by VMA. Otherwise correlation is performed
796 // using file, function and line debugging information.
797 void
799  const Prof::Flat::EventData& profevent,
800  VMA lm_load_addr,
802  Prof::Struct::LM* lmStrct,
803  /*const*/ BinUtil::LM* lm,
804  bool useStruct)
805 {
806  ulong period = profevent.mdesc().period();
807  bool doUnrelocate = lm->doUnrelocate(lm_load_addr);
808 
809  uint numMetrics = m_mMgr.size();
810 
811  for (uint i = 0; i < profevent.num_data(); ++i) {
812  const Prof::Flat::Datum& dat = profevent.datum(i);
813  VMA vma = dat.first; // relocated VMA
814  uint32_t samples = dat.second;
815  double events = samples * (double)period; // samples * (events/sample)
816 
817  // 1. Unrelocate vma.
818  VMA vma_ur = (doUnrelocate) ? (vma - lm_load_addr) : vma;
819 
820  // 2. Find associated scope and insert into scope tree
821  Prof::Struct::ANode* strct =
822  Util::demandStructure(vma_ur, lmStrct, lm, useStruct);
823 
824  strct->demandMetric(metric->id(), numMetrics/*size*/) += events;
825  DIAG_DevMsg(6, "Metric associate: "
826  << metric->name() << ":0x" << hex << vma_ur << dec
827  << " --> +" << events << "="
828  << strct->metric(metric->id()) << " :: " << strct->toXML());
829  }
830 }
831 
832 
833 
834 // A batch is a vector of [Prof::Flat::Profile, <metric-vector>] pairs
835 bool
837  Prof::Metric::Mgr::StringToADescVecMap::const_iterator& it,
838  const Prof::Metric::Mgr::StringToADescVecMap::const_iterator& it_end)
839 {
840  for (uint i = 0; i < profileBatchSz; ++i) {
841  if (it != it_end) {
842  const string& fnm = it->first;
844  const_cast<Prof::Metric::ADescVec&>(it->second);
845  Prof::Flat::ProfileData* prof = readProf(fnm);
846  batchJob.push_back(make_pair(prof, &metrics));
847  it++;
848  }
849  else {
850  break;
851  }
852  }
853 
854  bool haswork = !batchJob.empty();
855  return haswork;
856 }
857 
858 
859 void
861 {
862  for (uint i = 0; i < batchJob.size(); ++i) {
863  ProfToMetricsTuple& tup = batchJob[i];
864  delete tup.first;
865  }
866  batchJob.clear();
867 }
868 
869 
870 bool
871 Driver::hasStructure(const string& lmname, Prof::Struct::Tree& structure,
872  StringToBoolMap& hasStructureTbl)
873 {
874  // hasStructure's test depdends on the *initial* structure information
875  StringToBoolMap::iterator it = hasStructureTbl.find(lmname);
876  if (it != hasStructureTbl.end()) {
877  return it->second; // memoized answer
878  }
879  else {
880  Prof::Struct::LM* lmStrct =
881  Prof::Struct::LM::demand(structure.root(), lmname);
882  bool hasStruct = (!lmStrct->isLeaf());
883  hasStructureTbl.insert(make_pair(lmname, hasStruct));
884  if (!hasStruct && !m_args.structureFiles.empty()) {
885  DIAG_WMsg(2, "No STRUCTURE for " << lmname << ".");
886  }
887  return hasStruct;
888  }
889 }
890 
891 
892 //----------------------------------------------------------------------------
893 
894 void
896  Prof::Struct::Tree& structure)
897 {
898  using namespace Prof;
899 
900  // INVARIANT: All raw metrics have interior (and leaf) values before
901  // derived metrics are computed.
902 
903  // 1. Compute batch jobs: a derived metric with id 'x' only depends
904  // on metrics with id's strictly less than 'x'.
905  VMAIntervalSet ivalset; // cheat using a VMAInterval set
906  const Metric::AExpr** mExprVec = new const Metric::AExpr*[mMgr.size()];
907 
908  for (uint i = 0; i < mMgr.size(); i++) {
909  Metric::ADesc* m = mMgr.metric(i);
910  Metric::DerivedDesc* mm = dynamic_cast<Metric::DerivedDesc*>(m);
911  if (mm) {
912  ivalset.insert(VMAInterval(m->id(), m->id() + 1)); // [ )
913  mExprVec[i] = mm->expr();
916  }
917  }
918 
919  // 2. Now execute the batch jobs
920  for (VMAIntervalSet::iterator it = ivalset.begin();
921  it != ivalset.end(); ++it) {
922  const VMAInterval& ival = *it;
923  computeDerivedBatch(structure, mExprVec,
924  (uint)ival.beg(), (uint)ival.end());
925  }
926 
927  delete[] mExprVec;
928 }
929 
930 
931 void
933  const Prof::Metric::AExpr** mExprVec,
934  uint mBegId, uint mEndId)
935 {
936  // N.B. pre-order walk assumes point-wise metrics
937  // Cf. Prof::CCT::ANode::computeMetrics() && computeMetricsIncr().
938 
939  Prof::Struct::Root* strct = structure.root();
940  uint numMetrics = m_mMgr.size();
941 
942  for (Prof::Struct::ANodeIterator it(strct); it.Current(); it++) {
943  for (uint mId = mBegId; mId < mEndId; ++mId) {
944  const Prof::Metric::AExpr* expr = mExprVec[mId];
945  if (expr) {
946  double val = expr->eval(*it.current());
947  // if (!Prof::Metric::AExpr::isok(val)) ...
948  it.current()->demandMetric(mId, numMetrics/*size*/) = val;
949  }
950  }
951  }
952 }
953 
954 
955 
956 //----------------------------------------------------------------------------
957 
959 Driver::readProf(const string& fnm)
960 {
961  Prof::Flat::ProfileData* prof = new Prof::Flat::ProfileData(fnm.c_str());
962  readProf(prof);
963  return prof;
964 }
965 
966 
967 void
969 {
970  try {
971  prof->openread();
972  }
973  catch (...) {
974  DIAG_EMsg("While reading '" << prof->name() << "'");
975  throw;
976  }
977 }
978 
979 
981 Driver::openLM(const string& fnm)
982 {
983  BinUtil::LM* lm = NULL;
984  try {
985  lm = new BinUtil::LM();
986  lm->open(fnm.c_str());
987  }
988  catch (const BinUtil::Exception& x) {
989  DIAG_EMsg("While opening " << fnm.c_str() << ":\n" << x.message());
990  }
991  catch (...) {
992  DIAG_EMsg("Exception encountered while opening " << fnm.c_str());
993  }
994  return lm;
995 }
996 
997 
998 } // namespace Flat
999 
1000 } // namespace Analysis
1001 
1002 //****************************************************************************
const std::string & profileName() const
void write_txt(std::ostream &os) const
std::vector< std::string > groupFiles
Definition: Args.hpp:131
Metric::AExpr * expr() const
void write_txt_hdr(std::ostream &os, const std::string &hdr) const
void CloseStream(std::istream *s)
Definition: IOUtil.cpp:127
PathTupleVec searchPathTpls
Definition: Args.hpp:125
std::string db_dir
Definition: Args.hpp:199
std::string replacePath(const char *path)
static struct perf_mem_metric metric
Definition: pmu_x86.c:114
void genCol(uint mid, double metricVal, double metricTot, Flag flg=Flag_NULL)
Definition: TextUtil.cpp:183
const EventData & event(uint i) const
std::vector< ProfToMetricsTuple > ProfToMetricsTupleVec
Prof::Flat::ProfileData * readProf(const string &fnm)
unsigned int ln
Definition: SrcFile.hpp:66
uint64_t load_addr() const
#define DIAG_If(level)
Definition: diagnostics.h:134
std::istream * OpenIStream(const char *filenm)
Definition: IOUtil.cpp:85
bfd_vma VMA
Definition: ISATypes.hpp:79
bool isVisible() const
My_t::iterator iterator
bool hasDerived() const
Definition: Metric-Mgr.cpp:532
uint64_t toUInt64(const char *str, unsigned *endidx)
Definition: StrUtil.cpp:189
#define DIAG_EMsg(...)
Definition: diagnostics.h:251
void write_txt_secSummary(std::ostream &os, Analysis::TextUtil::ColumnFormatter &colFmt, const std::string &title, const Prof::Struct::ANodeFilter *filter) const
Prof::Metric::Mgr & m_mMgr
static const char * ADescTyToXMLString(ADescTy type)
void computeRawMetrics(Prof::Metric::Mgr &mMgr, Prof::Struct::Tree &structure)
bool doUnrelocate(VMA loadAddr) const
Definition: LM.hpp:227
bool txt_srcAnnotation
Definition: Args.hpp:233
std::vector< std::string > structureFiles
Definition: Args.hpp:128
const std::string & profileRelId() const
void write_experiment(std::ostream &os) const
void computeRawBatchJob_LM(const string &lmname, const string &lmname_orig, Prof::Struct::Tree &structure, ProfToMetricsTupleVec &profToMetricsVec, bool useStruct)
std::vector< ADesc * > ADescVec
Metric::ADesc * findSortKey() const
Definition: Metric-Mgr.cpp:487
void write_csv(std::ostream &os) const
bool isValid(SrcFile::ln line)
Definition: SrcFile.hpp:70
virtual const std::string & name() 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
BinUtil::LM * openLM(const string &fnm)
bool profflat_computeFinalMetricValues
Definition: Args.hpp:182
double metric(size_t mId) const
void correlateMetricsWithStructure(Prof::Metric::Mgr &mMgr, Prof::Struct::Tree &structure)
cct_node_t * node
Definition: cct.c:128
std::string name() const
bool hasStructure(const string &lmname, Prof::Struct::Tree &structure, StringToBoolMap &hasStructureTbl)
VMA beg() const
bool empty() const
Definition: Metric-Mgr.hpp:157
bool getNextRawBatch(ProfToMetricsTupleVec &batchJob, Prof::Metric::Mgr::StringToADescVecMap::const_iterator &it, const Prof::Metric::Mgr::StringToADescVecMap::const_iterator &it_end)
void openread(const char *filename=NULL)
virtual std::ostream & writeXML(std::ostream &os=std::cout, uint oFlags=0, const char *pre="") const
bool doDispPercent() const
unsigned long int ulong
Definition: uint.h:128
virtual const std::string & name() const
const ANodeFilter ANodeTyFilter[ANode::TyNUMBER]
const Analysis::Args & m_args
std::pair< VMA, bucketsz_t > Datum
Root * root() const
virtual std::string toXML(uint oFlags=0) const
std::ostream * OpenOStream(const char *filenm)
Definition: IOUtil.cpp:106
std::string MakeAttrStr(const char *x, int flags=ESC_TRUE)
Definition: xml.hpp:216
std::string out_db_experiment
Definition: Args.hpp:196
uint size() const
Definition: Metric-Mgr.hpp:153
void copySourceFiles(Prof::Struct::Root *structure, const Analysis::PathTupleVec &pathVec, const string &dstDir)
Definition: Util.cpp:377
Definition: xml.cpp:127
virtual std::string nameQual() const
const std::string & name() const
const StringToADescVecMap & fnameToFMetricMap() const
Definition: Metric-Mgr.hpp:217
std::string toString(const char *pfx="") const
Definition: Metric-Mgr.cpp:735
unsigned int uint
Definition: uint.h:124
void computeDerivedBatch(Prof::Struct::Tree &structure, const Prof::Metric::AExpr **mExprVec, uint mBegId, uint mEndId)
Prof::Struct::Tree & m_structure
virtual std::string toValueTyStringXML() const
const Metric::SampledDesc & mdesc() const
SrcFile::ln begLine() const
std::pair< Prof::Flat::ProfileData *, Prof::Metric::ADescVec * > ProfToMetricsTuple
ComputedTy computedType() const
Prof::Struct::ACodeNode * demandStructure(VMA vma, Prof::Struct::LM *lmStrct, BinUtil::LM *lm, bool useStruct, const string *unknownProcNm)
Definition: Util.cpp:317
std::map< std::string, Metric::ADescVec > StringToADescVecMap
Definition: Metric-Mgr.hpp:81
void write_txt_annotateFile(std::ostream &os, Analysis::TextUtil::ColumnFormatter &colFmt, const Prof::Struct::File *fileStrct) const
std::vector< std::string > replaceInPath
Definition: Args.hpp:134
std::string out_txt
Definition: Args.hpp:213
std::map< string, bool > StringToBoolMap
virtual double eval(const Metric::IData &mdata) const =0
virtual std::string nameQual() const
std::string out_db_config
Definition: Args.hpp:202
std::vector< PathTuple > PathTupleVec
Definition: Args.hpp:83
VMA end() const
static int cmpByLine(const void *x, const void *y)
std::pair< string, bool > mkdirUnique(const char *dirnm)
Definition: FileUtil.cpp:364
void aggregateMetrics(uint mBegId, uint mEndId)
std::pair< iterator, bool > insert(const VMA beg, const VMA end)
#define DIAG_DevMsg(level,...)
Definition: diagnostics.h:246
ADescTy type() const
void populateStructure(Prof::Struct::Tree &structure)
#define DIAG_Msg(level,...)
Definition: diagnostics.h:241
static LM * demand(Root *pgm, const std::string &lm_fnm)
double demandMetric(size_t mId, size_t size=0) const
void correlateRaw(Prof::Metric::ADesc *metric, const Prof::Flat::EventData &profevent, VMA lm_load_addr, Prof::Struct::Tree &structure, Prof::Struct::LM *lmStrct, BinUtil::LM *lm, bool useStruct)
const Datum & datum(uint i) const
#define NULL
Definition: ElfHelper.cpp:85
std::string title
Definition: Args.hpp:121
int metrics[MAX_EVENTS][MAX_METRICS]
Definition: generic.c:147
std::string MakeAttrNum(int x)
Definition: xml.hpp:228
virtual std::string message() const
Definition: LM.hpp:660
void write_config(std::ostream &os=std::cout) const
std::vector< std::string > replaceOutPath
Definition: Args.hpp:135
Metric::ADesc * metric(uint i)
Definition: Metric-Mgr.hpp:131
void computeDerivedMetrics(Prof::Metric::Mgr &mMgr, Prof::Struct::Tree &structure)
virtual NonUniformDegreeTreeNode * Current() const
bool db_copySrcFiles
Definition: Args.hpp:200
const std::string & profileType() const
void clearRawBatch(ProfToMetricsTupleVec &batchJob)
#define GCC_ATTR_UNUSED
Definition: gcc-attr.h:80
int txt_summary
Definition: Args.hpp:231
std::string toString() const
const ANodeFilter ANodeTyFilter[ANode::TyNUMBER]
std::pair< std::string, std::string > PathTuple
Definition: Args.hpp:82
std::vector< std::string > txt_srcFileGlobs
Definition: Args.hpp:234
void CSV_TreeDump(std::ostream &os=std::cout) const
void readStructure(Struct::Tree &structure, const std::vector< string > &structureFiles, PGMDocHandler::Doc_t docty, DocHandlerArgs &docargs)
Definition: PGMReader.cpp:133
static long period
Definition: itimer.c:194
virtual void open(const char *filenm)
Definition: LM.cpp:395
std::string out_db_csv
Definition: Args.hpp:197