static void makeDerivedMetrics(Prof::Metric::Mgr& metricMgr, uint /*Analysis::Args::MetricFlg*/ metrics) { if (Analysis::Args::MetricFlg_isSum(metrics)) { bool needAllStats = Analysis::Args::MetricFlg_isSet(metrics, Analysis::Args::MetricFlg_StatsAll); bool needMultiOccurance = Analysis::Args::MetricFlg_isThread(metrics); metricMgr.makeSummaryMetrics(needAllStats, needMultiOccurance); } if (!Analysis::Args::MetricFlg_isThread(metrics)) { using namespace Prof; for (uint i = 0; i < metricMgr.size(); i++) { Metric::ADesc* m = metricMgr.metric(i); Metric::SampledDesc* mm = dynamic_cast<Metric::SampledDesc*>(m); if (mm) { mm->isVisible(false); mm->isSortKey(false); } } for (uint i = 0; i < metricMgr.size(); i++) { Metric::ADesc* m = metricMgr.metric(i); Metric::DerivedDesc* mm = dynamic_cast<Metric::DerivedDesc*>(m); if (mm) { mm->isSortKey(true); break; } } } }
Prof::CallPath::Profile* read(const char* prof_fnm, uint groupId, uint rFlags) { // ------------------------------------------------------- // // ------------------------------------------------------- Prof::CallPath::Profile* prof = NULL; try { DIAG_MsgIf(0, "Reading: '" << prof_fnm << "'"); prof = Prof::CallPath::Profile::make(prof_fnm, rFlags, /*outfs*/ NULL); } catch (...) { DIAG_EMsg("While reading profile '" << prof_fnm << "'..."); throw; } // ------------------------------------------------------- // Potentially update the profile's metrics // ------------------------------------------------------- if (groupId > 0) { Prof::Metric::Mgr* metricMgr = prof->metricMgr(); for (uint i = 0; i < metricMgr->size(); ++i) { Prof::Metric::ADesc* m = metricMgr->metric(i); m->namePfx(StrUtil::toStr(groupId)); } metricMgr->recomputeMaps(); } return prof; }
MetricCursor::MetricCursor(const Prof::Metric::Mgr& metricMgr, const Prof::Flat::LM& proflm, const BinUtil::LM& lm) { m_loadAddr = (VMA)proflm.load_addr(); m_doUnrelocate = lm.doUnrelocate(m_loadAddr); // -------------------------------------------------------- // Find all metrics for load module and compute totals for each metric // For now we have one metric per sampled event. // -------------------------------------------------------- // NOTE: only handles raw events for (uint i = 0; i < metricMgr.size(); ++i) { const Prof::Metric::ADesc* m = metricMgr.metric(i); const Prof::Metric::SampledDesc* mm = dynamic_cast<const Prof::Metric::SampledDesc*>(m); if (mm) { uint mIdx = (uint)StrUtil::toUInt64(mm->profileRelId()); const Prof::Flat::EventData& profevent = proflm.event(mIdx); m_metricDescs.push_back(&profevent); } } m_metricTots.resize(m_metricDescs.size()); for (uint i = 0; i < m_metricDescs.size(); ++i) { const Prof::Flat::EventData& profevent = *(m_metricDescs[i]); uint64_t& metricTotal = m_metricTots[i]; metricTotal = 0; for (uint j = 0; j < profevent.num_data(); ++j) { const Prof::Flat::Datum& evdat = profevent.datum(j); uint32_t count = evdat.second; metricTotal += count; } } m_curMetricIdx.resize(m_metricDescs.size()); for (uint i = 0; i < m_curMetricIdx.size(); ++i) { m_curMetricIdx[i] = 0; } m_metricValAtVMA.resize(m_metricDescs.size()); }
// makeReturnCountMetric: A return count refers to the number of times // a given CCT node is called by its parent context. However, when // hpcrun records return counts, there is no structure (e.g. procedure // frames) in the CCT. An an example, in the CCT fragment below, the // return count [3] at 0xc means that 0xc returned to 0xbeef 3 times. // Simlarly, 0xbeef returned to its caller 5 times. // // | | // ip: 0xbeef [5] | // / | \ | // 0xa [1] 0xb [2] 0xc [3] | // | | | | // // To be able to say procedure F is called by procedure G x times // within this context, it is necessary to aggregate these counts at // the newly added procedure frames (Struct::ProcFrm). static void makeReturnCountMetric(Prof::CallPath::Profile& prof) { std::vector<uint> retCntId; // ------------------------------------------------------- // find return count metrics, if any // ------------------------------------------------------- Prof::Metric::Mgr* metricMgr = prof.metricMgr(); for (uint i = 0; i < metricMgr->size(); ++i) { Prof::Metric::ADesc* m = metricMgr->metric(i); if (m->nameBase().find(HPCRUN_METRIC_RetCnt) != string::npos) { retCntId.push_back(m->id()); m->computedType(Prof::Metric::ADesc::ComputedTy_Final); m->type(Prof::Metric::ADesc::TyExcl); } } if (retCntId.empty()) { return; } // ------------------------------------------------------- // propagate and aggregate return counts // ------------------------------------------------------- Prof::CCT::ANode* cct_root = prof.cct()->root(); Prof::CCT::ANodeIterator it(cct_root, NULL/*filter*/, false/*leavesOnly*/, IteratorStack::PostOrder); for (Prof::CCT::ANode* n = NULL; (n = it.current()); ++it) { if (typeid(*n) != typeid(Prof::CCT::ProcFrm) && n != cct_root) { Prof::CCT::ANode* n_parent = n->parent(); for (uint i = 0; i < retCntId.size(); ++i) { uint mId = retCntId[i]; n_parent->demandMetric(mId) += n->demandMetric(mId); n->metric(mId) = 0.0; } } } }