xref: /netbsd-src/external/gpl3/binutils.old/dist/gprofng/src/BaseMetricTreeNode.cc (revision 3117ece4fc4a4ca4489ba793710b60b0d26bab6c)
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2    Contributed by Oracle.
3 
4    This file is part of GNU Binutils.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20 
21 #include "config.h"
22 #include <stdio.h>
23 #include <strings.h>
24 #include <limits.h>
25 #include <sys/param.h>
26 
27 #include "hwcentry.h"
28 #include "DbeSession.h"
29 #include "Experiment.h"
30 #include "Expression.h"
31 #include "Metric.h"
32 #include "Table.h"
33 #include "i18n.h"
34 #include "debug.h"
35 
36 BaseMetricTreeNode::BaseMetricTreeNode ()
37 {
38   init_vars ();
39   build_basic_tree ();
40 }
41 
42 BaseMetricTreeNode::BaseMetricTreeNode (BaseMetric *item)
43 {
44   init_vars ();
45   bm = item;
46   name = dbe_strdup (bm->get_cmd ());
47   uname = dbe_strdup (bm->get_username ());
48   unit = NULL; //YXXX populate from base_metric (requires updating base_metric)
49   unit_uname = NULL;
50 }
51 
52 BaseMetricTreeNode::BaseMetricTreeNode (const char *_name, const char *_uname,
53 				    const char *_unit, const char *_unit_uname)
54 {
55   init_vars ();
56   name = dbe_strdup (_name);
57   uname = dbe_strdup (_uname);
58   unit = dbe_strdup (_unit);
59   unit_uname = dbe_strdup (_unit_uname);
60 }
61 
62 void
63 BaseMetricTreeNode::init_vars ()
64 {
65   name = NULL;
66   uname = NULL;
67   unit = NULL;
68   unit_uname = NULL;
69   root = this;
70   parent = NULL;
71   children = new Vector<BaseMetricTreeNode*>;
72   isCompositeMetric = false;
73   bm = NULL;
74   registered = false;
75   num_registered_descendents = 0;
76 }
77 
78 BaseMetricTreeNode::~BaseMetricTreeNode ()
79 {
80   children->destroy ();
81   delete children;
82   free (name);
83   free (uname);
84   free (unit);
85   free (unit_uname);
86 }
87 
88 BaseMetricTreeNode *
89 BaseMetricTreeNode::register_metric (BaseMetric *item)
90 {
91   BaseMetricTreeNode *found = root->find (item->get_cmd ());
92   if (!found)
93     {
94       switch (item->get_type ())
95 	{
96 	case BaseMetric::CP_TOTAL:
97 	  found = root->find (L_CP_TOTAL);
98 	  break;
99 	case BaseMetric::CP_TOTAL_CPU:
100 	  found = root->find (L_CP_TOTAL_CPU);
101 	  break;
102 	}
103       if (found && found->bm == NULL)
104 	found->bm = item;
105     }
106   if (!found)
107     {
108       switch (item->get_type ())
109 	{
110 	case BaseMetric::HEAP_ALLOC_BYTES:
111 	case BaseMetric::HEAP_ALLOC_CNT:
112 	case BaseMetric::HEAP_LEAK_BYTES:
113 	case BaseMetric::HEAP_LEAK_CNT:
114 	  found = root->find (get_prof_data_type_name (DATA_HEAP));
115 	  break;
116 	case BaseMetric::CP_KERNEL_CPU:
117 	case BaseMetric::CP_TOTAL:
118 	  found = root->find (get_prof_data_type_name (DATA_CLOCK));
119 	  break;
120 	case BaseMetric::CP_LMS_DFAULT:
121 	case BaseMetric::CP_LMS_TFAULT:
122 	case BaseMetric::CP_LMS_KFAULT:
123 	case BaseMetric::CP_LMS_STOPPED:
124 	case BaseMetric::CP_LMS_WAIT_CPU:
125 	case BaseMetric::CP_LMS_SLEEP:
126 	case BaseMetric::CP_LMS_USER_LOCK:
127 	case BaseMetric::CP_TOTAL_CPU:
128 	  found = root->find (L_CP_TOTAL);
129 	  break;
130 	case BaseMetric::CP_LMS_USER:
131 	case BaseMetric::CP_LMS_SYSTEM:
132 	case BaseMetric::CP_LMS_TRAP:
133 	  found = root->find (L_CP_TOTAL_CPU);
134 	  break;
135 	case BaseMetric::HWCNTR:
136 	  found = root->find ((item->get_flavors () & BaseMetric::DATASPACE) != 0 ?
137 			      L2_HWC_DSPACE : L2_HWC_GENERAL);
138 	  break;
139 	case BaseMetric::SYNC_WAIT_TIME:
140 	case BaseMetric::SYNC_WAIT_COUNT:
141 	  found = root->find (get_prof_data_type_name (DATA_SYNCH));
142 	  break;
143 	case BaseMetric::OMP_WORK:
144 	case BaseMetric::OMP_WAIT:
145 	case BaseMetric::OMP_OVHD:
146 	  found = root->find (get_prof_data_type_name (DATA_OMP));
147 	  break;
148 	case BaseMetric::IO_READ_TIME:
149 	case BaseMetric::IO_READ_BYTES:
150 	case BaseMetric::IO_READ_CNT:
151 	case BaseMetric::IO_WRITE_TIME:
152 	case BaseMetric::IO_WRITE_BYTES:
153 	case BaseMetric::IO_WRITE_CNT:
154 	case BaseMetric::IO_OTHER_TIME:
155 	case BaseMetric::IO_OTHER_CNT:
156 	case BaseMetric::IO_ERROR_TIME:
157 	case BaseMetric::IO_ERROR_CNT:
158 	  found = root->find (get_prof_data_type_name (DATA_IOTRACE));
159 	  break;
160 	case BaseMetric::ONAME:
161 	case BaseMetric::SIZES:
162 	case BaseMetric::ADDRESS:
163 	  found = root->find (L1_STATIC);
164 	  break;
165 	default:
166 	  found = root->find (L1_OTHER);
167 	  break;
168 	}
169       assert (found != NULL);
170       switch (item->get_type ())
171 	{
172 	case BaseMetric::CP_TOTAL:
173 	case BaseMetric::CP_TOTAL_CPU:
174 	  found->isCompositeMetric = true;
175 	  break;
176 	}
177       found = found->add_child (item);
178     }
179   register_node (found);
180   return found;
181 }
182 
183 void
184 BaseMetricTreeNode::register_node (BaseMetricTreeNode *node)
185 {
186   if (!node->registered)
187     {
188       node->registered = true;
189       BaseMetricTreeNode *tmp = node->parent;
190       while (tmp)
191 	{
192 	  tmp->num_registered_descendents++;
193 	  tmp = tmp->parent;
194 	}
195     }
196 }
197 
198 BaseMetricTreeNode *
199 BaseMetricTreeNode::find (const char *_name)
200 {
201   BaseMetricTreeNode *found = NULL;
202   if (dbe_strcmp (get_name (), _name) == 0)
203     return this;
204   if (bm && dbe_strcmp (bm->get_cmd (), _name) == 0)
205     return this;
206   BaseMetricTreeNode *child;
207   int index;
208 
209   Vec_loop (BaseMetricTreeNode*, children, index, child)
210   {
211     found = child->find (_name);
212     if (found)
213       return found;
214   }
215   return NULL;
216 }
217 
218 static void
219 int_get_registered_descendents (BaseMetricTreeNode* curr,
220 			  Vector<BaseMetricTreeNode*> *dest, bool nearest_only)
221 {
222   if (!curr)
223     return;
224   if (curr->is_registered ())
225     {
226       dest->append (curr);
227       if (nearest_only)
228 	return; // soon as we hit a live node, stop following branch
229     }
230   int index;
231   BaseMetricTreeNode *child;
232 
233   Vec_loop (BaseMetricTreeNode*, curr->get_children (), index, child)
234   {
235     int_get_registered_descendents (child, dest, nearest_only);
236   }
237 }
238 
239 void
240 BaseMetricTreeNode::get_nearest_registered_descendents (Vector<BaseMetricTreeNode*> *dest)
241 {
242   if (!dest || dest->size () != 0)
243     abort ();
244   bool nearest_only = true;
245   int_get_registered_descendents (this, dest, nearest_only);
246 }
247 
248 void
249 BaseMetricTreeNode::get_all_registered_descendents (Vector<BaseMetricTreeNode*> *dest)
250 {
251   if (!dest || dest->size () != 0)
252     abort ();
253   bool nearest_only = false;
254   int_get_registered_descendents (this, dest, nearest_only);
255 }
256 
257 char *
258 BaseMetricTreeNode::get_description ()
259 {
260   if (bm)
261     {
262       Hwcentry* hw_ctr = bm->get_hw_ctr ();
263       if (hw_ctr)
264 	return hw_ctr->short_desc;
265     }
266   return NULL;
267 }
268 
269 void
270 BaseMetricTreeNode::build_basic_tree ()
271 {
272 #define TREE_INSERT_DATA_TYPE(t) add_child(get_prof_data_type_name (t), get_prof_data_type_uname (t))
273   BaseMetricTreeNode *level1, *level2;
274   // register L1_DURATION here because it has a value but is not a true metric
275   register_node (add_child (L1_DURATION, L1_DURATION_UNAME, UNIT_SECONDS,
276 			    UNIT_SECONDS_UNAME));
277   register_node (add_child (L1_GCDURATION, L1_GCDURATION_UNAME, UNIT_SECONDS,
278 			    UNIT_SECONDS_UNAME));
279   TREE_INSERT_DATA_TYPE (DATA_HEAP);
280   level1 = TREE_INSERT_DATA_TYPE (DATA_CLOCK);
281   level1 = level1->add_child (L_CP_TOTAL, GTXT ("XXX Total Thread Time"));
282   level1->isCompositeMetric = true;
283   level2 = level1->add_child (L_CP_TOTAL_CPU, GTXT ("XXX Total CPU Time"));
284   level2->isCompositeMetric = true;
285 
286   add_child (L1_OTHER, L1_OTHER_UNAME);
287   level1 = TREE_INSERT_DATA_TYPE (DATA_HWC);
288   level1->add_child (L2_HWC_DSPACE, L2_HWC_DSPACE_UNAME);
289   level1->add_child (L2_HWC_GENERAL, L2_HWC_GENERAL_UNAME);
290   TREE_INSERT_DATA_TYPE (DATA_SYNCH);
291   TREE_INSERT_DATA_TYPE (DATA_OMP);
292   TREE_INSERT_DATA_TYPE (DATA_IOTRACE);
293   add_child (L1_STATIC, L1_STATIC_UNAME);
294 }
295 
296 BaseMetricTreeNode *
297 BaseMetricTreeNode::add_child (BaseMetric *item)
298 {
299   return add_child (new BaseMetricTreeNode (item));
300 }
301 
302 BaseMetricTreeNode *
303 BaseMetricTreeNode::add_child (const char * _name, const char *_uname,
304 			       const char * _unit, const char * _unit_uname)
305 {
306   return add_child (new BaseMetricTreeNode (_name, _uname, _unit, _unit_uname));
307 }
308 
309 BaseMetricTreeNode *
310 BaseMetricTreeNode::add_child (BaseMetricTreeNode *new_node)
311 {
312   new_node->parent = this;
313   new_node->root = root;
314   children->append (new_node);
315   return new_node;
316 }
317 
318 char *
319 BaseMetricTreeNode::dump ()
320 {
321   int len = 4;
322   char *s = bm ? bm->dump () : dbe_strdup ("<no base metric>");
323   char *msg = dbe_sprintf ("%s\n%*c %*c unit='%s' unit_uname='%s' uname='%s' name='%s'\n",
324 			   STR (s), len, ' ', len, ' ',
325 			   STR (get_unit_uname ()), STR (get_unit ()),
326 			   STR (get_user_name ()), STR (get_name ()));
327   free (s);
328   return msg;
329 }
330