diff options
Diffstat (limited to 'gprofng/src/BaseMetricTreeNode.cc')
-rw-r--r-- | gprofng/src/BaseMetricTreeNode.cc | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/gprofng/src/BaseMetricTreeNode.cc b/gprofng/src/BaseMetricTreeNode.cc new file mode 100644 index 00000000000..2d1db99bd3a --- /dev/null +++ b/gprofng/src/BaseMetricTreeNode.cc @@ -0,0 +1,329 @@ +/* Copyright (C) 2021 Free Software Foundation, Inc. + Contributed by Oracle. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "config.h" +#include <stdio.h> +#include <strings.h> +#include <limits.h> +#include <sys/param.h> + +#include "hwcentry.h" +#include "DbeSession.h" +#include "Experiment.h" +#include "Expression.h" +#include "Metric.h" +#include "Table.h" +#include "i18n.h" +#include "debug.h" + +BaseMetricTreeNode::BaseMetricTreeNode () +{ + init_vars (); + build_basic_tree (); +} + +BaseMetricTreeNode::BaseMetricTreeNode (BaseMetric *item) +{ + init_vars (); + bm = item; + name = dbe_strdup (bm->get_cmd ()); + uname = dbe_strdup (bm->get_username ()); + unit = NULL; //YXXX populate from base_metric (requires updating base_metric) + unit_uname = NULL; +} + +BaseMetricTreeNode::BaseMetricTreeNode (const char *_name, const char *_uname, + const char *_unit, const char *_unit_uname) +{ + init_vars (); + name = dbe_strdup (_name); + uname = dbe_strdup (_uname); + unit = dbe_strdup (_unit); + unit_uname = dbe_strdup (_unit_uname); +} + +void +BaseMetricTreeNode::init_vars () +{ + name = NULL; + uname = NULL; + unit = NULL; + unit_uname = NULL; + root = this; + parent = NULL; + children = new Vector<BaseMetricTreeNode*>; + isCompositeMetric = false; + bm = NULL; + registered = false; + num_registered_descendents = 0; +} + +BaseMetricTreeNode::~BaseMetricTreeNode () +{ + children->destroy (); + delete children; + free (name); + free (uname); + free (unit); + free (unit_uname); +} + +BaseMetricTreeNode * +BaseMetricTreeNode::register_metric (BaseMetric *item) +{ + BaseMetricTreeNode *found = root->find (item->get_cmd ()); + if (!found) + { + switch (item->get_type ()) + { + case BaseMetric::CP_TOTAL: + found = root->find (L_CP_TOTAL); + break; + case BaseMetric::CP_TOTAL_CPU: + found = root->find (L_CP_TOTAL_CPU); + break; + } + if (found && found->bm == NULL) + found->bm = item; + } + if (!found) + { + switch (item->get_type ()) + { + case BaseMetric::HEAP_ALLOC_BYTES: + case BaseMetric::HEAP_ALLOC_CNT: + case BaseMetric::HEAP_LEAK_BYTES: + case BaseMetric::HEAP_LEAK_CNT: + found = root->find (get_prof_data_type_name (DATA_HEAP)); + break; + case BaseMetric::CP_KERNEL_CPU: + case BaseMetric::CP_TOTAL: + found = root->find (get_prof_data_type_name (DATA_CLOCK)); + break; + case BaseMetric::CP_LMS_DFAULT: + case BaseMetric::CP_LMS_TFAULT: + case BaseMetric::CP_LMS_KFAULT: + case BaseMetric::CP_LMS_STOPPED: + case BaseMetric::CP_LMS_WAIT_CPU: + case BaseMetric::CP_LMS_SLEEP: + case BaseMetric::CP_LMS_USER_LOCK: + case BaseMetric::CP_TOTAL_CPU: + found = root->find (L_CP_TOTAL); + break; + case BaseMetric::CP_LMS_USER: + case BaseMetric::CP_LMS_SYSTEM: + case BaseMetric::CP_LMS_TRAP: + found = root->find (L_CP_TOTAL_CPU); + break; + case BaseMetric::HWCNTR: + found = root->find ((item->get_flavors () & BaseMetric::DATASPACE) != 0 ? + L2_HWC_DSPACE : L2_HWC_GENERAL); + break; + case BaseMetric::SYNC_WAIT_TIME: + case BaseMetric::SYNC_WAIT_COUNT: + found = root->find (get_prof_data_type_name (DATA_SYNCH)); + break; + case BaseMetric::OMP_WORK: + case BaseMetric::OMP_WAIT: + case BaseMetric::OMP_OVHD: + found = root->find (get_prof_data_type_name (DATA_OMP)); + break; + case BaseMetric::IO_READ_TIME: + case BaseMetric::IO_READ_BYTES: + case BaseMetric::IO_READ_CNT: + case BaseMetric::IO_WRITE_TIME: + case BaseMetric::IO_WRITE_BYTES: + case BaseMetric::IO_WRITE_CNT: + case BaseMetric::IO_OTHER_TIME: + case BaseMetric::IO_OTHER_CNT: + case BaseMetric::IO_ERROR_TIME: + case BaseMetric::IO_ERROR_CNT: + found = root->find (get_prof_data_type_name (DATA_IOTRACE)); + break; + case BaseMetric::ONAME: + case BaseMetric::SIZES: + case BaseMetric::ADDRESS: + found = root->find (L1_STATIC); + break; + default: + found = root->find (L1_OTHER); + break; + } + assert (found != NULL); + switch (item->get_type ()) + { + case BaseMetric::CP_TOTAL: + case BaseMetric::CP_TOTAL_CPU: + found->isCompositeMetric = true; + break; + } + found = found->add_child (item); + } + register_node (found); + return found; +} + +void +BaseMetricTreeNode::register_node (BaseMetricTreeNode *node) +{ + if (!node->registered) + { + node->registered = true; + BaseMetricTreeNode *tmp = node->parent; + while (tmp) + { + tmp->num_registered_descendents++; + tmp = tmp->parent; + } + } +} + +BaseMetricTreeNode * +BaseMetricTreeNode::find (const char *_name) +{ + BaseMetricTreeNode *found = NULL; + if (dbe_strcmp (get_name (), _name) == 0) + return this; + if (bm && dbe_strcmp (bm->get_cmd (), _name) == 0) + return this; + BaseMetricTreeNode *child; + int index; + + Vec_loop (BaseMetricTreeNode*, children, index, child) + { + found = child->find (_name); + if (found) + return found; + } + return NULL; +} + +static void +int_get_registered_descendents (BaseMetricTreeNode* curr, + Vector<BaseMetricTreeNode*> *dest, bool nearest_only) +{ + if (!curr) + return; + if (curr->is_registered ()) + { + dest->append (curr); + if (nearest_only) + return; // soon as we hit a live node, stop following branch + } + int index; + BaseMetricTreeNode *child; + + Vec_loop (BaseMetricTreeNode*, curr->get_children (), index, child) + { + int_get_registered_descendents (child, dest, nearest_only); + } +} + +void +BaseMetricTreeNode::get_nearest_registered_descendents (Vector<BaseMetricTreeNode*> *dest) +{ + if (!dest || dest->size () != 0) + abort (); + bool nearest_only = true; + int_get_registered_descendents (this, dest, nearest_only); +} + +void +BaseMetricTreeNode::get_all_registered_descendents (Vector<BaseMetricTreeNode*> *dest) +{ + if (!dest || dest->size () != 0) + abort (); + bool nearest_only = false; + int_get_registered_descendents (this, dest, nearest_only); +} + +char * +BaseMetricTreeNode::get_description () +{ + if (bm) + { + Hwcentry* hw_ctr = bm->get_hw_ctr (); + if (hw_ctr) + return hw_ctr->short_desc; + } + return NULL; +} + +void +BaseMetricTreeNode::build_basic_tree () +{ +#define TREE_INSERT_DATA_TYPE(t) add_child(get_prof_data_type_name (t), get_prof_data_type_uname (t)) + BaseMetricTreeNode *level1, *level2; + // register L1_DURATION here because it has a value but is not a true metric + register_node (add_child (L1_DURATION, L1_DURATION_UNAME, UNIT_SECONDS, + UNIT_SECONDS_UNAME)); + register_node (add_child (L1_GCDURATION, L1_GCDURATION_UNAME, UNIT_SECONDS, + UNIT_SECONDS_UNAME)); + TREE_INSERT_DATA_TYPE (DATA_HEAP); + level1 = TREE_INSERT_DATA_TYPE (DATA_CLOCK); + level1 = level1->add_child (L_CP_TOTAL, GTXT ("XXX Total Thread Time")); + level1->isCompositeMetric = true; + level2 = level1->add_child (L_CP_TOTAL_CPU, GTXT ("XXX Total CPU Time")); + level2->isCompositeMetric = true; + + add_child (L1_OTHER, L1_OTHER_UNAME); + level1 = TREE_INSERT_DATA_TYPE (DATA_HWC); + level1->add_child (L2_HWC_DSPACE, L2_HWC_DSPACE_UNAME); + level1->add_child (L2_HWC_GENERAL, L2_HWC_GENERAL_UNAME); + TREE_INSERT_DATA_TYPE (DATA_SYNCH); + TREE_INSERT_DATA_TYPE (DATA_OMP); + TREE_INSERT_DATA_TYPE (DATA_IOTRACE); + add_child (L1_STATIC, L1_STATIC_UNAME); +} + +BaseMetricTreeNode * +BaseMetricTreeNode::add_child (BaseMetric *item) +{ + return add_child (new BaseMetricTreeNode (item)); +} + +BaseMetricTreeNode * +BaseMetricTreeNode::add_child (const char * _name, const char *_uname, + const char * _unit, const char * _unit_uname) +{ + return add_child (new BaseMetricTreeNode (_name, _uname, _unit, _unit_uname)); +} + +BaseMetricTreeNode * +BaseMetricTreeNode::add_child (BaseMetricTreeNode *new_node) +{ + new_node->parent = this; + new_node->root = root; + children->append (new_node); + return new_node; +} + +char * +BaseMetricTreeNode::dump () +{ + int len = 4; + char *s = bm ? bm->dump () : dbe_strdup ("<no base metric>"); + char *msg = dbe_sprintf ("%s\n%*c %*c unit='%s' unit_uname='%s' uname='%s' name='%s'\n", + STR (s), len, ' ', len, ' ', + STR (get_unit_uname ()), STR (get_unit ()), + STR (get_user_name ()), STR (get_name ())); + free (s); + return msg; +} |