HPCToolkit
CallPath.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::hex;
64 using std::dec;
65 
66 #include <fstream>
67 
68 #include <string>
69 using std::string;
70 
71 #include <climits>
72 #include <cstring>
73 
74 #include <typeinfo>
75 
76 #include <sys/stat.h>
77 
78 //*************************** User Include Files ****************************
79 
80 #include <include/uint.h>
81 #include <include/gcc-attr.h>
82 
83 #include "CallPath.hpp"
85 #include "Util.hpp"
86 
87 #include <lib/prof/CCT-Tree.hpp>
88 #include <lib/prof/Metric-Mgr.hpp>
90 
93 
95 
96 #include <lib/binutils/LM.hpp>
98 
99 #include <lib/xml/xml.hpp>
100 using namespace xml;
101 
102 #include <lib/support/diagnostics.h>
103 #include <lib/support/Logic.hpp>
104 #include <lib/support/IOUtil.hpp>
105 #include <lib/support/StrUtil.hpp>
106 
107 
108 
109 //********************************** Macros **********************************
110 
111 #define DEBUG_COALESCING 0
112 
113 
114 
115 //*************************** Forward Declarations ***************************
116 
117 std::ostream* Analysis::CallPath::dbgOs = NULL; // for parallel debugging
118 
119 
120 
121 //****************************************************************************
122 //
123 //****************************************************************************
124 
125 static void
127 
128 
129 static bool
130 vdso_loadmodule(const char *pathname)
131 {
132  return pathname && strstr(pathname, "vdso");
133 }
134 
135 
136 namespace Analysis {
137 
138 namespace CallPath {
139 
140 
142 read(const Util::StringVec& profileFiles, const Util::UIntVec* groupMap,
143  int mergeTy, uint rFlags, uint mrgFlags)
144 {
145  // Special case
146  if (profileFiles.empty()) {
148  return prof;
149  }
150 
151  // General case
152  uint groupId = (groupMap) ? (*groupMap)[0] : 0;
153  Prof::CallPath::Profile* prof = read(profileFiles[0], groupId, rFlags);
154 
155  // add the directory into the set of directories
156  prof->addDirectory(profileFiles[0]);
157 
158  for (uint i = 1; i < profileFiles.size(); ++i) {
159  groupId = (groupMap) ? (*groupMap)[i] : 0;
160  Prof::CallPath::Profile* p = read(profileFiles[i], groupId, rFlags);
161  prof->merge(*p, mergeTy, mrgFlags);
162 
164  delete p;
165 
166  // add the directory into the set of directories
167  prof->addDirectory(profileFiles[i]);
168  }
169  prof->metricMgr()->mergePerfEventStatistics_finalize(profileFiles.size());
170 
171  return prof;
172 }
173 
174 
176 read(const char* prof_fnm, uint groupId, uint rFlags)
177 {
178  // -------------------------------------------------------
179  //
180  // -------------------------------------------------------
181 
183  try {
184  DIAG_MsgIf(0, "Reading: '" << prof_fnm << "'");
185  prof = Prof::CallPath::Profile::make(prof_fnm, rFlags, /*outfs*/ NULL);
186  }
187  catch (...) {
188  DIAG_EMsg("While reading profile '" << prof_fnm << "'...");
189  throw;
190  }
191 
192  // -------------------------------------------------------
193  // Potentially update the profile's metrics
194  // -------------------------------------------------------
195 
196  if (groupId > 0) {
197  Prof::Metric::Mgr* metricMgr = prof->metricMgr();
198  for (uint i = 0; i < metricMgr->size(); ++i) {
199  Prof::Metric::ADesc* m = metricMgr->metric(i);
200  m->namePfx(StrUtil::toStr(groupId));
201  }
202  metricMgr->recomputeMaps();
203  }
204 
205  return prof;
206 }
207 
208 
209 void
211 {
213 
215  PGMDocHandler::Doc_STRUCT, docargs);
216 
217  // BAnal::Struct::makeStructure() creates a Struct::Tree that
218  // distinguishes between non-call-site statements and call site
219  // statements mapping to the same line.
220  //
221  // To maintain the Non-Overlapping Principle with respect to the
222  // Struct::Tree, we used to coalesce non-call-site statements and
223  // call site statements mapping to the same source line. However,
224  // this is problematic on two counts.
225  //
226  // First, it is somewhat pointless unless (1)
227  // Analysis::Util::demandStructure() enforces the Non-Overlapping
228  // Principle; and (2) overlayStaticStructureMain(), in addition to
229  // creating frames, merges nodes (Stmts and Calls) that map to the
230  // same structure.
231  //
232  // Second, for constructing hpcviewer's Callers view, we need
233  // static-structure ids to maintain call site distinctions, even if
234  // several call sites map to the same line.
235  //
236  // (Cf. Analysis::CallPath::noteStaticStructureOnLeaves() and
237  // Prof::CCT::ADynNode::isMergable().)
238  if (0) {
239  coalesceStmts(*structure);
240  }
241 }
242 
243 
244 } // namespace CallPath
245 
246 } // namespace Analysis
247 
248 
249 //****************************************************************************
250 
251 
252 static void
254 
255 
256 static void
258 {
259  coalesceStmts(structure.root());
260 }
261 
262 
263 // coalesceStmts: Maintain Non-Overlapping Principle of source code
264 // for static struture. Structure information currently distinguishes
265 // non-callsite statements from callsite statements, even if they are
266 // within the same scope and on the same source line.
267 void
269 {
270  typedef std::map<SrcFile::ln, Prof::Struct::Stmt*> LineToStmtMap;
271 
272  if (!node) {
273  return;
274  }
275 
276  // A <line> -> <stmt> is sufficient for statements within the same scope
277  LineToStmtMap stmtMap;
278 
279  // ---------------------------------------------------
280  // For each immediate child of this node...
281  //
282  // Use cmpById()-ordering so that results are deterministic
283  // (cf. hpcprof-mpi)
284  // ---------------------------------------------------
286  it.current(); /* */) {
287  Prof::Struct::ANode* n = it.current();
288  it++; // advance iterator -- it is pointing at 'n'
289 
290  if ( n->isLeaf() && (typeid(*n) == typeid(Prof::Struct::Stmt)) ) {
291  // Test for duplicate source line info.
292  Prof::Struct::Stmt* n_stmt = static_cast<Prof::Struct::Stmt*>(n);
293  SrcFile::ln line = n_stmt->begLine();
294  LineToStmtMap::iterator it_stmt = stmtMap.find(line);
295  if (it_stmt != stmtMap.end()) {
296  // found -- we have a duplicate
297  Prof::Struct::Stmt* n_stmtOrig = (*it_stmt).second;
298  DIAG_MsgIf(0, "coalesceStmts: deleting " << n_stmt->toStringMe());
299  Prof::Struct::ANode::merge(n_stmtOrig, n_stmt); // deletes n_stmt
300  }
301  else {
302  // no entry found -- add
303  stmtMap.insert(std::make_pair(line, n_stmt));
304  }
305  }
306  else if (!n->isLeaf()) {
307  // Recur
308  coalesceStmts(n);
309  }
310  }
311 }
312 
313 
314 //****************************************************************************
315 // Overlaying static structure on a CCT
316 //****************************************************************************
317 
318 typedef std::map<Prof::Struct::ANode*, Prof::CCT::ANode*> StructToCCTMap;
319 
320 static void
322  Prof::LoadMap::LM* loadmap_lm,
323  Prof::Struct::LM* lmStrct, BinUtil::LM* lm);
324 
325 static Prof::CCT::ANode*
327  StructToCCTMap& strctToCCTMap);
328 
329 static Prof::CCT::ProcFrm*
331  StructToCCTMap& strctToCCTMap);
332 
333 static void
335  Prof::Struct::ACodeNode* node_strct,
336  StructToCCTMap& strctToCCTMap);
337 
338 static void
340 
341 
342 //****************************************************************************
343 
344 
345 void
348  string agent, bool doNormalizeTy,
349  bool printProgress)
350 {
351  const Prof::LoadMap* loadmap = prof.loadmap();
352  Prof::Struct::Root* rootStrct = prof.structure()->root();
353 
354  std::string errors;
355 
356  // -------------------------------------------------------
357  // Overlay static structure. N.B. To process spurious samples,
358  // iteration includes LoadMap::LMId_NULL
359  // -------------------------------------------------------
361  i <= loadmap->size(); ++i) {
362  Prof::LoadMap::LM* lm = loadmap->lm(i);
363  if (lm->isUsed()) {
364  try {
365  const string& lm_nm = lm->name();
366 
367  Prof::Struct::LM* lmStrct = Prof::Struct::LM::demand(rootStrct, lm_nm);
369  printProgress);
370  }
371  catch (const Diagnostics::Exception& x) {
372  errors += " " + x.what() + "\n";
373  }
374  }
375  }
376 
377  if (!errors.empty()) {
378  DIAG_WMsgIf(1, "Cannot fully process samples because of errors reading load modules:\n" << errors);
379  }
380 
381 
382  // -------------------------------------------------------
383  // Basic normalization
384  // -------------------------------------------------------
385  if (doNormalizeTy) {
386  coalesceStmts(prof);
387  }
388 
389  applyThreadMetricAgents(prof, agent);
390 }
391 
392 
393 void
396  Prof::LoadMap::LM* loadmap_lm,
397  Prof::Struct::LM* lmStrct,
398  bool printProgress)
399 {
400  const string& lm_nm = loadmap_lm->name();
401  BinUtil::LM* lm = NULL;
402 
403  bool useStruct = (lmStrct->childCount() > 0);
404 
405  if (useStruct) {
406  DIAG_MsgIf(printProgress, "STRUCTURE: " << lm_nm);
407  } else if (loadmap_lm->id() == Prof::LoadMap::LMId_NULL) {
408  // no-op for this case
409  } else if (vdso_loadmodule(lm_nm.c_str())) {
410  DIAG_WMsgIf(printProgress, "Cannot fully process samples for virtual load module " << lm_nm);
411  } else {
412 
413  try {
414  lm = new BinUtil::LM();
415  lm->open(lm_nm.c_str());
417  }
418  catch (const Diagnostics::Exception& x) {
419  delete lm;
420  lm = NULL;
421  DIAG_WMsgIf(printProgress, "Cannot fully process samples for load module " <<
422  lm_nm << ": " << x.what());
423  }
424  if (lm) DIAG_MsgIf(printProgress, "Line map : " << lm_nm);
425  }
426 
427  if (lm) {
428  lmStrct->pretty_name(lm->name().c_str());
429  }
430  Analysis::CallPath::overlayStaticStructure(prof, loadmap_lm, lmStrct, lm);
431 
432  // account for new structure inserted by BAnal::Struct::makeStructureSimple()
433  lmStrct->computeVMAMaps();
434 
435  delete lm;
436 }
437 
438 
439 // overlayStaticStructure: Create frames for CCT::Call and CCT::Stmt
440 // nodes using a preorder walk over the CCT.
441 void
444  Prof::LoadMap::LM* loadmap_lm,
445  Prof::Struct::LM* lmStrct, BinUtil::LM* lm)
446 {
447  overlayStaticStructure(prof.cct()->root(), loadmap_lm, lmStrct, lm);
448 }
449 
450 
451 
452 void
455 {
456  const Prof::Struct::Root* rootStrct = prof.structure()->root();
457 
458  Prof::CCT::ANodeIterator it(prof.cct()->root(), NULL/*filter*/,
459  true/*leavesOnly*/, IteratorStack::PreOrder);
460  for (Prof::CCT::ANode* n = NULL; (n = it.current()); ++it) {
461  Prof::CCT::ADynNode* n_dyn = dynamic_cast<Prof::CCT::ADynNode*>(n);
462  if (n_dyn) {
463  Prof::LoadMap::LMId_t lmId = n_dyn->lmId(); // ok if LoadMap::LMId_NULL
464  Prof::LoadMap::LM* loadmap_lm = prof.loadmap()->lm(lmId);
465  const string& lm_nm = loadmap_lm->name();
466 
467  const Prof::Struct::LM* lmStrct = rootStrct->findLM(lm_nm);
468  DIAG_Assert(lmStrct, "failed to find Struct::LM: " << lm_nm);
469 
470  VMA lm_ip = n_dyn->lmIP();
471  const Prof::Struct::ACodeNode* strct = lmStrct->findByVMA(lm_ip);
472 
473  // Laks: I don't think an empty strct is critical. We can just send a warning
474  // and then continue. (like the serial version of hpcprof)
475  if (!strct) {
476  DIAG_EMsg("Analysis::CallPath::noteStaticStructureOnLeaves: failed to find structure for: "
478  continue;
479  }
480 
481  n->structure(strct);
482  }
483  }
484 }
485 
486 
487 //****************************************************************************
488 
489 static void
491  Prof::LoadMap::LM* loadmap_lm,
492  Prof::Struct::LM* lmStrct, BinUtil::LM* lm)
493 {
494  // INVARIANT: The parent of 'node' has been fully processed
495  // w.r.t. the given load module and lives within a correctly located
496  // procedure frame.
497 
498  if (!node) { return; }
499 
500  bool useStruct = (!lm);
501 
502  // N.B.: dynamically allocate to better handle the deep recursion
503  // required for very deep CCTs.
504  StructToCCTMap* strctToCCTMap = new StructToCCTMap;
505 
506  if (0 && Analysis::CallPath::dbgOs) {
507  (*Analysis::CallPath::dbgOs) << "overlayStaticStructure: node (";
508  Prof::CCT::ADynNode* node_dyn = dynamic_cast<Prof::CCT::ADynNode*>(node);
509  if (node_dyn) {
510  (*Analysis::CallPath::dbgOs) << node_dyn->lmId() << ", " << hex << node_dyn->lmIP() << dec;
511  }
512  (*Analysis::CallPath::dbgOs) << "): " << node->toStringMe() << std::endl;
513  }
514 
515  // ---------------------------------------------------
516  // For each immediate child of this node...
517  //
518  // Use cmpByDynInfo()-ordering so that results are deterministic
519  // (cf. hpcprof-mpi)
520  // ---------------------------------------------------
522  it.current(); /* */) {
523  Prof::CCT::ANode* n = it.current();
524  it++; // advance iterator -- it is pointing at 'n'
525 
526  // ---------------------------------------------------
527  // process Prof::CCT::ADynNode nodes
528  //
529  // N.B.: Since we process w.r.t. one load module at a time, we may
530  // see non-ADynNode nodes!
531  // ---------------------------------------------------
532  Prof::CCT::ADynNode* n_dyn = dynamic_cast<Prof::CCT::ADynNode*>(n);
533  if (n_dyn && (n_dyn->lmId() == loadmap_lm->id())) {
534  using namespace Prof;
535 
536  const string* unkProcNm = &Prof::Struct::Tree::UnknownProcNm;
537  if (n_dyn->isSecondarySynthRoot()) {
538  unkProcNm = &Struct::Tree::PartialUnwindProcNm;
539 
540  } else if (n_dyn->hpcrun_node_type() == NODE_TYPE_GLOBAL_VARIABLE) {
541  // datacentric: case for global variable, if the address of the variable
542  // is not recognized, we need to label it as "<unknown variable> instead of
543  // <unknown procedure>
544  unkProcNm = &Struct::Tree::UnknownGlobalVariable;
545  }
546 
547  // 1. Add symbolic information to 'n_dyn'
548  VMA lm_ip = n_dyn->lmIP();
549  Struct::ACodeNode* strct =
550  Analysis::Util::demandStructure(lm_ip, lmStrct, lm, useStruct,
551  unkProcNm);
552 
553  n->structure(strct);
554  //strct->demandMetric(CallPath::Profile::StructMetricIdFlg) += 1.0;
555 
556  DIAG_MsgIf(0, "overlayStaticStructure: dyn (" << n_dyn->lmId() << ", " << hex << lm_ip << ") --> struct " << strct << dec << " " << strct->toStringMe());
557  if (0 && Analysis::CallPath::dbgOs) {
558  (*Analysis::CallPath::dbgOs) << "dyn (" << n_dyn->lmId() << ", " << hex << lm_ip << dec << ") --> struct " << strct->toStringMe() << std::endl;
559  }
560 
561  // 2. Demand a procedure frame for 'n_dyn' and its scope within it
562  Struct::ANode* scope_strct = strct->ancestor(Struct::ANode::TyLoop,
563  Struct::ANode::TyAlien,
564  Struct::ANode::TyProc);
565  //scope_strct->demandMetric(CallPath::Profile::StructMetricIdFlg) += 1.0;
566 
567  Prof::CCT::ANode* scope_frame =
568  demandScopeInFrame(n_dyn, scope_strct, *strctToCCTMap);
569 
570  // 3. Link 'n' to its parent
571  n->unlink();
572  n->link(scope_frame);
573  }
574 
575  // ---------------------------------------------------
576  // recur
577  // ---------------------------------------------------
578  if (!n->isLeaf()) {
579  overlayStaticStructure(n, loadmap_lm, lmStrct, lm);
580  }
581  }
582 
583  delete strctToCCTMap;
584 }
585 
586 
587 // demandScopeInFrame: Return the scope in the CCT frame that
588 // corresponds to 'strct'. Creates a procedure frame and adds
589 // structure to it, if necessary.
590 //
591 // INVARIANT: symbolic information has been added to 'node'.
592 static Prof::CCT::ANode*
594  Prof::Struct::ANode* strct,
595  StructToCCTMap& strctToCCTMap)
596 {
597  Prof::CCT::ANode* frameScope = NULL;
598 
599  StructToCCTMap::iterator it = strctToCCTMap.find(strct);
600  if (it != strctToCCTMap.end()) {
601  frameScope = (*it).second;
602  }
603  else {
604  Prof::Struct::Proc* procStrct = strct->ancestorProc();
605  makeFrame(node, procStrct, strctToCCTMap);
606 
607  it = strctToCCTMap.find(strct);
608  DIAG_Assert(it != strctToCCTMap.end(), "");
609  frameScope = (*it).second;
610  }
611 
612  return frameScope;
613 }
614 
615 
616 // makeFrame: Create a CCT::ProcFrm 'frame' corresponding to 'procStrct'
617 // - make 'frame' a sibling of 'node'
618 // - populate 'strctToCCTMap' with the frame's static structure
619 static Prof::CCT::ProcFrm*
621  StructToCCTMap& strctToCCTMap)
622 {
623  Prof::CCT::ProcFrm* frame = new Prof::CCT::ProcFrm(NULL, procStrct);
624  frame->link(node->parent());
625 
626  // OK, this is very tricky ... quite a hack
627  // for any artificial "root", its frame scope becomes the "root", while the
628  // "statement" becomes a regular node
629  // This happens because the viewer will combine the frame procedure and
630  // the statement, with the frame procedure as the outer node.
631  // By switching the root type to the frame procedure, the viewer will know
632  // that it has to separate the root into different view
633  //
634  // Also, in the computation of inclusive metric (in CCT-Tree.cpp)
635  // we don't aggregate the metrics of "artificial root" into the "invisible root"
636 
637  uint16_t hpcrun_type = node->hpcrun_node_type();
638  frame->hpcrun_node_type(hpcrun_type);
640 
641  // making pair between the struct and the frame
642 
643  strctToCCTMap.insert(std::make_pair(procStrct, frame));
644 
645  makeFrameStructure(frame, procStrct, strctToCCTMap);
646 
647  return frame;
648 }
649 
650 
651 // makeFrameStructure: Given a procedure frame 'frame' and its
652 // associated procedure structure 'procStrct', mirror procStrct's loop
653 // and alien structure within 'frame'. Populate 'strctToCCTMap'.
654 //
655 // NOTE: this *eagerly* adds structure to a frame that may later be
656 // pruned by pruneTrivialNodes(). We could be a little smarter, but on
657 // another day.
658 static void
660  Prof::Struct::ACodeNode* node_strct,
661  StructToCCTMap& strctToCCTMap)
662 {
663  for (Prof::Struct::ACodeNodeChildIterator it(node_strct);
664  it.Current(); ++it) {
665  Prof::Struct::ACodeNode* n_strct = it.current();
666 
667  // Done: if we reach the natural base case or embedded procedure
668  if (n_strct->isLeaf() || typeid(*n_strct) == typeid(Prof::Struct::Proc)) {
669  continue;
670  }
671 
672  // Create n_frame, the frame node corresponding to n_strct
673  Prof::CCT::ANode* n_frame = NULL;
674  if (typeid(*n_strct) == typeid(Prof::Struct::Loop)) {
675  n_frame = new Prof::CCT::Loop(node_frame, n_strct);
676  }
677  else if (typeid(*n_strct) == typeid(Prof::Struct::Alien)) {
678  n_frame = new Prof::CCT::Proc(node_frame, n_strct);
679  }
680 
681  if (n_frame) {
682  strctToCCTMap.insert(std::make_pair(n_strct, n_frame));
683  DIAG_DevMsgIf(0, "makeFrameStructure: " << hex << " [" << n_strct << " -> " << n_frame << "]" << dec);
684 
685  // Recur
686  makeFrameStructure(n_frame, n_strct, strctToCCTMap);
687  }
688  }
689 }
690 
691 
692 //***************************************************************************
693 
694 static void
696 
697 static void
699 {
700  coalesceStmts(prof.cct()->root());
701 }
702 
703 
704 // coalesceStmts: After static structure has been overlayed,
705 // CCT::Stmt's live within a procedure frame (alien or native).
706 // However, leaf nodes (CCT::Stmt) are still distinct according to
707 // instruction pointer. Group CCT::Stmts within the same scope by
708 // line (or structure).
709 void
711 {
712  typedef std::map<SrcFile::ln, Prof::CCT::Stmt*> LineToStmtMap;
713 
714  if (!node) {
715  return;
716  }
717 
718  // A <line> -> <stmt> is sufficient because procedure frames
719  // identify a unique load module and source file.
720  //
721  // N.B.: dynamically allocate to better handle the deep recursion
722  // required for very deep CCTs.
723  LineToStmtMap* stmtMap = new LineToStmtMap;
724 
725  // ---------------------------------------------------
726  // For each immediate child of this node...
727  //
728  // cmpByDynInfo()-ordering should be good enough
729  // ---------------------------------------------------
731  it.current(); /* */) {
732  Prof::CCT::ANode* n = it.current();
733  it++; // advance iterator -- it is pointing at 'n'
734 
735  if ( n->isLeaf() && (typeid(*n) == typeid(Prof::CCT::Stmt)) ) {
736  // Test for duplicate source line info.
737  Prof::CCT::Stmt* n_stmt = static_cast<Prof::CCT::Stmt*>(n);
738  SrcFile::ln line = n_stmt->begLine();
739  LineToStmtMap::iterator it_stmt = stmtMap->find(line);
740  if (it_stmt != stmtMap->end()) {
741  // found -- we have a duplicate
742  Prof::CCT::Stmt* n_stmtOrig = (*it_stmt).second;
743 
744  DIAG_MsgIf(DEBUG_COALESCING, "Coalescing:\n"
745  << "\tx: "
746  << n_stmtOrig->toStringMe(Prof::CCT::Tree::OFlg_Debug)
747  << "\n\ty: "
749 
750  // N.B.: Because (a) trace records contain a function's
751  // representative IP and (b) two traces that contain samples
752  // from the same function should have their conflict resolved
753  // in Prof::CallPath::Profile::merge(), we would expect that
754  // merge effects are impossible. That is, we expect that it
755  // is impossible that a CCT::ProcFrm has multiple CCT::Stmts
756  // with distinct trace ids.
757  //
758  // However, merge effects are possible *after* static
759  // structure is added to the CCT. The reason is that multiple
760  // object-level procedures can map to one source-level
761  // procedure (e.g., multiple template instantiations mapping
762  // to the same source template or multiple stripped functions
763  // mapping to UnknownProcNm).
764  if (! Prof::CCT::ADynNode::hasMergeEffects(*n_stmtOrig, *n_stmt)) {
765  Prof::CCT::MergeEffect effct = n_stmtOrig->mergeMe(*n_stmt, /*MergeContext=*/ NULL,/*metricBegIdx=*/ 0, /*mayConflict=*/ false);
766  DIAG_Assert(effct.isNoop(), "Analysis::CallPath::coalesceStmts: trace ids lost (" << effct.toString() << ") when merging y into x:\n"
767  << "\tx: " << n_stmtOrig->toStringMe(Prof::CCT::Tree::OFlg_Debug) << "\n"
768  << "\ty: " << n_stmt->toStringMe(Prof::CCT::Tree::OFlg_Debug));
769 
770  // remove 'n_stmt' from tree
771  n_stmt->unlink();
772  delete n_stmt; // NOTE: could clear corresponding StructMetricIdFlg
773  }
774  }
775  else {
776  // no entry found -- add
777  stmtMap->insert(std::make_pair(line, n_stmt));
778  }
779  }
780  else if (!n->isLeaf()) {
781  // Recur
782  coalesceStmts(n);
783  }
784  }
785 
786  delete stmtMap;
787 }
788 
789 
790 //***************************************************************************
791 // Normalizing the CCT
792 //***************************************************************************
793 
794 static void
796 
797 static void
799 
800 static void
802 
803 
804 void
806  uint8_t* prunedNodes)
807 {
808  VMAIntervalSet ivalset;
809 
810  const Prof::Metric::Mgr& mMgrGbl = *(prof.metricMgr());
811  for (uint mId = 0; mId < mMgrGbl.size(); ++mId) {
812  const Prof::Metric::ADesc* m = mMgrGbl.metric(mId);
813  if (m->isVisible()
815  && (m->nameBase().find("Sum") != string::npos)) {
816  ivalset.insert(VMAInterval(mId, mId + 1)); // [ )
817  }
818  }
819 
820  prof.cct()->root()->pruneByMetrics(*prof.metricMgr(), ivalset,
821  prof.cct()->root(), 0.001,
822  prunedNodes);
823 }
824 
825 
826 void
828  string agent, bool GCC_ATTR_UNUSED doNormalizeTy)
829 {
830  pruneTrivialNodes(prof);
831 
832  if (agent == "agent-cilk") {
833  mergeCilkMain(prof); // may delete CCT:ProcFrm
834  }
835 }
836 
837 
838 void
840 {
841  // -------------------------------------------------------
842  // Prune Struct::Tree based on CallPath::Profile::StructMetricIdFlg
843  //
844  // Defer this until the end so that we keep the minimal
845  // Struct::Tree. Note that this should almost certainly come after
846  // all uses of noteStaticStructureOnLeaves().
847  // -------------------------------------------------------
848 
849  noteStaticStructure(prof);
850 
851  Prof::Struct::Root* rootStrct = prof.structure()->root();
853  rootStrct->pruneByMetrics();
854 }
855 
856 
857 //***************************************************************************
858 
859 // pruneTrivialNodes:
860 //
861 // Without static structure, the CCT is sparse in the sense that
862 // *every* node must have some non-zero inclusive metric value. To
863 // see this, note that every leaf node represents a sample point;
864 // therefore all interior metric values must be greater than zero.
865 //
866 // However, when static structure is added, the CCT may contain
867 // 'spurious' static scopes in the sense that their metric values are
868 // zero. Since such scopes will not have CCT::Stmt nodes as children,
869 // we can prune them by removing empty scopes rather than computing
870 // inclusive values and pruning nodes whose metric values are all
871 // zero.
872 
873 static void
875 
876 static void
878 {
879  pruneTrivialNodes(prof.cct()->root());
880 }
881 
882 
883 static void
885 {
886  using namespace Prof;
887 
888  if (!node) { return; }
889 
890  for (CCT::ANodeChildIterator it(node); it.Current(); /* */) {
891  CCT::ANode* x = it.current();
892  it++; // advance iterator -- it is pointing at 'x'
893 
894  // 1. Recursively do any trimming for this tree's children
896 
897  // 2. Trim this node if necessary
898  if (x->isLeaf()) {
899  bool isPrunableTy = (typeid(*x) == typeid(CCT::ProcFrm) ||
900  typeid(*x) == typeid(CCT::Proc) ||
901  typeid(*x) == typeid(CCT::Loop));
902  bool isSynthetic =
903  (dynamic_cast<Prof::CCT::ADynNode*>(x)
904  && static_cast<Prof::CCT::ADynNode*>(x)->isSecondarySynthRoot());
905 
906  if (isPrunableTy || isSynthetic) {
907  x->unlink(); // unlink 'x' from tree
908  DIAG_DevMsgIf(0, "pruneTrivialNodes: " << hex << x << dec << " (sid: " << x->structureId() << ")");
909  delete x;
910  }
911  }
912  }
913 }
914 
915 
916 //***************************************************************************
917 
918 // mergeCilkMain: cilk_main is called from two distinct call sites
919 // within the runtime, resulting in an undesirable bifurcation within
920 // the CCT. The easiest way to fix this is to use a normalization
921 // step.
922 static void
924 {
925  using namespace Prof;
926 
927  CCT::ProcFrm* mainFrm = NULL;
928 
929  // 1. attempt to find 'CilkNameMgr::cilkmain'
930  for (CCT::ANodeIterator it(prof.cct()->root(),
931  &CCT::ANodeTyFilter[CCT::ANode::TyProcFrm]);
932  it.Current(); ++it) {
933  CCT::ProcFrm* x = static_cast<CCT::ProcFrm*>(it.current());
934  if (x->procName() == CilkNameMgr::cilkmain) {
935  mainFrm = x;
936  break;
937  }
938  }
939 
940  // 2. merge any sibling 'CilkNameMgr::cilkmain'
941  if (mainFrm) {
942  CCT::ANodeChildIterator it(mainFrm->parent(),
943  &CCT::ANodeTyFilter[CCT::ANode::TyProcFrm]);
944  for ( ; it.Current(); /* */) {
945  CCT::ProcFrm* x = static_cast<CCT::ProcFrm*>(it.current());
946  it++; // advance iterator -- it is pointing at 'x'
947 
948  if (x->procName() == CilkNameMgr::cilkmain) {
949  mainFrm->merge(x); // deletes 'x'
950  }
951  }
952  }
953 }
954 
955 
956 //***************************************************************************
957 
958 static void
960 {
961  using namespace Prof;
962 
963  const Prof::CCT::ANode* cct_root = prof.cct()->root();
964 
965  for (CCT::ANodeIterator it(cct_root); it.Current(); ++it) {
966  CCT::ANode* x = it.current();
967 
968  Prof::Struct::ACodeNode* strct = x->structure();
969  if (strct) {
970  strct->demandMetric(CallPath::Profile::StructMetricIdFlg) += 1.0;
971  }
972  }
973 }
974 
975 
976 //***************************************************************************
977 // Making special CCT metrics
978 //***************************************************************************
979 
980 static void
982 
983 // N.B.: Expects that thread-level metrics are available.
984 void
986  string agent)
987 {
988  makeReturnCountMetric(prof);
989 
990  if (!agent.empty()) {
991  MetricComponentsFact* metricComponentsFact = NULL;
992  if (agent == "agent-cilk") {
993  metricComponentsFact = new CilkOverheadMetricFact;
994  }
995  else if (agent == "agent-mpi") {
996  // *** applySummaryMetricAgents() ***
997  }
998  else if (agent == "agent-pthread") {
999  metricComponentsFact = new PthreadOverheadMetricFact;
1000  }
1001  else {
1002  DIAG_Die("Bad value for 'agent': " << agent);
1003  }
1004 
1005  if (metricComponentsFact) {
1006  metricComponentsFact->make(prof);
1007  delete metricComponentsFact;
1008  }
1009  }
1010 }
1011 
1012 
1013 // N.B.: Expects that summary metrics have been computed.
1014 void
1016  string agent)
1017 {
1018  if (!agent.empty()) {
1019  MetricComponentsFact* metricComponentsFact = NULL;
1020  if (agent == "agent-mpi") {
1021  metricComponentsFact = new MPIBlameShiftIdlenessFact;
1022  }
1023 
1024  if (metricComponentsFact) {
1025  metricComponentsFact->make(prof);
1026  delete metricComponentsFact;
1027  }
1028  }
1029 }
1030 
1031 
1032 //***************************************************************************
1033 
1034 // makeReturnCountMetric: A return count refers to the number of times
1035 // a given CCT node is called by its parent context. However, when
1036 // hpcrun records return counts, there is no structure (e.g. procedure
1037 // frames) in the CCT. An an example, in the CCT fragment below, the
1038 // return count [3] at 0xc means that 0xc returned to 0xbeef 3 times.
1039 // Simlarly, 0xbeef returned to its caller 5 times.
1040 //
1041 // | |
1042 // ip: 0xbeef [5] |
1043 // / | \ |
1044 // 0xa [1] 0xb [2] 0xc [3] |
1045 // | | | |
1046 //
1047 // To be able to say procedure F is called by procedure G x times
1048 // within this context, it is necessary to aggregate these counts at
1049 // the newly added procedure frames (Struct::ProcFrm).
1050 static void
1052 {
1053  std::vector<uint> retCntId;
1054 
1055  // -------------------------------------------------------
1056  // find return count metrics, if any
1057  // -------------------------------------------------------
1058  Prof::Metric::Mgr* metricMgr = prof.metricMgr();
1059  for (uint i = 0; i < metricMgr->size(); ++i) {
1060  Prof::Metric::ADesc* m = metricMgr->metric(i);
1061  if (m->nameBase().find(HPCRUN_METRIC_RetCnt) != string::npos) {
1062  retCntId.push_back(m->id());
1065  }
1066  }
1067 
1068  if (retCntId.empty()) {
1069  return;
1070  }
1071 
1072  // -------------------------------------------------------
1073  // propagate and aggregate return counts
1074  // -------------------------------------------------------
1075  Prof::CCT::ANode* cct_root = prof.cct()->root();
1076  Prof::CCT::ANodeIterator it(cct_root, NULL/*filter*/, false/*leavesOnly*/,
1078  for (Prof::CCT::ANode* n = NULL; (n = it.current()); ++it) {
1079  if (typeid(*n) != typeid(Prof::CCT::ProcFrm) && n != cct_root) {
1080  Prof::CCT::ANode* n_parent = n->parent();
1081  for (uint i = 0; i < retCntId.size(); ++i) {
1082  uint mId = retCntId[i];
1083  n_parent->demandMetric(mId) += n->demandMetric(mId);
1084  n->metric(mId) = 0.0;
1085  }
1086  }
1087  }
1088 }
1089 
1090 
1091 //****************************************************************************
1092 //
1093 //****************************************************************************
1094 
1095 namespace Analysis {
1096 
1097 namespace CallPath {
1098 
1099 static void
1100 write(Prof::CallPath::Profile& prof, std::ostream& os,
1101  const Analysis::Args& args);
1102 
1103 
1104 // makeDatabase: assumes Analysis::Args::makeDatabaseDir() has been called
1105 void
1107 {
1108  const string& db_dir = args.db_dir;
1109 
1110  DIAG_Msg(1, "Populating Experiment database: " << db_dir);
1111 
1112  // 1. Copy source files.
1113  // NOTE: makes file names in 'prof.structure' relative to database
1115  args.searchPathTpls, db_dir);
1116 
1117  // 2. Copy trace files (if necessary)
1119 
1120  // 3. Create 'experiment.xml' file
1121  string experiment_fnm = db_dir + "/" + args.out_db_experiment;
1122  std::ostream* os = IOUtil::OpenOStream(experiment_fnm.c_str());
1123 
1124  char* outBuf = new char[HPCIO_RWBufferSz];
1125 
1126  std::streambuf* os_buf = os->rdbuf();
1127  os_buf->pubsetbuf(outBuf, HPCIO_RWBufferSz);
1128 
1129  // 4. Write data for 'experiment.xml'
1130  Analysis::CallPath::write(prof, *os, args);
1131  IOUtil::CloseStream(os);
1132 
1133  delete[] outBuf;
1134 }
1135 
1136 
1137 static void
1138 write(Prof::CallPath::Profile& prof, std::ostream& os,
1139  const Analysis::Args& args)
1140 {
1141  static const char* experimentDTD =
1143 
1144  using namespace Prof;
1145 
1146  int oFlags = 0; // CCT::Tree::OFlg_LeafMetricsOnly;
1148  oFlags |= CCT::Tree::OFlg_Compressed;
1149  }
1150  DIAG_If(5) {
1151  oFlags |= CCT::Tree::OFlg_Debug;
1152  }
1153 
1154  if (args.db_addStructId) {
1155  oFlags |= CCT::Tree::OFlg_StructId;
1156  }
1157 
1158  uint metricBegId = 0;
1159  uint metricEndId = prof.metricMgr()->size();
1160 
1161  {
1162  Metric::ADesc* mBeg = prof.metricMgr()->findFirstVisible();
1163  Metric::ADesc* mEnd = prof.metricMgr()->findLastVisible();
1164  metricBegId = (mBeg) ? mBeg->id() : Metric::Mgr::npos;
1165  metricEndId = (mEnd) ? mEnd->id() + 1 : Metric::Mgr::npos;
1166  }
1167 
1168  string name = (args.title.empty()) ? prof.name() : args.title;
1169 
1170  os << "<?xml version=\"1.0\"?>\n";
1171  os << "<!DOCTYPE HPCToolkitExperiment [\n" << experimentDTD << "]>\n";
1172 
1173  os << "<HPCToolkitExperiment version=\"2.1\">\n";
1174  os << "<Header n" << MakeAttrStr(name) << ">\n";
1175  os << " <Info/>\n";
1176  os << "</Header>\n";
1177 
1178  os << "<SecCallPathProfile i=\"0\" n" << MakeAttrStr(name) << ">\n";
1179 
1180  // ------------------------------------------------------------
1181  //
1182  // ------------------------------------------------------------
1183  os << "<SecHeader>\n";
1184  prof.writeXML_hdr(os, metricBegId, metricEndId, oFlags);
1185  os << " <Info/>\n";
1186  os << "</SecHeader>\n";
1187  os.flush();
1188 
1189  // ------------------------------------------------------------
1190  //
1191  // ------------------------------------------------------------
1192  os << "<SecCallPathProfileData>\n";
1193  prof.cct()->writeXML(os, prof.metricMgr(), metricBegId, metricEndId, oFlags);
1194  os << "</SecCallPathProfileData>\n";
1195 
1196  os << "</SecCallPathProfile>\n";
1197  os << "</HPCToolkitExperiment>\n";
1198  os.flush();
1199 }
1200 
1201 } // namespace CallPath
1202 
1203 } // namespace Analysis
1204 
1205 //***************************************************************************
1206 
Struct::ACodeNode * structure() const
Definition: CCT-Tree.hpp:401
static void makeFrameStructure(Prof::CCT::ANode *node_frame, Prof::Struct::ACodeNode *node_strct, StructToCCTMap &strctToCCTMap)
Definition: CallPath.cpp:659
LM * findLM(const char *nm) const
static const std::string cilkmain
void CloseStream(std::istream *s)
Definition: IOUtil.cpp:127
ssize_t MONITOR_EXT_WRAP_NAME() write(int fd, const void *buf, size_t count)
Definition: io-over.c:189
void readStructure(Prof::Struct::Tree *structure, const Analysis::Args &args)
Definition: CallPath.cpp:210
virtual MergeEffect mergeMe(const ANode &y, MergeContext *mrgCtxt=NULL, uint metricBegIdx=0, bool mayConflict=true)
Definition: CCT-Tree.cpp:949
PathTupleVec searchPathTpls
Definition: Args.hpp:125
static void makeReturnCountMetric(Prof::CallPath::Profile &prof)
Definition: CallPath.cpp:1051
void pruneByMetrics(const Metric::Mgr &mMgr, const VMAIntervalSet &ivalset, const ANode *root, double thresholdPct, uint8_t *prunedNodes=NULL)
Definition: CCT-Tree.cpp:691
std::string db_dir
Definition: Args.hpp:199
ANode * parent() const
Definition: CCT-Tree.hpp:434
uint structureId() const
Definition: CCT-Tree.hpp:409
void applySummaryMetricAgents(Prof::CallPath::Profile &prof, string agent)
Definition: CallPath.cpp:1015
virtual std::string toStringMe(uint oFlags=0) const
Definition: CCT-Tree.cpp:1134
void normalize(Prof::CallPath::Profile &prof, string agent, bool doNormalizeTy)
unsigned int ln
Definition: SrcFile.hpp:66
#define DIAG_If(level)
Definition: diagnostics.h:134
bfd_vma VMA
Definition: ISATypes.hpp:79
bool isVisible() const
virtual NonUniformDegreeTreeNode * Current() const
#define DIAG_EMsg(...)
Definition: diagnostics.h:251
void mergePerfEventStatistics(Mgr *source)
Definition: Metric-Mgr.cpp:203
string toStr(const int x, int base)
Definition: StrUtil.cpp:243
static int cmpById(const void *x, const void *y)
virtual const std::string & what() const
Definition: Exception.hpp:126
static bool hasMergeEffects(const ADynNode &x, const ADynNode &y)
Definition: CCT-Tree.hpp:966
ANode * ancestor(ANodeTy type) const
std::vector< std::string > structureFiles
Definition: Args.hpp:128
static void coalesceStmts(Prof::Struct::Tree &structure)
Definition: CallPath.cpp:257
LM * lm(LMId_t id) const
Definition: LoadMap.hpp:230
ANode * root() const
Definition: CCT-Tree.hpp:160
void computeVMAMaps() const
virtual void make(Prof::CallPath::Profile &prof)
void overlayStaticStructureMain(Prof::CallPath::Profile &prof, string agent, bool doNormalizeTy, bool printProgress)
Definition: CallPath.cpp:347
static void overlayStaticStructure(Prof::CCT::ANode *node, Prof::LoadMap::LM *loadmap_lm, Prof::Struct::LM *lmStrct, BinUtil::LM *lm)
Definition: CallPath.cpp:490
void pruneStructTree(Prof::CallPath::Profile &prof)
Definition: CallPath.cpp:839
virtual void read(const std::set< std::string > &directorySet, ReadFlg readflg)
Definition: LM.cpp:460
int Diagnostics_GetDiagnosticFilterLevel()
Definition: diagnostics.cpp:87
cct_node_t * node
Definition: cct.c:128
const StringSet & traceFileNameSet() const
std::vector< uint > UIntVec
Definition: Util.hpp:109
static RealPathMgr & singleton()
void mergePerfEventStatistics_finalize(int num_profiles)
Definition: Metric-Mgr.cpp:222
void makeDatabase(Prof::CallPath::Profile &prof, const Analysis::Args &args)
Definition: CallPath.cpp:1106
std::ostream & writeXML_hdr(std::ostream &os, uint metricBeg, uint metricEnd, uint oFlags, const char *pfx="") const
static const std::string UnknownProcNm
virtual VMA lmIP() const
Definition: CCT-Tree.hpp:845
LMId_t id() const
Definition: LoadMap.hpp:123
bool db_addStructId
Definition: Args.hpp:205
Root * root() 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
#define DIAG_MsgIf(ifexpr,...)
Definition: diagnostics.h:236
uint size() const
Definition: Metric-Mgr.hpp:153
const std::string & name() const
Definition: LoadMap.hpp:128
void copySourceFiles(Prof::Struct::Root *structure, const Analysis::PathTupleVec &pathVec, const string &dstDir)
Definition: Util.cpp:377
static Prof::CCT::ANode * demandScopeInFrame(Prof::CCT::ADynNode *node, Prof::Struct::ANode *strct, StructToCCTMap &strctToCCTMap)
Definition: CallPath.cpp:593
Definition: xml.cpp:127
static Prof::CCT::ProcFrm * makeFrame(Prof::CCT::ADynNode *node, Prof::Struct::Proc *procStrct, StructToCCTMap &strctToCCTMap)
Definition: CallPath.cpp:620
const char * pretty_name() const
const std::string & nameBase() const
const std::string & name() const
Definition: LM.hpp:170
unsigned int uint
Definition: uint.h:124
#define DEBUG_COALESCING
Definition: CallPath.cpp:111
void copyTraceFiles(const std::string &dstDir, const std::set< string > &srcFiles)
Definition: Util.cpp:586
SrcFile::ln begLine() const
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
#define HPCRUN_METRIC_RetCnt
Definition: hpcrun-metric.h:82
void link(NonUniformDegreeTreeNode *parent)
static const LMId_t LMId_NULL
Definition: LoadMap.hpp:108
#define NODE_TYPE_GLOBAL_VARIABLE
Definition: hpcrun-fmt.h:518
Metric::ADesc * findFirstVisible() const
Definition: Metric-Mgr.cpp:502
virtual const std::string & procName() const
Definition: CCT-Tree.hpp:1086
LMId_t size() const
Definition: LoadMap.hpp:225
static int cmpByDynInfo(const void *x, const void *y)
uint merge(Profile &y, int mergeTy, uint mrgFlag=0)
const LoadMap * loadmap() const
void aggregateMetrics(uint mBegId, uint mEndId)
std::pair< iterator, bool > insert(const VMA beg, const VMA end)
std::string toString(const char *pfx="") const
Definition: CCT-Merge.cpp:121
ADescTy type() const
LoadMap::LMId_t lmId() const
Definition: CCT-Tree.hpp:823
bool isSecondarySynthRoot() const
Definition: CCT-Tree.hpp:913
static const int StructMetricIdFlg
static void pruneTrivialNodes(Prof::CallPath::Profile &prof)
Definition: CallPath.cpp:877
static void mergeCilkMain(Prof::CallPath::Profile &prof)
Definition: CallPath.cpp:923
const Metric::Mgr * metricMgr() const
std::string toStringMe(uint oFlags=0, const char *pre="") const
#define DIAG_Msg(level,...)
Definition: diagnostics.h:241
Prof::Struct::Tree * structure() const
static Profile * make(uint rFlags)
static LM * demand(Root *pgm, const std::string &lm_fnm)
static bool vdso_loadmodule(const char *pathname)
Definition: CallPath.cpp:130
double demandMetric(size_t mId, size_t size=0) const
static void noteStaticStructure(Prof::CallPath::Profile &prof)
Definition: CallPath.cpp:959
void pruneBySummaryMetrics(Prof::CallPath::Profile &prof, uint8_t *prunedNodes)
Definition: CallPath.cpp:805
void hpcrun_node_type(uint16_t type)
Definition: CCT-Tree.hpp:422
ssize_t MONITOR_EXT_WRAP_NAME() read(int fd, void *buf, size_t count)
Definition: io-over.c:152
virtual std::string toStringMe(uint oFlags=0) const
Definition: CCT-Tree.cpp:1367
void noteStaticStructureOnLeaves(Prof::CallPath::Profile &prof)
Definition: CallPath.cpp:454
bool isUsed() const
Definition: LoadMap.hpp:142
#define NULL
Definition: ElfHelper.cpp:85
const std::string & namePfx() const
std::string title
Definition: Args.hpp:121
void addDirectory(std::string filename)
#define NODE_TYPE_REGULAR
Definition: hpcrun-fmt.h:515
ACodeNode * findByVMA(VMA vma) const
Metric::ADesc * metric(uint i)
Definition: Metric-Mgr.hpp:131
void overlayStaticStructure(Prof::CallPath::Profile &prof, Prof::LoadMap::LM *loadmap_lm, Prof::Struct::LM *lmStrct, BinUtil::LM *lm)
Definition: CallPath.cpp:443
std::ostream & writeXML(std::ostream &os, const Metric::Mgr *metricMgr, uint metricBeg=Metric::IData::npos, uint metricEnd=Metric::IData::npos, uint oFlags=0) const
Definition: CCT-Tree.cpp:281
std::ostream * dbgOs
Definition: CallPath.cpp:117
SrcFile::ln begLine() const
Definition: CCT-Tree.hpp:413
#define DIAG_Die(...)
Definition: diagnostics.h:267
#define GCC_ATTR_UNUSED
Definition: gcc-attr.h:80
<!-- ********************************************************************--> n<!-- HPCToolkit Experiment DTD --> n<!-- Version 2.1 --> n<!-- ********************************************************************--> n<!ELEMENT HPCToolkitExperiment(Header,(SecCallPathProfile|SecFlatProfile) *)> n<!ATTLIST HPCToolkitExperiment\n version CDATA #REQUIRED > n n<!-- ******************************************************************--> n n<!-- Info/NV:flexible name-value pairs:(n) ame;(t) ype;(v) alue --> n<!ELEMENT Info(NV *)> n<!ATTLIST Info\n n CDATA #IMPLIED > n<!ELEMENT NV EMPTY > n<!ATTLIST NV\n n CDATA #REQUIRED\n t CDATA #IMPLIED\n v CDATA #REQUIRED > n n<!-- ******************************************************************--> n<!-- Header --> n<!-- ******************************************************************--> n<!ELEMENT Header(Info *)> n<!ATTLIST Header\n n CDATA #REQUIRED > n n<!-- ******************************************************************--> n<!-- Section Header --> n<!-- ******************************************************************--> n<!ELEMENT SecHeader(MetricTable?, MetricDBTable?, TraceDBTable?, LoadModuleTable?, FileTable?, ProcedureTable?, Info *)> n n<!-- MetricTable:--> n<!ELEMENT MetricTable(Metric) * > n n<!-- Metric:(i) d;(n) ame --> n<!--(v) alue-type:transient type of values --> n<!--(t) ype:persistent type of metric --> n<!-- fmt:format;show;--> n<!ELEMENT Metric(MetricFormula *, Info?)> n<!ATTLIST Metric\n i CDATA #REQUIRED\n n CDATA #REQUIRED\n es CDATA #IMPLIED\n em CDATA #IMPLIED\n ep CDATA #IMPLIED\n v(raw|final|derived-incr|derived) \"raw\\ t (inclusive|exclusive|nil) \nil\\ partner CDATA #IMPLIED\ fmt CDATA #IMPLIED\ show (1|0) \1\\ show-percent (1|0) \1> n n<!-- MetricFormula represents derived metrics: (t)ype; (frm): formula --> n<!ELEMENT MetricFormula (Info?)> n<!ATTLIST MetricFormula\ t (combine|finalize) \finalize\\ i CDATA #IMPLIED\ frm CDATA #REQUIRED> n n<!-- Metric data, used in sections: (n)ame [from Metric]; (v)alue --> n<!ELEMENT M EMPTY> n<!ATTLIST M\ n CDATA #REQUIRED\ v CDATA #REQUIRED> n n<!-- MetricDBTable: --> n<!ELEMENT MetricDBTable (MetricDB)*> n n<!-- MetricDB: (i)d; (n)ame --> n<!-- (t)ype: persistent type of metric --> n<!-- db-glob: file glob describing files in metric db --> n<!-- db-id: id within metric db --> n<!-- db-num-metrics: number of metrics in db --> n<!-- db-header-sz: size (in bytes) of a db file header --> n<!ELEMENT MetricDB EMPTY> n<!ATTLIST MetricDB\ i CDATA #REQUIRED\ n CDATA #REQUIRED\ t (inclusive|exclusive|nil) \nil\\ partner CDATA #IMPLIED\ db-glob CDATA #IMPLIED\ db-id CDATA #IMPLIED\ db-num-metrics CDATA #IMPLIED\ db-header-sz CDATA #IMPLIED> n n<!-- TraceDBTable: --> n<!ELEMENT TraceDBTable (TraceDB)> n n<!-- TraceDB: (i)d --> n<!-- db-min-time: min beginning time stamp (global) --> n<!-- db-max-time: max ending time stamp (global) --> n<!ELEMENT TraceDB EMPTY> n<!ATTLIST TraceDB\ i CDATA #REQUIRED\ db-glob CDATA #IMPLIED\ db-min-time CDATA #IMPLIED\ db-max-time CDATA #IMPLIED\ db-header-sz CDATA #IMPLIED> n n<!-- LoadModuleTable assigns a short name to a load module --> n<!ELEMENT LoadModuleTable (LoadModule)*> n n<!ELEMENT LoadModule (Info?)> n<!ATTLIST LoadModule\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!-- FileTable assigns a short name to a file --> n<!ELEMENT FileTable (File)*> n n<!ELEMENT File (Info?)> n<!ATTLIST File\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!-- ProcedureTable assigns a short name to a procedure --> n<!ELEMENT ProcedureTable (Procedure)*> n n<!-- Info/NV: flexible name-value pairs: (n)ame; (t)ype; (v)alue --> n<!-- f: family of the procedure (fake, root, ...)--> n<!ELEMENT Procedure (Info?)> n<!ATTLIST Procedure\ i CDATA #REQUIRED\ n CDATA #REQUIRED\ f CDATA #IMPLIED> n n<!-- ****************************************************************** --> n<!-- Section: Call path profile --> n<!-- ****************************************************************** --> n<!ELEMENT SecCallPathProfile (SecHeader, SecCallPathProfileData)> n<!ATTLIST SecCallPathProfile\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!ELEMENT SecCallPathProfileData (PF|M)*> n<!-- Procedure frame --> n<!-- (i)d: unique identifier for cross referencing --> n<!-- (s)tatic scope id --> n<!-- (n)ame: a string or an id in ProcedureTable --> n<!-- (lm) load module: a string or an id in LoadModuleTable --> n<!-- (f)ile name: a string or an id in LoadModuleTable --> n<!-- (l)ine range: \beg-end\ (inclusive range) --> n<!-- (a)lien: whether frame is alien to enclosing P --> n<!-- (str)uct: hpcstruct node id --> n<!-- (t)ype: hpcrun node type: memory access, variable declaration, ... --> n<!-- (v)ma-range-set: \{[beg-end), [beg-end)...}\ --> n<!ELEMENT PF (PF|Pr|L|C|S|M)*> n<!ATTLIST PF\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ n CDATA #REQUIRED\ lm CDATA #IMPLIED\ f CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Procedure (static): GOAL: replace with 'P' --> n<!ELEMENT Pr (Pr|L|C|S|M)*> n<!ATTLIST Pr\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ n CDATA #REQUIRED\ lm CDATA #IMPLIED\ f CDATA #IMPLIED\ l CDATA #IMPLIED\ a (1|0) \0\\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Callsite (a special StatementRange) --> n<!ELEMENT C (PF|M)*> n<!ATTLIST C\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n n<!-- ****************************************************************** --> n<!-- Section: Flat profile --> n<!-- ****************************************************************** --> n<!ELEMENT SecFlatProfile (SecHeader, SecFlatProfileData)> n<!ATTLIST SecFlatProfile\ i CDATA #REQUIRED\ n CDATA #REQUIRED> n n<!ELEMENT SecFlatProfileData (LM|M)*> n<!-- Load module: (i)d; (n)ame; (v)ma-range-set --> n<!ELEMENT LM (F|P|M)*> n<!ATTLIST LM\ i CDATA #IMPLIED\ n CDATA #REQUIRED\ v CDATA #IMPLIED> n<!-- File --> n<!ELEMENT F (P|L|S|M)*> n<!ATTLIST F\ i CDATA #IMPLIED\ n CDATA #REQUIRED> n<!-- Procedure (Note 1) --> n<!ELEMENT P (P|A|L|S|C|M)*> n<!ATTLIST P\ i CDATA #IMPLIED\ n CDATA #REQUIRED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Alien (Note 1) --> n<!ELEMENT A (A|L|S|C|M)*> n<!ATTLIST A\ i CDATA #IMPLIED\ f CDATA #IMPLIED\ n CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Loop (Note 1,2) --> n<!ELEMENT L (A|Pr|L|S|C|M)*> n<!ATTLIST L\ i CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ f CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Statement (Note 2) --> n<!-- (it): trace record identifier --> n<!ELEMENT S (S|M)*> n<!ATTLIST S\ i CDATA #IMPLIED\ it CDATA #IMPLIED\ s CDATA #IMPLIED\ l CDATA #IMPLIED\ str CDATA #IMPLIED\ v CDATA #IMPLIED> n<!-- Note 1: Contained Cs may not contain PFs --> n<!-- Note 2: The 's' attribute is not used for flat profiles --> n
const std::string & name() const
const ANodeFilter ANodeTyFilter[ANode::TyNUMBER]
Proc * ancestorProc() const
Metric::ADesc * findLastVisible() const
Definition: Metric-Mgr.cpp:517
static void write(Prof::CallPath::Profile &prof, std::ostream &os, const Analysis::Args &args)
Definition: CallPath.cpp:1138
std::map< Prof::Struct::ANode *, Prof::CCT::ANode * > StructToCCTMap
Definition: CallPath.cpp:318
virtual NonUniformDegreeTreeNode * Current() const
std::vector< std::string > StringVec
Definition: Util.hpp:108
#define HPCIO_RWBufferSz
Definition: hpcio.h:86
MergeEffect merge(ANode *y)
Definition: CCT-Tree.cpp:906
static bool merge(ANode *node_dst, ANode *node_src)
void readStructure(Struct::Tree &structure, const std::vector< string > &structureFiles, PGMDocHandler::Doc_t docty, DocHandlerArgs &docargs)
Definition: PGMReader.cpp:133
void applyThreadMetricAgents(Prof::CallPath::Profile &prof, string agent)
Definition: CallPath.cpp:985
CCT::Tree * cct() const
virtual void open(const char *filenm)
Definition: LM.cpp:395
virtual NonUniformDegreeTreeNode * Current() const