From 471e1b4618596a42514545ef8dc21c5e495b4d0b Mon Sep 17 00:00:00 2001 From: Kevin Huck Date: Tue, 11 May 2021 21:19:12 -0700 Subject: [PATCH] Adding task tree ASCII output, for issue #150 --- src/apex/dependency_tree.cpp | 38 ++++++++++++++++++++++++++++++++++ src/apex/dependency_tree.hpp | 4 ++++ src/apex/profiler_listener.cpp | 4 ++++ src/apex/task_identifier.cpp | 19 +++++++++++++++++ src/apex/task_identifier.hpp | 1 + 5 files changed, 66 insertions(+) diff --git a/src/apex/dependency_tree.cpp b/src/apex/dependency_tree.cpp index c53f2a11..edb628b1 100644 --- a/src/apex/dependency_tree.cpp +++ b/src/apex/dependency_tree.cpp @@ -9,6 +9,8 @@ #include "dependency_tree.hpp" #include "utils.hpp" #include +#include +#include namespace apex { @@ -90,11 +92,47 @@ void Node::writeNode(std::ofstream& outfile, double total) { } } +void Node::writeNodeASCII(double total, size_t indent) { + for (size_t i = 0 ; i < indent ; i++) { + std::cout << "| "; + } + indent++; + // Write out the name + std::cout << data->get_short_name() << ": "; + // write out the inclusive and percent of total + const std::string apex_main_str("APEX MAIN"); + double acc = (data == task_identifier::get_task_id(apex_main_str)) ? + total : accumulated; + double percentage = (accumulated / total) * 100.0; + std::cout << std::setprecision(5) << acc << " - " + << std::setprecision(4) << percentage << "% ["; + // write the number of calls + double ncalls = (calls == 0) ? 1 : calls; + std::cout << ncalls << "]"; + // write other stats - min, max, stddev + double mean = acc / ncalls; + double variance = ((sumsqr / ncalls) - (mean * mean)); + double stddev = sqrt(variance); + std::cout << " {min=" << std::setprecision(4) << min << ", max=" << max + << ", mean=" << mean << ", var=" << variance + << ", std dev=" << stddev << "}"; + // end the line + std::cout << std::endl; + + // do all the children + for (auto c : children) { + c.second->writeNodeASCII(acc, indent); + } +} + void Node::addAccumulated(double value, bool is_resume) { static std::mutex m; m.lock(); if (!is_resume) { calls+=1; } accumulated = accumulated + value; + if (min == 0.0 || value < min) { min = value; } + if (value > max) { max = value; } + sumsqr = sumsqr + (value*value); m.unlock(); } diff --git a/src/apex/dependency_tree.hpp b/src/apex/dependency_tree.hpp index cbb620c5..bb13d95f 100644 --- a/src/apex/dependency_tree.hpp +++ b/src/apex/dependency_tree.hpp @@ -23,6 +23,9 @@ class Node { size_t count; double calls; double accumulated; + double min; + double max; + double sumsqr; size_t index; std::unordered_map children; static std::mutex treeMutex; @@ -48,6 +51,7 @@ class Node { void addAccumulated(double value, bool is_resume); size_t getIndex() { return index; }; void writeNode(std::ofstream& outfile, double total); + void writeNodeASCII(double total, size_t indent); }; } // dependency_tree diff --git a/src/apex/profiler_listener.cpp b/src/apex/profiler_listener.cpp index 6981815c..d9cf179a 100644 --- a/src/apex/profiler_listener.cpp +++ b/src/apex/profiler_listener.cpp @@ -1012,6 +1012,10 @@ std::unordered_set free_profiles; root->tree_node->writeNode(myfile, wall_clock_main); myfile << "}\n"; myfile.close(); + // dump the tree to the screen, for now + std::cout << std::endl; + root->tree_node->writeNodeASCII(wall_clock_main, 0); + std::cout << std::endl; } /* Write TAU profiles from the collected data. */ diff --git a/src/apex/task_identifier.cpp b/src/apex/task_identifier.cpp index 5f0e5c81..3b3a847f 100644 --- a/src/apex/task_identifier.cpp +++ b/src/apex/task_identifier.cpp @@ -55,6 +55,25 @@ std::mutex bfd_mutex; the program exits and the pointers aren't needed any more. */ } + std::string task_identifier::get_short_name() { + std::string shorter(get_name(true)); + size_t trim_at = shorter.find("("); + if (trim_at != std::string::npos) { + shorter = shorter.substr(0, trim_at); + } + trim_at = shorter.find("<"); + if (trim_at != std::string::npos) { + shorter = shorter.substr(0, trim_at); + } + size_t maxlength = 50; + // to keep formatting pretty, trim any long timer names + if (shorter.size() > maxlength) { + shorter.resize(maxlength-3); + shorter.resize(maxlength, '.'); + } + return shorter; + } + std::string task_identifier::get_name(bool resolve) { if (!has_name && resolve) { if (_resolved_name == "" && address != APEX_NULL_FUNCTION_ADDRESS) { diff --git a/src/apex/task_identifier.hpp b/src/apex/task_identifier.hpp index d093f90f..7d5cc999 100644 --- a/src/apex/task_identifier.hpp +++ b/src/apex/task_identifier.hpp @@ -63,6 +63,7 @@ class task_identifier { static task_identifier * get_task_id (apex_function_address a); static task_identifier * get_task_id (const std::string& n); std::string get_name(bool resolve = true); + std::string get_short_name(); ~task_identifier() { } // requried for using this class as a key in an unordered map. // the hash function is defined below.