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 <stdlib.h>
23 #include <ctype.h>
24 #include <string.h>
25 #include <math.h>
26 #include <assert.h>
27 #include <libintl.h>
28 #include <unistd.h>
29 #include <stdio.h>
30 #include <fcntl.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33
34 #include "util.h"
35 #include "Dbe.h"
36 #include "StringBuilder.h"
37 #include "DbeSession.h"
38 #include "DbeView.h"
39 #include "Settings.h"
40 #include "Print.h"
41 #include "DbeView.h"
42 #include "Experiment.h"
43 #include "MetricList.h"
44 #include "Module.h"
45 #include "Function.h"
46 #include "DataSpace.h"
47 #include "DataObject.h"
48 #include "FilterExp.h"
49 #include "LoadObject.h"
50 #include "Emsg.h"
51 #include "Table.h"
52 #include "DbeFile.h"
53 #include "CallStack.h"
54
55 int
open(Print_params * params)56 er_print_common_display::open (Print_params *params)
57 {
58 pr_params = *params;
59 pr_params.name = dbe_strdup (params->name);
60 if (params->dest == DEST_PRINTER)
61 {
62 tmp_file = dbeSession->get_tmp_file_name (NTXT ("print"), false);
63 dbeSession->tmp_files->append (strdup (tmp_file));
64 out_file = fopen (tmp_file, NTXT ("w"));
65 }
66 else if (params->dest == DEST_OPEN_FILE)
67 out_file = pr_params.openfile;
68 else
69 out_file = fopen (pr_params.name, NTXT ("w"));
70
71 if (out_file == NULL)
72 // Failure
73 return 1;
74 return 0;
75 }
76
77 bool
print_output()78 er_print_common_display::print_output ()
79 {
80 char *sys_call;
81 bool ret = true;
82 if (pr_params.dest != DEST_OPEN_FILE)
83 fclose (out_file);
84
85 if (pr_params.dest == DEST_PRINTER)
86 {
87 if (streq ((char *) pr_params.name, NTXT ("")))
88 sys_call = dbe_sprintf ("(/usr/bin/lp -c -n%d %s) 2>/dev/null 1>&2",
89 pr_params.ncopies, tmp_file);
90 else
91 sys_call = dbe_sprintf ("(/usr/bin/lp -c -d%s -n%d %s) 2>/dev/null 1>&2",
92 pr_params.name, pr_params.ncopies, tmp_file);
93 if (system (sys_call) != 0)
94 ret = false;
95 unlink (tmp_file);
96 free (sys_call);
97 }
98
99 return ret;
100 }
101
102 // Return the report. If the report size is greater than max, return truncated report
103 // Allocates memory, so the caller should free this memory.
104
105 char *
get_output(int maxsize)106 er_print_common_display::get_output (int maxsize)
107 {
108 off_t max = (off_t) maxsize;
109 if (out_file != (FILE *) NULL)
110 {
111 fclose (out_file); // close tmp_file
112 out_file = (FILE *) NULL;
113 }
114 struct stat sbuf;
115 int st = stat (tmp_file, &sbuf);
116 if (st == 0)
117 {
118 off_t sz = sbuf.st_size;
119 if (sz > max)
120 return dbe_sprintf (GTXT ("Error: report is too long.\n"));
121 if (sz <= 0)
122 return dbe_sprintf (GTXT ("Error: empty temporary file: %s\n"),
123 tmp_file);
124 max = sz;
125 }
126
127 FILE *f = fopen (tmp_file, "r");
128 if (f == NULL)
129 return dbe_sprintf (GTXT ("Error: cannot open temporary file: %s\n"),
130 tmp_file);
131 char *report = (char *) malloc (max);
132 if (report)
133 {
134 if (1 != fread (report, max - 1, 1, f))
135 {
136 fclose (f);
137 free (report);
138 return dbe_sprintf (GTXT ("Error: cannot read temporary file: %s\n"),
139 tmp_file);
140 }
141 report[max - 1] = 0;
142 }
143 fclose (f);
144 return report;
145 }
146
147 void
header_dump(int exp_idx)148 er_print_common_display::header_dump (int exp_idx)
149 {
150 if (load && (exp_idx == exp_idx1))
151 {
152 load = false;
153 print_load_object (out_file);
154 }
155 print_header (dbeSession->get_exp (exp_idx), out_file);
156 }
157
158 char *
pr_load_objects(Vector<LoadObject * > * loadobjects,char * lead)159 pr_load_objects (Vector<LoadObject*> *loadobjects, char *lead)
160 {
161 int size, i;
162 LoadObject *lo;
163 Emsg *m;
164 char *msg;
165 StringBuilder sb;
166 char *lo_name;
167 size = loadobjects->size ();
168 for (i = 0; i < size; i++)
169 {
170 lo = loadobjects->fetch (i);
171 lo_name = lo->get_name ();
172 if (lo_name != NULL)
173 {
174 size_t len = strlen (lo_name);
175 if (len > 7 && streq (lo_name + len - 7, NTXT (".class>")))
176 continue;
177 }
178
179 // print the segment name
180 sb.append (lead);
181 sb.append (NTXT (" "));
182 sb.append (lo->get_name ());
183 sb.append (NTXT (" ("));
184 sb.append (lo->get_pathname ());
185 sb.append (NTXT (")\n"));
186
187 // and any warnings
188 m = lo->fetch_warnings ();
189 if (m != NULL)
190 {
191 msg = pr_mesgs (m, NULL, NTXT (" "));
192 sb.append (msg);
193 free (msg);
194 }
195 }
196 return sb.toString ();
197 }
198
199 char *
pr_mesgs(Emsg * msg,const char * null_str,const char * lead)200 pr_mesgs (Emsg *msg, const char *null_str, const char *lead)
201 {
202 Emsg *m;
203 StringBuilder sb;
204 if (msg == NULL)
205 return dbe_strdup (null_str);
206 for (m = msg; m; m = m->next)
207 {
208 sb.append (lead);
209 sb.append (m->get_msg ());
210 sb.append (NTXT ("\n"));
211 }
212 return sb.toString ();
213 }
214
215 void
print_load_object(FILE * out_file)216 print_load_object (FILE *out_file)
217 {
218 Vector<LoadObject*> *loadobjects = dbeSession->get_text_segments ();
219 char *msg = pr_load_objects (loadobjects, NTXT ("\t"));
220 fprintf (out_file, GTXT ("Load Object Coverage:\n"));
221 fprintf (out_file, NTXT ("%s"), msg);
222 fprintf (out_file,
223 "----------------------------------------------------------------\n");
224 free (msg);
225 delete loadobjects;
226 }
227
228 void
print_header(Experiment * exp,FILE * out_file)229 print_header (Experiment *exp, FILE *out_file)
230 {
231 fprintf (out_file, GTXT ("Experiment: %s\n"), exp->get_expt_name ());
232 char *msg = pr_mesgs (exp->fetch_notes (), NTXT (""), NTXT (""));
233 fprintf (out_file, NTXT ("%s"), msg);
234 free (msg);
235
236 msg = pr_mesgs (exp->fetch_errors (), GTXT ("No errors\n"), NTXT (""));
237 fprintf (out_file, NTXT ("%s"), msg);
238 free (msg);
239
240 msg = pr_mesgs (exp->fetch_warnings (), GTXT ("No warnings\n"), NTXT (""));
241 fprintf (out_file, NTXT ("%s"), msg);
242 free (msg);
243
244 msg = pr_mesgs (exp->fetch_comments (), NTXT (""), NTXT (""));
245 fprintf (out_file, NTXT ("%s"), msg);
246 free (msg);
247
248 msg = pr_mesgs (exp->fetch_pprocq (), NTXT (""), NTXT (""));
249 fprintf (out_file, NTXT ("%s"), msg);
250 free (msg);
251 }
252
253 static char *
delTrailingBlanks(char * s)254 delTrailingBlanks (char *s)
255 {
256 for (int i = (int) strlen (s) - 1; i >= 0 && s[i] == ' '; i--)
257 s[i] = 0;
258 return s;
259 }
260
261 /**
262 * Print the 3-line header with column heads for the metrics
263 * Return offset of "Name" column (this is needed to print Callers-Callees)
264 */
265 int
print_label(FILE * out_file,MetricList * metrics_list,Metric::HistMetric * hist_metric,int space)266 print_label (FILE *out_file, MetricList *metrics_list,
267 Metric::HistMetric *hist_metric, int space)
268 {
269 char line0[2 * MAX_LEN], line1[2 * MAX_LEN];
270 char line2[2 * MAX_LEN], line3[2 * MAX_LEN];
271 int name_offset = 0;
272 *line0 = *line1 = *line2 = *line3 = '\0';
273 Vector<Metric*> *mlist = metrics_list->get_items ();
274 for (int index = 0, mlist_sz = mlist->size (); index < mlist_sz; index++)
275 {
276 Metric *mitem = mlist->fetch (index);
277 if (mitem->is_visible () || mitem->is_tvisible () || mitem->is_pvisible ())
278 {
279 Metric::HistMetric *hitem = hist_metric + index;
280 const char *s;
281 if (index > 0 && mitem->get_type () == Metric::ONAME)
282 {
283 s = " ";
284 name_offset = strlen (line1);
285 }
286 else
287 s = "";
288 int width = (int) hitem->width;
289 size_t len = strlen (line1);
290 snprintf (line1 + len, sizeof (line1) - len, "%s%-*s", s, width,
291 hitem->legend1);
292 len = strlen (line2);
293 snprintf (line2 + len, sizeof (line2) - len, "%s%-*s", s, width,
294 hitem->legend2);
295 len = strlen (line3);
296 snprintf (line3 + len, sizeof (line3) - len, "%s%-*s", s, width,
297 hitem->legend3);
298 len = strlen (line0);
299 snprintf (line0 + len, sizeof (line0) - len, "%s%-*s", s, width,
300 mitem->legend ? mitem->legend : NTXT (""));
301 }
302 }
303 char *s = delTrailingBlanks (line0);
304 if (*s)
305 fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), s);
306 fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line1));
307 fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line2));
308 fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line3));
309 return name_offset;
310 }
311
er_print_histogram(DbeView * _dbev,Hist_data * data,MetricList * metrics_list,Print_mode disp_type,int limit,char * sort_name,Histable * sobj,bool show_load,bool show_header)312 er_print_histogram::er_print_histogram (DbeView *_dbev, Hist_data *data,
313 MetricList *metrics_list,
314 Print_mode disp_type, int limit,
315 char *sort_name, Histable *sobj,
316 bool show_load, bool show_header)
317 {
318 hist_data = data;
319 mlist = metrics_list;
320 type = disp_type;
321 number_entries = limit;
322 sort_metric = sort_name;
323 sel_obj = sobj;
324 dbev = _dbev;
325 exp_idx1 = 0;
326 exp_idx2 = dbeSession->nexps () - 1;
327 load = show_load;
328 header = show_header;
329 }
330
331 void
dump_list(int limit)332 er_print_histogram::dump_list (int limit)
333 {
334 Histable::NameFormat nfmt = dbev->get_name_format ();
335 StringBuilder sb;
336 char *title = NULL; // No title for some formats
337 enum PrintMode pm = dbev->get_printmode ();
338
339 // create a header line, except for delimiter-separated list output
340 if (pm != PM_DELIM_SEP_LIST)
341 {
342 if (hist_data->type == Histable::FUNCTION)
343 sb.append (GTXT ("Functions sorted by metric: "));
344 else if (hist_data->type == Histable::INSTR)
345 sb.append (GTXT ("PCs sorted by metric: "));
346 else if (hist_data->type == Histable::LINE)
347 sb.append (GTXT ("Lines sorted by metric: "));
348 else if (hist_data->type == Histable::DOBJECT)
349 sb.append (GTXT ("Dataobjects sorted by metric: "));
350 else
351 sb.append (GTXT ("Objects sorted by metric: "));
352 sb.append (sort_metric);
353 title = sb.toString ();
354 }
355
356 switch (pm)
357 {
358 case PM_TEXT:
359 {
360 Metric::HistMetric *hist_metric = hist_data->get_histmetrics ();
361 fprintf (out_file, NTXT ("%s\n\n"), title); //print title
362 hist_data->print_label (out_file, hist_metric, 0);
363 hist_data->print_content (out_file, hist_metric, limit);
364 fprintf (out_file, nl);
365 break;
366 }
367 case PM_HTML:
368 {
369 print_html_title (out_file, title);
370 print_html_label (out_file, mlist);
371 print_html_content (out_file, hist_data, mlist, limit, nfmt);
372 print_html_trailer (out_file);
373 break;
374 }
375 case PM_DELIM_SEP_LIST:
376 {
377 char delim = dbev->get_printdelimiter ();
378 print_delim_label (out_file, mlist, delim);
379 print_delim_content (out_file, hist_data, mlist, limit, nfmt, delim);
380 print_delim_trailer (out_file, delim);
381 break;
382 }
383 }
384 free (title);
385 }
386
387 void
dump_annotated_dataobjects(Vector<int> * marks,int ithreshold)388 er_print_histogram::dump_annotated_dataobjects (Vector<int> *marks,
389 int ithreshold)
390 {
391 if (!dbeSession->is_datamode_available ())
392 fprintf (out_file,
393 GTXT ("No dataspace information recorded in experiments\n\n"));
394
395 Hist_data *layout_data = dbev->get_data_space ()->get_layout_data (hist_data, marks, ithreshold);
396 Metric::HistMetric *hist_metric = layout_data->get_histmetrics ();
397
398 // snprintf (hist_metric[name_index].legend2, MAX_LEN, GTXT ("* +offset .element"));
399 layout_data->print_label (out_file, hist_metric, 3);
400 fprintf (out_file, nl);
401 StringBuilder sb;
402
403 for (long i = 0; i < layout_data->size (); i++)
404 {
405 sb.setLength (0);
406 if (marks->find (i) != -1)
407 sb.append ("## ");
408 else
409 sb.append (" ");
410 layout_data->print_row (&sb, i, hist_metric, " ");
411 sb.toFileLn (out_file);
412 }
413 fprintf (out_file, nl);
414 delete layout_data;
415 }
416
417 static int
max_length(size_t len,size_t str_len)418 max_length(size_t len, size_t str_len)
419 {
420 if (str_len > len)
421 return str_len;
422 return len;
423 }
424
425 void
dump_detail(int limit)426 er_print_histogram::dump_detail (int limit)
427 {
428 Histable *obj;
429 Hist_data *current_data;
430 Histable::Type htype;
431 TValue *values;
432 double dvalue, percent;
433 MetricList *prop_mlist = new MetricList (mlist);
434 Metric *mitem;
435 int index, i;
436 Module *module;
437 LoadObject *loadobject;
438 char *sname, *oname, *lname, *alias, *mangle;
439
440 Histable::NameFormat nfmt = dbev->get_name_format ();
441
442 // Check max. length of metrics names
443 size_t len = 0, slen = 0;
444 Vec_loop (Metric*, prop_mlist->get_items (), index, mitem)
445 {
446 mitem->set_vvisible (true);
447 if (mitem->get_vtype () == VT_LABEL)
448 continue;
449
450 if (mitem->get_subtype () != Metric::STATIC)
451 {
452 mitem->set_pvisible (true);
453 len = max_length (len, hist_data->value_maxlen (index));
454 slen = max_length (slen, strlen (mitem->get_name ()));
455 }
456 }
457
458 // now get the length of the other (non-performance-data) messages
459 if (hist_data->type == Histable::FUNCTION)
460 {
461 slen = max_length (slen, strlen (GTXT ("Source File")));
462 slen = max_length (slen, strlen (GTXT ("Object File")));
463 slen = max_length (slen, strlen (GTXT ("Load Object")));
464 slen = max_length (slen, strlen (GTXT ("Mangled Name")));
465 slen = max_length (slen, strlen (GTXT ("Aliases")));
466 }
467 else if (hist_data->type == Histable::DOBJECT)
468 {
469 slen = max_length (slen, strlen (GTXT ("Scope")));
470 slen = max_length (slen, strlen (GTXT ("Type")));
471 slen = max_length (slen, strlen (GTXT ("Member of")));
472 slen = max_length (slen, strlen (GTXT ("Offset (bytes)")));
473 slen = max_length (slen, strlen (GTXT ("Size (bytes)")));
474 slen = max_length (slen, strlen (GTXT ("Elements")));
475 }
476 int max_len = (int) len;
477 int smax_len = (int) slen;
478
479 #define PR_TITLE(t) fprintf (out_file, "\t%*s:", smax_len, t)
480 #define PR(title, nm) PR_TITLE(title); \
481 if (nm) \
482 fprintf (out_file, " %s", nm); \
483 fprintf (out_file, "\n")
484
485 // now loop over the objects
486 int num_printed_items = 0;
487 for (i = 0; i < hist_data->size (); i++)
488 {
489 if (hist_data->type == Histable::FUNCTION)
490 {
491 if (num_printed_items >= limit)
492 break;
493 obj = sel_obj ? sel_obj : hist_data->fetch (i)->obj;
494 htype = obj->get_type ();
495
496 // ask the view for all the data for the object
497 // xxxxx may be expensive to rescan all packets via get_hist_data()
498 current_data = dbev->get_hist_data (prop_mlist,
499 htype, 0, Hist_data::SELF, obj);
500 if (current_data->size () == 0)
501 continue;
502 values = current_data->fetch (0)->value;
503 }
504 else
505 {
506 obj = hist_data->fetch (i)->obj;
507 DataObject *dobj = (DataObject*) obj;
508 if (sel_obj)
509 {
510 // print selected item and its members
511 if (sel_obj != obj
512 && (DataObject*) sel_obj != dobj->get_parent ())
513 // not a match, advance to next item
514 continue;
515 }
516 else if (num_printed_items >= limit)
517 break;
518 htype = obj->get_type ();
519 values = hist_data->fetch (i)->value;
520 current_data = hist_data;
521 }
522
523 if (num_printed_items)
524 // if this isn't the first one, add a blank line
525 fprintf (out_file, NTXT ("\n"));
526 num_printed_items++;
527
528 // Print full object name
529 if (htype != Histable::DOBJECT)
530 fprintf (out_file, NTXT ("%s\n"), obj->get_name (nfmt));
531 else
532 {
533 DataObject *dobj = (DataObject*) obj;
534 if (!dobj->get_parent ())
535 fprintf (out_file, NTXT ("%s\n"), obj->get_name (nfmt));
536 else
537 fprintf (out_file, NTXT (" %s\n"), obj->get_name (nfmt));
538 }
539
540 Vec_loop (Metric*, prop_mlist->get_items (), index, mitem)
541 {
542 if (mitem->get_vtype () == VT_LABEL)
543 continue;
544 if (mitem->get_subtype () == Metric::STATIC
545 && htype == Histable::DOBJECT)
546 continue;
547 PR_TITLE (mitem->get_name ());
548
549 char buf[128];
550 char *s = values[index].to_str (buf, sizeof (buf));
551 if (mitem->get_value_styles () & VAL_PERCENT)
552 {
553 dvalue = values[index].to_double ();
554 percent = 100.0 * current_data->get_percentage (dvalue, index);
555 if (!mitem->is_time_val ())
556 {
557 fprintf (out_file, " %*s", max_len, s);
558 if (dvalue == 0.)
559 fprintf (out_file, " ( 0. %%)\n");
560 else
561 fprintf (out_file, " (%5.1f%%)\n", percent);
562 continue;
563 }
564
565 TValue v;
566 v.tag = VT_DOUBLE;
567 v.sign = false;
568 v.d = dvalue / (1.e+6 * dbeSession->get_clock (-1));
569 char buf1[128];
570 char *s1 = v.to_str (buf1, sizeof (buf1));
571 fprintf (out_file, " %*s", max_len, s1);
572 if (dvalue == 0.)
573 fprintf (out_file, " ( 0. %%)\n");
574 else
575 fprintf (out_file, " (%5.1f%%)\n", percent);
576 PR_TITLE (GTXT ("Count"));
577 }
578
579 int max_len1 = max_len;
580 for (int j = (int) strlen (s) - 1; j >= 0 && s[j] == ' '; j--)
581 {
582 s[j] = 0;
583 max_len1--;
584 }
585 fprintf (out_file, " %*s\n", max_len1, s);
586 }
587
588 // now add the descriptive information about the object
589 if (htype != Histable::DOBJECT)
590 {
591 Function *func = (Function*) obj->convertto (Histable::FUNCTION);
592 if (func && func->get_type () == Histable::FUNCTION)
593 {
594 // Print the source/object/load-object files & aliases
595 oname = lname = alias = NULL;
596 sname = func->getDefSrcName ();
597 mangle = func->get_mangled_name ();
598 if (mangle && streq (func->get_name (), mangle))
599 mangle = NULL;
600 module = func->module;
601 if (module)
602 {
603 oname = module->get_name ();
604 loadobject = module->loadobject;
605 if (loadobject)
606 {
607 lname = loadobject->get_pathname ();
608 alias = loadobject->get_alias (func);
609 }
610 }
611
612 if (htype == Histable::INSTR && dbeSession->is_datamode_available ())
613 alias = ((DbeInstr*) obj)->get_descriptor ();
614
615 PR (GTXT ("Source File"), sname);
616 PR (GTXT ("Object File"), oname);
617 PR (GTXT ("Load Object"), lname);
618 PR (GTXT ("Mangled Name"), mangle);
619 PR (GTXT ("Aliases"), alias);
620 }
621 }
622 else
623 {
624 // Print the dataobject information
625 DataObject *dobj = (DataObject*) obj;
626 Histable *scope = dobj->get_scope ();
627
628 // print the scope
629 PR_TITLE (GTXT ("Scope"));
630 if (!scope)
631 fprintf (out_file, GTXT ("(Global)\n"));
632 else switch (scope->get_type ())
633 {
634 case Histable::FUNCTION:
635 fprintf (out_file, NTXT ("%s(%s)\n"),
636 ((Function*) scope)->module->get_name (),
637 scope->get_name ());
638 break;
639 case Histable::LOADOBJECT:
640 case Histable::MODULE:
641 default:
642 fprintf (out_file, NTXT ("%s\n"), scope->get_name ());
643 }
644
645 // print the type name
646 PR_TITLE (GTXT ("Type"));
647 if (dobj->get_typename ())
648 fprintf (out_file, NTXT ("%s\n"), dobj->get_typename ());
649 else
650 fprintf (out_file, GTXT ("(Synthetic)\n"));
651
652 // print the offset
653 if (dobj->get_offset () != -1)
654 {
655 if (dobj->get_parent ())
656 {
657 PR_TITLE (GTXT ("Member of"));
658 fprintf (out_file, NTXT ("%s\n"), dobj->get_parent ()->get_name ());
659 }
660 PR_TITLE (GTXT ("Offset (bytes)"));
661 fprintf (out_file, NTXT ("%lld\n"), (long long) dobj->get_offset ());
662 }
663 // print the size
664 if (dobj->get_size ())
665 {
666 PR_TITLE (GTXT ("Size (bytes)"));
667 fprintf (out_file, NTXT ("%lld\n"), (long long) dobj->get_size ());
668 }
669 }
670 if (hist_data->type == Histable::FUNCTION)
671 delete current_data;
672 }
673 if (num_printed_items == 0 && sel_obj)
674 fprintf (stderr,
675 GTXT ("Error: Specified item `%s' had no recorded metrics.\n"),
676 sel_obj->get_name ());
677 delete prop_mlist;
678 }
679
680 static Metric::HistMetric *
allocateHistMetric(int no_metrics)681 allocateHistMetric (int no_metrics)
682 {
683 Metric::HistMetric *hist_metric = new Metric::HistMetric[no_metrics];
684 for (int i = 0; i < no_metrics; i++)
685 {
686 Metric::HistMetric *hm = &hist_metric[i];
687 hm->init ();
688 }
689 return hist_metric;
690 }
691
692 void
dump_gprof(int limit)693 er_print_histogram::dump_gprof (int limit)
694 {
695 StringBuilder sb;
696 Histable *obj;
697 Hist_data *callers;
698 Hist_data *callees;
699 Hist_data *center;
700
701 int no_metrics = mlist->get_items ()->size ();
702 Metric::HistMetric *hist_metric = allocateHistMetric (no_metrics);
703 for (int i = 0; i < limit; i++)
704 {
705 obj = sel_obj ? sel_obj : hist_data->fetch (i)->obj;
706 callers = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
707 Hist_data::CALLERS, obj);
708 callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
709 Hist_data::CALLEES, obj);
710 center = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
711 Hist_data::SELF, obj);
712 callers->update_max (hist_metric);
713 callees->update_max (hist_metric);
714 center->update_max (hist_metric);
715 callers->update_legend_width (hist_metric);
716 callers->print_label (out_file, hist_metric, 0);
717 callers->print_content (out_file, hist_metric, callers->size ());
718
719 if (center->size () > 0)
720 {
721 center->update_total (callers->get_totals ());
722 sb.setLength (0);
723 center->print_row (&sb, 0, hist_metric, NTXT ("*"));
724 sb.toFileLn (out_file);
725 }
726 callees->print_content (out_file, hist_metric, callees->size ());
727 fprintf (out_file, nl);
728 delete callers;
729 delete callees;
730 delete center;
731 }
732 delete[] hist_metric;
733 }
734
735 // dump an annotated file
736 void
dump_anno_file(FILE * fp,Histable::Type type,Module * module,DbeView * dbev,MetricList * mlist,TValue * ftotal,const char * srcFile,Function * func,Vector<int> * marks,int threshold,int vis_bits,int src_visible,bool hex_visible,bool src_only)737 dump_anno_file (FILE *fp, Histable::Type type, Module *module, DbeView *dbev,
738 MetricList *mlist, TValue *ftotal, const char *srcFile,
739 Function *func, Vector<int> *marks, int threshold, int vis_bits,
740 int src_visible, bool hex_visible, bool src_only)
741 {
742 int lspace, mspace, tspace, remain, mindex, next_mark, hidx, index;
743 Metric *mitem;
744 char buf[MAX_LEN];
745 Hist_data::HistItem *item;
746
747 SourceFile *srcContext = NULL;
748 bool func_scope = dbev == NULL ? false : dbev->get_func_scope ();
749 if (srcFile)
750 {
751 srcContext = module->findSource (srcFile, false);
752 if (srcContext == NULL)
753 {
754 Vector<SourceFile*> *includes = module->includes;
755 char *bname = get_basename (srcFile);
756 for (int i = 0, sz = includes ? includes->size () : 0; i < sz; i++)
757 {
758 SourceFile *sf = includes->fetch (i);
759 if (streq (get_basename (sf->get_name ()), bname))
760 {
761 srcContext = sf;
762 break;
763 }
764 }
765 }
766 if (func)
767 func_scope = true;
768 }
769 else if (func)
770 srcContext = func->getDefSrc ();
771
772 Hist_data *hdata = module->get_data (dbev, mlist, type, ftotal, srcContext,
773 func, marks, threshold, vis_bits,
774 src_visible, hex_visible,
775 func_scope, src_only);
776
777 if (hdata == NULL)
778 return;
779
780 // force the name metric to be invisible
781 MetricList *nmlist = hdata->get_metric_list ();
782 nmlist->find_metric (GTXT ("name"), Metric::STATIC)->clear_all_visbits ();
783 Metric::HistMetric *hist_metric = hdata->get_histmetrics ();
784
785 // lspace is for max line number that's inserted; use to set width
786 int max_lineno = 0;
787 Vec_loop (Hist_data::HistItem*, hdata, hidx, item)
788 {
789 if (!item->obj)
790 continue;
791 if (item->obj->get_type () == Histable::LINE
792 && ((DbeLine*) item->obj)->lineno > max_lineno)
793 max_lineno = ((DbeLine*) item->obj)->lineno;
794 else if (item->obj->get_type () == Histable::INSTR
795 && ((DbeInstr*) item->obj)->lineno > max_lineno)
796 max_lineno = ((DbeInstr*) item->obj)->lineno;
797 }
798
799 lspace = snprintf (buf, sizeof (buf), NTXT ("%d"), max_lineno);
800
801 // mspace is the space needed for all metrics, and the mark, if any
802 mspace = 0;
803 if (nmlist->get_items ()->size () > 0)
804 {
805 mspace = 3; // mark "## "
806 Vec_loop (Metric*, nmlist->get_items (), index, mitem)
807 {
808 if (mitem->is_visible () || mitem->is_tvisible ()
809 || mitem->is_pvisible ())
810 mspace += (int) hist_metric[index].width;
811 }
812 }
813 tspace = 0;
814 remain = (mspace + lspace + 3) % 8; // " " before, ". " after line#
815 if (remain)
816 { // tab alignment
817 tspace = 8 - remain;
818 mspace += tspace;
819 }
820 mindex = 0;
821 next_mark = (mindex < marks->size ()) ? marks->fetch (mindex) : -1;
822
823 // Print the header for this list
824 SourceFile *sf = srcContext ? srcContext : module->getMainSrc ();
825 char *src_name = sf->dbeFile->get_location_info ();
826 DbeFile *df = module->dbeFile;
827 if (df == NULL || (df->filetype & DbeFile::F_JAVACLASS) == 0)
828 df = module->loadobject->dbeFile;
829 char *lo_name = df->get_location_info ();
830 char *dot_o_name = lo_name;
831 if (module->dot_o_file)
832 dot_o_name = module->dot_o_file->dbeFile->get_location_info ();
833 fprintf (fp, GTXT ("Source file: %s\nObject file: %s\nLoad Object: %s\n\n"),
834 src_name, dot_o_name, lo_name);
835
836 // Print metric labels
837 if (nmlist->get_items ()->size () != 0)
838 print_label (fp, nmlist, hist_metric, 3);
839
840 // determine the name metric (not printed as a metric, though)
841 int lind = nmlist->get_listorder (GTXT ("name"), Metric::STATIC);
842
843 // now loop over the data rows -- the lines in the annotated source/disasm,
844 // including index lines, compiler commentary, etc.
845 StringBuilder sb;
846 Vec_loop (Hist_data::HistItem*, hdata, hidx, item)
847 {
848 sb.setLength (0);
849 if (item->type == Module::AT_DIS || item->type == Module::AT_QUOTE
850 || item->type == Module::AT_SRC)
851 {
852 // does this line get a high-metric mark?
853 if (hidx == next_mark)
854 {
855 sb.append (NTXT ("## "));
856 mindex++;
857 next_mark = (mindex < marks->size ()) ? marks->fetch (mindex) : -1;
858 }
859 else
860 sb.append (NTXT (" "));
861
862 hdata->print_row (&sb, hidx, hist_metric, NTXT (" "));
863 sb.toFile (fp);
864 for (int i = sb.length (); i < mspace; i++)
865 {
866 fputc (' ', fp);
867 }
868 }
869 else
870 // this line does not get any metrics; insert blanks in lieu of them
871 for (int i = 0; i < mspace; i++)
872 fputc (' ', fp);
873
874 switch (item->type)
875 {
876 case Module::AT_SRC_ONLY:
877 if (item->obj == NULL)
878 fprintf (fp, NTXT ("%*s. "), lspace + 1, "?");
879 else
880 fprintf (fp, "%*d. ", lspace + 1, ((DbeLine*) item->obj)->lineno);
881 break;
882
883 case Module::AT_SRC:
884 fprintf (fp, "%*d. ", lspace + 1, ((DbeLine*) item->obj)->lineno);
885 break;
886 case Module::AT_FUNC:
887 case Module::AT_QUOTE:
888 fprintf (fp, NTXT ("%*c"), lspace + 3, ' ');
889 break;
890 case Module::AT_DIS:
891 case Module::AT_DIS_ONLY:
892 if (item->obj == NULL || ((DbeInstr*) item->obj)->lineno == -1)
893 fprintf (fp, "%*c[%*s] ", lspace + 3, ' ', lspace, "?");
894 else
895 fprintf (fp, "%*c[%*d] ", lspace + 3, ' ', lspace,
896 ((DbeInstr*) item->obj)->lineno);
897 break;
898 case Module::AT_COM:
899 case Module::AT_EMPTY:
900 break;
901
902 }
903 if (item->value[lind].l == NULL)
904 item->value[lind].l = dbe_strdup (GTXT ("INTERNAL ERROR: missing line text"));
905 fprintf (fp, NTXT ("%s\n"), item->value[lind].l);
906 }
907 delete hdata;
908 }
909
910 void
dump_annotated()911 er_print_histogram::dump_annotated ()
912 {
913 Vector<int> *marks = new Vector<int>;
914 Function *anno_func = (Function *) sel_obj;
915 Module *module = anno_func ? anno_func->module : NULL;
916
917 if (hist_data->type == Histable::DOBJECT)
918 dump_annotated_dataobjects (marks, number_entries); // threshold
919 else if (number_entries == 0)
920 // Annotated source
921 dump_anno_file (out_file, Histable::LINE, module, dbev, mlist,
922 hist_data->get_totals ()->value, NULL, anno_func, marks,
923 dbev->get_thresh_src (), dbev->get_src_compcom (),
924 dbev->get_src_visible (), dbev->get_hex_visible (), true);
925 else
926 // Annotated disassembly
927 dump_anno_file (out_file, Histable::INSTR, module, dbev, mlist,
928 hist_data->get_totals ()->value, NULL, anno_func, marks,
929 dbev->get_thresh_dis (), dbev->get_dis_compcom (),
930 dbev->get_src_visible (), dbev->get_hex_visible (), true);
931 }
932
933 void
data_dump()934 er_print_histogram::data_dump ()
935 {
936 int limit;
937 if (hist_data->get_status () == Hist_data::SUCCESS)
938 {
939 if (sort_metric[0] == '\n')
940 { // csingle Callers-Callees entry
941 sort_metric++;
942 fprintf (out_file, NTXT ("%s\n\n"), sort_metric);
943 }
944 else if (!sel_obj && type != MODE_LIST)
945 {
946 if (hist_data->type == Histable::FUNCTION)
947 fprintf (out_file,
948 GTXT ("Functions sorted by metric: %s\n\n"), sort_metric);
949 else if (hist_data->type == Histable::DOBJECT)
950 fprintf (out_file, GTXT ("Dataobjects sorted by metric: %s\n\n"),
951 sort_metric);
952 else
953 fprintf (out_file,
954 GTXT ("Objects sorted by metric: %s\n\n"), sort_metric);
955 }
956 limit = hist_data->size ();
957 if ((number_entries > 0) && (number_entries < limit))
958 limit = number_entries;
959
960 switch (type)
961 {
962 case MODE_LIST:
963 dump_list (limit);
964 break;
965 case MODE_DETAIL:
966 dump_detail (limit);
967 break;
968 case MODE_GPROF:
969 dump_gprof (limit);
970 break;
971 case MODE_ANNOTATED:
972 dump_annotated ();
973 break;
974 }
975 }
976 else
977 fprintf (out_file, GTXT ("Get_Hist_data call failed %d\n"),
978 (int) hist_data->get_status ());
979 }
980
981 /*
982 * Class er_print_ctree to print functions call tree
983 */
er_print_ctree(DbeView * _dbev,Vector<Histable * > * _cstack,Histable * _sobj,int _limit)984 er_print_ctree::er_print_ctree (DbeView *_dbev, Vector<Histable*> *_cstack,
985 Histable *_sobj, int _limit)
986 {
987 dbev = _dbev;
988 cstack = _cstack;
989 sobj = _sobj;
990 limit = _limit;
991 print_row = 0;
992 exp_idx1 = 0;
993 exp_idx2 = dbeSession->nexps () - 1;
994 load = false;
995 header = false;
996 }
997
998 void
data_dump()999 er_print_ctree::data_dump ()
1000 {
1001 StringBuilder sb;
1002 Hist_data::HistItem *total;
1003 sb.append (GTXT ("Functions Call Tree. Metric: "));
1004 char *s = dbev->getSort (MET_CALL_AGR);
1005 sb.append (s);
1006 free (s);
1007 sb.toFileLn (out_file);
1008 fprintf (out_file, NTXT ("\n"));
1009 mlist = dbev->get_metric_list (MET_CALL_AGR);
1010
1011 // Change cstack: add sobj to the end of cstack
1012 cstack->append (sobj);
1013 Hist_data *center = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1014 Hist_data::SELF, cstack);
1015 Hist_data *callers = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1016 Hist_data::CALLERS, cstack);
1017 Hist_data *callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1018 Hist_data::CALLEES, cstack);
1019
1020 // Restore cstack
1021 int last = cstack->size () - 1;
1022 cstack->remove (last);
1023
1024 // Prepare formats
1025 int no_metrics = mlist->size ();
1026
1027 // calculate max. width using data from callers, callees, center
1028 hist_metric = allocateHistMetric (no_metrics);
1029 callers->update_max (hist_metric);
1030 callees->update_max (hist_metric);
1031 center->update_max (hist_metric);
1032 callers->update_legend_width (hist_metric);
1033 callers->print_label (out_file, hist_metric, 0); // returns Name column offset
1034
1035 print_row = 0;
1036 // Pass real total to print_children()
1037 total = center->get_totals ();
1038 print_children (center, 0, sobj, NTXT (" "), total);
1039
1040 // Free memory
1041 cstack->reset ();
1042 delete callers;
1043 delete callees;
1044 delete center;
1045 delete[] hist_metric;
1046 }
1047
1048 /*
1049 * Recursive method print_children prints Call Tree elements.
1050 */
1051 void
print_children(Hist_data * data,int index,Histable * my_obj,char * prefix,Hist_data::HistItem * total)1052 er_print_ctree::print_children (Hist_data *data, int index, Histable *my_obj,
1053 char * prefix, Hist_data::HistItem *total)
1054 {
1055 StringBuilder buf;
1056 const char *P0 = "+-";
1057 const char *P2 = " |";
1058 const char *P1 = " ";
1059
1060 // If limit exceeded - return
1061 ++print_row;
1062 if (limit > 0 && print_row > limit)
1063 return;
1064
1065 if (my_obj == NULL)
1066 return; // should never happen
1067
1068 // Prepare prefix
1069 buf.append (prefix);
1070 if (buf.endsWith (P2))
1071 {
1072 int len = buf.length () - 1;
1073 buf.setLength (len);
1074 }
1075 buf.append (P0);
1076
1077 // Change cstack: add my_obj to the end of cstack
1078 cstack->append (my_obj);
1079
1080 // Print current node info
1081 char * my_prefix = buf.toString ();
1082
1083 // Replace parent's total values with real total values
1084 data->update_total (total); // Needed to to calculate percentage only
1085 buf.setLength (0);
1086 data->print_row (&buf, index, hist_metric, my_prefix);
1087 buf.toFileLn (out_file);
1088 free (my_prefix);
1089
1090 // Get children
1091 Hist_data *callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1092 Hist_data::CALLEES, cstack);
1093 int nc = callees->size ();
1094 if (nc > 0)
1095 {
1096 // Print children
1097 Hist_data::HistItem *item;
1098 Histable *ch_obj;
1099 char *ch_prefix;
1100 buf.setLength (0);
1101 buf.append (prefix);
1102 buf.append (P2);
1103 ch_prefix = buf.toString ();
1104 for (int i = 0; i < nc - 1; i++)
1105 {
1106 item = callees->fetch (i);
1107 ch_obj = item->obj;
1108 print_children (callees, i, ch_obj, ch_prefix, total);
1109 }
1110 free (ch_prefix);
1111 buf.setLength (0);
1112 buf.append (prefix);
1113 buf.append (P1);
1114 ch_prefix = buf.toString ();
1115 item = callees->fetch (nc - 1);
1116 ch_obj = item->obj;
1117 print_children (callees, nc - 1, ch_obj, ch_prefix, total);
1118 free (ch_prefix);
1119 }
1120
1121 // Restore cstack
1122 int last = cstack->size () - 1;
1123 cstack->remove (last);
1124 delete callees;
1125 return;
1126 }
1127
er_print_gprof(DbeView * _dbev,Vector<Histable * > * _cstack)1128 er_print_gprof::er_print_gprof (DbeView *_dbev, Vector<Histable*> *_cstack)
1129 {
1130 dbev = _dbev;
1131 cstack = _cstack;
1132 exp_idx1 = 0;
1133 exp_idx2 = dbeSession->nexps () - 1;
1134 load = false;
1135 header = false;
1136 }
1137
1138 void
data_dump()1139 er_print_gprof::data_dump ()
1140 {
1141 StringBuilder sb;
1142 sb.append (GTXT ("Callers and callees sorted by metric: "));
1143 char *s = dbev->getSort (MET_CALL);
1144 sb.append (s);
1145 free (s);
1146 sb.toFileLn (out_file);
1147 fprintf (out_file, NTXT ("\n"));
1148
1149 MetricList *mlist = dbev->get_metric_list (MET_CALL);
1150 Hist_data *center = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1151 Hist_data::SELF, cstack);
1152 Hist_data *callers = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1153 Hist_data::CALLERS, cstack);
1154 Hist_data *callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1155 Hist_data::CALLEES, cstack);
1156
1157 mlist = center->get_metric_list ();
1158 int no_metrics = mlist->get_items ()->size ();
1159
1160 // update max. width for callers/callees/center function item
1161 Metric::HistMetric *hist_metric = allocateHistMetric (no_metrics);
1162 callers->update_max (hist_metric);
1163 callees->update_max (hist_metric);
1164 center->update_max (hist_metric);
1165
1166 callers->update_legend_width (hist_metric);
1167 int name_offset = callers->print_label (out_file, hist_metric, 0); // returns Name column offset
1168 // Print Callers
1169 sb.setLength (0);
1170 for (int i = 0; i < name_offset; i++)
1171 sb.append (NTXT ("="));
1172 if (name_offset > 0)
1173 sb.append (NTXT (" "));
1174 char *line1 = sb.toString ();
1175 char *line2;
1176 if (callers->size () > 0)
1177 line2 = GTXT ("Callers");
1178 else
1179 line2 = GTXT ("No Callers");
1180 fprintf (out_file, NTXT ("%s%s\n"), line1, line2);
1181 callers->print_content (out_file, hist_metric, callers->size ());
1182
1183 // Print Stack Fragment
1184 line2 = GTXT ("Stack Fragment");
1185 fprintf (out_file, NTXT ("\n%s%s\n"), line1, line2);
1186
1187 for (long i = 0, last = cstack->size () - 1; i <= last; ++i)
1188 {
1189 sb.setLength (0);
1190 if (i == last && center->size () > 0)
1191 {
1192 center->update_total (callers->get_totals ()); // Needed to to calculate percentage only
1193 center->print_row (&sb, center->size () - 1, hist_metric, NTXT (" "));
1194 }
1195 else
1196 {
1197 for (int n = name_offset; n > 0; n--)
1198 sb.append (NTXT (" "));
1199 if (name_offset > 0)
1200 sb.append (NTXT (" "));
1201 sb.append (cstack->get (i)->get_name ());
1202 }
1203 sb.toFileLn (out_file);
1204 }
1205
1206 // Print Callees
1207 if (callees->size () > 0)
1208 line2 = GTXT ("Callees");
1209 else
1210 line2 = GTXT ("No Callees");
1211 fprintf (out_file, NTXT ("\n%s%s\n"), line1, line2);
1212 callees->print_content (out_file, hist_metric, callees->size ());
1213 fprintf (out_file, nl);
1214 free (line1);
1215 delete callers;
1216 delete callees;
1217 delete center;
1218 delete[] hist_metric;
1219 }
1220
er_print_leaklist(DbeView * _dbev,bool show_leak,bool show_alloca,int _limit)1221 er_print_leaklist::er_print_leaklist (DbeView *_dbev, bool show_leak,
1222 bool show_alloca, int _limit)
1223 {
1224 dbev = _dbev;
1225 leak = show_leak;
1226 alloca = show_alloca;
1227 limit = _limit;
1228 }
1229
1230 // Output routine for leak list only
1231 void
data_dump()1232 er_print_leaklist::data_dump ()
1233 {
1234 CStack_data *lam;
1235 CStack_data::CStack_item *lae;
1236 int index;
1237 if (!dbeSession->is_leaklist_available ())
1238 fprintf (out_file, GTXT ("No leak or allocation information recorded in experiments\n\n"));
1239
1240 MetricList *origmlist = dbev->get_metric_list (MET_NORMAL);
1241 if (leak)
1242 {
1243 // make a copy of the metric list, and set metrics for leaks
1244 MetricList *nmlist = new MetricList (origmlist);
1245 nmlist->set_metrics ("e.heapleakbytes:e.heapleakcnt:name", true,
1246 dbev->get_derived_metrics ());
1247
1248 // now make a compacted version of it to get the right indices
1249 MetricList *mlist = new MetricList (nmlist);
1250 delete nmlist;
1251
1252 // fetch the callstack data
1253 lam = dbev->get_cstack_data (mlist);
1254
1255 // now print it
1256 if (lam && lam->size () != 0)
1257 {
1258 fprintf (out_file, GTXT ("Summary Results: Distinct Leaks = %d, Total Instances = %lld, Total Bytes Leaked = %lld\n\n"),
1259 (int) lam->size (), lam->total->value[1].ll,
1260 lam->total->value[0].ll);
1261
1262 Vec_loop (CStack_data::CStack_item*, lam->cstack_items, index, lae)
1263 {
1264 fprintf (out_file,
1265 GTXT ("Leak #%d, Instances = %lld, Bytes Leaked = %lld\n"),
1266 index + 1, lae->value[1].ll, lae->value[0].ll);
1267 if (lae->stack != NULL)
1268 for (int i = lae->stack->size () - 1; i >= 0; i--)
1269 {
1270 DbeInstr *instr = lae->stack->fetch (i);
1271 fprintf (out_file, NTXT (" %s\n"), instr->get_name ());
1272 }
1273 fprintf (out_file, NTXT ("\n"));
1274 if (index + 1 == limit) break;
1275 }
1276 }
1277 else
1278 fprintf (out_file, GTXT ("No leak information\n\n"));
1279 delete lam;
1280 delete mlist;
1281 }
1282
1283 if (alloca)
1284 {
1285 // make a copy of the metric list, and set metrics for leaks
1286 MetricList *nmlist = new MetricList (origmlist);
1287 nmlist->set_metrics ("e.heapallocbytes:e.heapalloccnt:name",
1288 true, dbev->get_derived_metrics ());
1289
1290 // now make a compacted version of it to get the right indices
1291 MetricList *mlist = new MetricList (nmlist);
1292 delete nmlist;
1293
1294 // fetch the callstack data
1295 lam = dbev->get_cstack_data (mlist);
1296
1297 // now print it
1298 if (lam && lam->size () != 0)
1299 {
1300 fprintf (out_file, GTXT ("Summary Results: Distinct Allocations = %d, Total Instances = %lld, Total Bytes Allocated = %lld\n\n"),
1301 (int) lam->size (), lam->total->value[1].ll,
1302 lam->total->value[0].ll);
1303 Vec_loop (CStack_data::CStack_item*, lam->cstack_items, index, lae)
1304 {
1305 fprintf (out_file, GTXT ("Allocation #%d, Instances = %lld, Bytes Allocated = %lld\n"),
1306 index + 1, lae->value[1].ll, lae->value[0].ll);
1307 if (lae->stack != NULL)
1308 for (int i = lae->stack->size () - 1; i >= 0; i--)
1309 {
1310 DbeInstr *instr = lae->stack->fetch (i);
1311 fprintf (out_file, NTXT (" %s\n"), instr->get_name ());
1312 }
1313 fprintf (out_file, NTXT ("\n"));
1314 if (index + 1 == limit) break;
1315 }
1316 }
1317 else
1318 fprintf (out_file, GTXT ("No allocation information\n\n"));
1319 delete lam;
1320 delete mlist;
1321 }
1322 }
1323
er_print_heapactivity(DbeView * _dbev,Histable::Type _type,bool _printStat,int _limit)1324 er_print_heapactivity::er_print_heapactivity (DbeView *_dbev,
1325 Histable::Type _type,
1326 bool _printStat, int _limit)
1327 {
1328 dbev = _dbev;
1329 type = _type;
1330 printStat = _printStat;
1331 limit = _limit;
1332 }
1333
1334 void
printCallStacks(Hist_data * hist_data)1335 er_print_heapactivity::printCallStacks (Hist_data *hist_data)
1336 {
1337 Hist_data::HistItem *hi;
1338 HeapData *hData;
1339 long stackId;
1340 int size = hist_data->size ();
1341 if (limit > 0 && limit < size)
1342 size = limit;
1343
1344 Histable::NameFormat fmt = dbev->get_name_format ();
1345 for (int i = 0; i < size; i++)
1346 {
1347 hi = hist_data->fetch (i);
1348 hData = (HeapData*) hi->obj;
1349 stackId = hData->id;
1350 if (i != 0)
1351 fprintf (out_file, NTXT ("\n"));
1352
1353 fprintf (out_file, NTXT ("%s\n"), hData->get_name (fmt));
1354 if (hData->getAllocCnt () > 0)
1355 {
1356 fprintf (out_file, GTXT ("Instances = %d "),
1357 (int) (hData->getAllocCnt ()));
1358 fprintf (out_file, GTXT ("Bytes Allocated = %lld\n"),
1359 (long long) hData->getAllocBytes ());
1360 }
1361
1362 if (hData->getLeakCnt () > 0)
1363 {
1364 fprintf (out_file, GTXT ("Instances = %d "),
1365 (int) (hData->getLeakCnt ()));
1366 fprintf (out_file, GTXT ("Bytes Leaked = %lld\n"),
1367 (long long) hData->getLeakBytes ());
1368 }
1369
1370 // There is no stack trace for <Total>
1371 if (i == 0)
1372 continue;
1373
1374 // LIBRARY VISIBILITY pass extra argument if necessary to get hide stack
1375 Vector<Histable*> *instrs = CallStack::getStackPCs ((void *) stackId);
1376 if (instrs != NULL)
1377 {
1378 int stSize = instrs->size ();
1379 for (int j = 0; j < stSize; j++)
1380 {
1381 Histable *instr = instrs->fetch (j);
1382 if (instr != NULL)
1383 fprintf (out_file, NTXT (" %s\n"), instr->get_name ());
1384 }
1385 delete instrs;
1386 }
1387 }
1388 }
1389
1390 void
printStatistics(Hist_data * hist_data)1391 er_print_heapactivity::printStatistics (Hist_data *hist_data)
1392 {
1393 Hist_data::HistItem *hi;
1394 HeapData *hDataTotal;
1395 hi = hist_data->fetch (0);
1396 hDataTotal = (HeapData*) hi->obj;
1397 Vector<hrtime_t> *pTimestamps;
1398 if (hDataTotal->getPeakMemUsage () > 0)
1399 {
1400 fprintf (out_file, GTXT ("\nProcess With Highest Peak Memory Usage\n"));
1401 fprintf (out_file,
1402 "-------------------------------------------------------\n");
1403 fprintf (out_file, GTXT ("Heap size bytes %lld\n"),
1404 (long long) hDataTotal->getPeakMemUsage ());
1405 fprintf (out_file, GTXT ("Experiment Id %d\n"),
1406 (int) (hDataTotal->getUserExpId ()));
1407 fprintf (out_file, GTXT ("Process Id %d\n"),
1408 (int) (hDataTotal->getPid ()));
1409 pTimestamps = hDataTotal->getPeakTimestamps ();
1410 if (pTimestamps != NULL)
1411 for (int i = 0; i < pTimestamps->size (); i++)
1412 fprintf (out_file,
1413 GTXT ("Time of peak %.3f (secs.)\n"),
1414 (double) (pTimestamps->fetch (i) / (double) NANOSEC));
1415 }
1416
1417 if (hDataTotal->getAllocCnt () > 0)
1418 {
1419 fprintf (out_file, GTXT ("\nMemory Allocations Statistics\n"));
1420 fprintf (out_file,
1421 GTXT ("Allocation Size Range Allocations \n"));
1422 fprintf (out_file,
1423 "-------------------------------------------------------\n");
1424 if (hDataTotal->getA0KB1KBCnt () > 0)
1425 fprintf (out_file, NTXT (" 0KB - 1KB %d\n"),
1426 hDataTotal->getA0KB1KBCnt ());
1427 if (hDataTotal->getA1KB8KBCnt () > 0)
1428 fprintf (out_file, NTXT (" 1KB - 8KB %d\n"),
1429 hDataTotal->getA1KB8KBCnt ());
1430 if (hDataTotal->getA8KB32KBCnt () > 0)
1431 fprintf (out_file, NTXT (" 8KB - 32KB %d\n"),
1432 hDataTotal->getA8KB32KBCnt ());
1433 if (hDataTotal->getA32KB128KBCnt () > 0)
1434 fprintf (out_file, NTXT (" 32KB - 128KB %d\n"),
1435 hDataTotal->getA32KB128KBCnt ());
1436 if (hDataTotal->getA128KB256KBCnt () > 0)
1437 fprintf (out_file, NTXT (" 128KB - 256KB %d\n"),
1438 hDataTotal->getA128KB256KBCnt ());
1439 if (hDataTotal->getA256KB512KBCnt () > 0)
1440 fprintf (out_file, NTXT (" 256KB - 512KB %d\n"),
1441 hDataTotal->getA256KB512KBCnt ());
1442 if (hDataTotal->getA512KB1000KBCnt () > 0)
1443 fprintf (out_file, NTXT (" 512KB - 1000KB %d\n"),
1444 hDataTotal->getA512KB1000KBCnt ());
1445 if (hDataTotal->getA1000KB10MBCnt () > 0)
1446 fprintf (out_file, NTXT (" 1000KB - 10MB %d\n"),
1447 hDataTotal->getA1000KB10MBCnt ());
1448 if (hDataTotal->getA10MB100MBCnt () > 0)
1449 fprintf (out_file, NTXT (" 10MB - 100MB %d\n"),
1450 hDataTotal->getA10MB100MBCnt ());
1451 if (hDataTotal->getA100MB1GBCnt () > 0)
1452 fprintf (out_file, NTXT (" 100MB - 1GB %d\n"),
1453 hDataTotal->getA100MB1GBCnt ());
1454 if (hDataTotal->getA1GB10GBCnt () > 0)
1455 fprintf (out_file, NTXT (" 1GB - 10GB %d\n"),
1456 hDataTotal->getA1GB10GBCnt ());
1457 if (hDataTotal->getA10GB100GBCnt () > 0)
1458 fprintf (out_file, NTXT (" 10GB - 100GB %d\n"),
1459 hDataTotal->getA10GB100GBCnt ());
1460 if (hDataTotal->getA100GB1TBCnt () > 0)
1461 fprintf (out_file, NTXT (" 100GB - 1TB %d\n"),
1462 hDataTotal->getA100GB1TBCnt ());
1463 if (hDataTotal->getA1TB10TBCnt () > 0)
1464 fprintf (out_file, NTXT (" 1TB - 10TB %d\n"),
1465 hDataTotal->getA1TB10TBCnt ());
1466 fprintf (out_file, GTXT ("\nSmallest allocation bytes %lld\n"),
1467 (long long) hDataTotal->getASmallestBytes ());
1468 fprintf (out_file, GTXT ("Largest allocation bytes %lld\n"),
1469 (long long) hDataTotal->getALargestBytes ());
1470 fprintf (out_file, GTXT ("Total allocations %d\n"),
1471 hDataTotal->getAllocCnt ());
1472 fprintf (out_file, GTXT ("Total bytes %lld\n"),
1473 (long long) hDataTotal->getAllocBytes ());
1474 }
1475
1476 if (hDataTotal->getLeakCnt () > 0)
1477 {
1478 fprintf (out_file, GTXT ("\nMemory Leaks Statistics\n"));
1479 fprintf (out_file,
1480 GTXT ("Leak Size Range Leaks \n"));
1481 fprintf (out_file,
1482 "-------------------------------------------------------\n");
1483 if (hDataTotal->getL0KB1KBCnt () > 0)
1484 fprintf (out_file, NTXT (" 0KB - 1KB %d\n"),
1485 hDataTotal->getL0KB1KBCnt ());
1486 if (hDataTotal->getL1KB8KBCnt () > 0)
1487 fprintf (out_file, NTXT (" 1KB - 8KB %d\n"),
1488 hDataTotal->getL1KB8KBCnt ());
1489 if (hDataTotal->getL8KB32KBCnt () > 0)
1490 fprintf (out_file, NTXT (" 8KB - 32KB %d\n"),
1491 hDataTotal->getL8KB32KBCnt ());
1492 if (hDataTotal->getL32KB128KBCnt () > 0)
1493 fprintf (out_file, NTXT (" 32KB - 128KB %d\n"),
1494 hDataTotal->getL32KB128KBCnt ());
1495 if (hDataTotal->getL128KB256KBCnt () > 0)
1496 fprintf (out_file, NTXT (" 128KB - 256KB %d\n"),
1497 hDataTotal->getL128KB256KBCnt ());
1498 if (hDataTotal->getL256KB512KBCnt () > 0)
1499 fprintf (out_file, NTXT (" 256KB - 512KB %d\n"),
1500 hDataTotal->getL256KB512KBCnt ());
1501 if (hDataTotal->getL512KB1000KBCnt () > 0)
1502 fprintf (out_file, NTXT (" 512KB - 1000KB %d\n"),
1503 hDataTotal->getL512KB1000KBCnt ());
1504 if (hDataTotal->getL1000KB10MBCnt () > 0)
1505 fprintf (out_file, NTXT (" 1000KB - 10MB %d\n"),
1506 hDataTotal->getL1000KB10MBCnt ());
1507 if (hDataTotal->getL10MB100MBCnt () > 0)
1508 fprintf (out_file, NTXT (" 10MB - 100MB %d\n"),
1509 hDataTotal->getL10MB100MBCnt ());
1510 if (hDataTotal->getL100MB1GBCnt () > 0)
1511 fprintf (out_file, NTXT (" 100MB - 1GB %d\n"),
1512 hDataTotal->getL100MB1GBCnt ());
1513 if (hDataTotal->getL1GB10GBCnt () > 0)
1514 fprintf (out_file, NTXT (" 1GB - 10GB %d\n"),
1515 hDataTotal->getL1GB10GBCnt ());
1516 if (hDataTotal->getL10GB100GBCnt () > 0)
1517 fprintf (out_file, NTXT (" 10GB - 100GB %d\n"),
1518 hDataTotal->getL10GB100GBCnt ());
1519 if (hDataTotal->getL100GB1TBCnt () > 0)
1520 fprintf (out_file, NTXT (" 100GB - 1TB %d\n"),
1521 hDataTotal->getL100GB1TBCnt ());
1522 if (hDataTotal->getL1TB10TBCnt () > 0)
1523 fprintf (out_file, NTXT (" 1TB - 10TB %d\n"),
1524 hDataTotal->getL1TB10TBCnt ());
1525 fprintf (out_file, GTXT ("\nSmallest leaked bytes %lld\n"),
1526 (long long) hDataTotal->getLSmallestBytes ());
1527 fprintf (out_file, GTXT ("Largest leaked bytes %lld\n"),
1528 (long long) hDataTotal->getLLargestBytes ());
1529 fprintf (out_file, GTXT ("Total leaked %d \n"),
1530 hDataTotal->getLeakCnt ());
1531 fprintf (out_file, GTXT ("Total bytes %lld\n"),
1532 (long long) hDataTotal->getLeakBytes ());
1533 }
1534 fprintf (out_file, NTXT ("\n"));
1535 }
1536
1537 void
data_dump()1538 er_print_heapactivity::data_dump ()
1539 {
1540 // get the list of heap events from DbeView
1541 int numExps = dbeSession->nexps ();
1542 if (!numExps)
1543 {
1544 fprintf (out_file,
1545 GTXT ("There is no heap event information in the experiments\n"));
1546 return;
1547 }
1548 MetricList *mlist = dbev->get_metric_list (MET_HEAP);
1549 Hist_data *hist_data;
1550 hist_data = dbev->get_hist_data (mlist, type, 0, Hist_data::ALL);
1551 if (printStat)
1552 printStatistics (hist_data);
1553 else
1554 printCallStacks (hist_data);
1555 }
1556
er_print_ioactivity(DbeView * _dbev,Histable::Type _type,bool _printStat,int _limit)1557 er_print_ioactivity::er_print_ioactivity (DbeView *_dbev, Histable::Type _type,
1558 bool _printStat, int _limit)
1559 {
1560 dbev = _dbev;
1561 type = _type;
1562 printStat = _printStat;
1563 limit = _limit;
1564 }
1565
1566 void
printCallStacks(Hist_data * hist_data)1567 er_print_ioactivity::printCallStacks (Hist_data *hist_data)
1568 {
1569 Hist_data::HistItem *hi;
1570 FileData *fData;
1571 long stackId;
1572 int size = hist_data->size ();
1573 if (limit > 0 && limit < size)
1574 size = limit;
1575
1576 for (int i = 0; i < size; i++)
1577 {
1578 hi = hist_data->fetch (i);
1579 fData = (FileData*) hi->obj;
1580 stackId = fData->id;
1581 if (i != 0)
1582 fprintf (out_file, NTXT ("\n"));
1583 fprintf (out_file, NTXT ("%s\n"), fData->getFileName ());
1584 if (fData->getWriteCnt () > 0)
1585 {
1586 fprintf (out_file, GTXT ("Write Time=%.6f (secs.) "),
1587 (double) (fData->getWriteTime () / (double) NANOSEC));
1588 fprintf (out_file, GTXT ("Write Bytes=%lld "),
1589 (long long) fData->getWriteBytes ());
1590 fprintf (out_file, GTXT ("Write Count=%d\n"),
1591 (int) (fData->getWriteCnt ()));
1592 }
1593 if (fData->getReadCnt () > 0)
1594 {
1595 fprintf (out_file, GTXT ("Read Time=%.6f (secs.) "),
1596 (double) (fData->getReadTime () / (double) NANOSEC));
1597 fprintf (out_file, GTXT ("Read Bytes=%lld "),
1598 (long long) fData->getReadBytes ());
1599 fprintf (out_file, GTXT ("Read Count=%d\n"),
1600 (int) fData->getReadCnt ());
1601 }
1602 if (fData->getOtherCnt () > 0)
1603 {
1604 fprintf (out_file, GTXT ("Other I/O Time=%.6f (secs.) "),
1605 (double) (fData->getOtherTime () / (double) NANOSEC));
1606 fprintf (out_file, GTXT ("Other I/O Count=%d\n"),
1607 (int) (fData->getOtherCnt ()));
1608 }
1609 if (fData->getErrorCnt () > 0)
1610 {
1611 fprintf (out_file, GTXT ("I/O Error Time=%.6f (secs.) "),
1612 (double) (fData->getErrorTime () / (double) NANOSEC));
1613 fprintf (out_file, GTXT ("I/O Error Count=%d\n"),
1614 (int) (fData->getErrorCnt ()));
1615 }
1616
1617 // There is no stack trace for <Total>
1618 if (i == 0)
1619 continue;
1620
1621 // LIBRARY VISIBILITY pass extra argument if necessary to get hide stack
1622 Vector<Histable*> *instrs = CallStack::getStackPCs ((void *) stackId);
1623 if (instrs != NULL)
1624 {
1625 int stSize = instrs->size ();
1626 for (int j = 0; j < stSize; j++)
1627 {
1628 Histable *instr = instrs->fetch (j);
1629 if (instr != NULL)
1630 fprintf (out_file, " %s\n", instr->get_name ());
1631 }
1632 delete instrs;
1633 }
1634 }
1635 }
1636
1637 void
printStatistics(Hist_data * hist_data)1638 er_print_ioactivity::printStatistics (Hist_data *hist_data)
1639 {
1640 Hist_data::HistItem *hi;
1641 FileData *fDataTotal;
1642
1643 hi = hist_data->fetch (0);
1644 fDataTotal = (FileData*) hi->obj;
1645
1646 if (fDataTotal->getWriteCnt () > 0)
1647 {
1648 fprintf (out_file,
1649 GTXT ("\nWrite Statistics\n"));
1650 fprintf (out_file,
1651 GTXT ("I/O Size Range Write Calls \n"));
1652 fprintf (out_file,
1653 "-------------------------------------------------------\n");
1654 if (fDataTotal->getW0KB1KBCnt () > 0)
1655 fprintf (out_file, NTXT (" 0KB - 1KB %d\n"),
1656 fDataTotal->getW0KB1KBCnt ());
1657 if (fDataTotal->getW1KB8KBCnt () > 0)
1658 fprintf (out_file, NTXT (" 1KB - 8KB %d\n"),
1659 fDataTotal->getW1KB8KBCnt ());
1660 if (fDataTotal->getW8KB32KBCnt () > 0)
1661 fprintf (out_file, NTXT (" 8KB - 32KB %d\n"),
1662 fDataTotal->getW8KB32KBCnt ());
1663 if (fDataTotal->getW32KB128KBCnt () > 0)
1664 fprintf (out_file, NTXT (" 32KB - 128KB %d\n"),
1665 fDataTotal->getW32KB128KBCnt ());
1666 if (fDataTotal->getW128KB256KBCnt () > 0)
1667 fprintf (out_file, NTXT (" 128KB - 256KB %d\n"),
1668 fDataTotal->getW128KB256KBCnt ());
1669 if (fDataTotal->getW256KB512KBCnt () > 0)
1670 fprintf (out_file, NTXT (" 256KB - 512KB %d\n"),
1671 fDataTotal->getW256KB512KBCnt ());
1672 if (fDataTotal->getW512KB1000KBCnt () > 0)
1673 fprintf (out_file, NTXT (" 512KB - 1000KB %d\n"),
1674 fDataTotal->getW512KB1000KBCnt ());
1675 if (fDataTotal->getW1000KB10MBCnt () > 0)
1676 fprintf (out_file, NTXT (" 1000KB - 10MB %d\n"),
1677 fDataTotal->getW1000KB10MBCnt ());
1678 if (fDataTotal->getW10MB100MBCnt () > 0)
1679 fprintf (out_file, NTXT (" 10MB - 100MB %d\n"),
1680 fDataTotal->getW10MB100MBCnt ());
1681 if (fDataTotal->getW100MB1GBCnt () > 0)
1682 fprintf (out_file, NTXT (" 100MB - 1GB %d\n"),
1683 fDataTotal->getW100MB1GBCnt ());
1684 if (fDataTotal->getW1GB10GBCnt () > 0)
1685 fprintf (out_file, NTXT (" 1GB - 10GB %d\n"),
1686 fDataTotal->getW1GB10GBCnt ());
1687 if (fDataTotal->getW10GB100GBCnt () > 0)
1688 fprintf (out_file, NTXT (" 10GB - 100GB %d\n"),
1689 fDataTotal->getW10GB100GBCnt ());
1690 if (fDataTotal->getW100GB1TBCnt () > 0)
1691 fprintf (out_file, NTXT (" 100GB - 1TB %d\n"),
1692 fDataTotal->getW100GB1TBCnt ());
1693 if (fDataTotal->getW1TB10TBCnt () > 0)
1694 fprintf (out_file, NTXT (" 1TB - 10TB %d\n"),
1695 fDataTotal->getW1TB10TBCnt ());
1696 fprintf (out_file,
1697 GTXT ("\nLongest write %.6f (secs.)\n"),
1698 (double) (fDataTotal->getWSlowestBytes () / (double) NANOSEC));
1699 fprintf (out_file, GTXT ("Smallest write bytes %lld\n"),
1700 (long long) fDataTotal->getWSmallestBytes ());
1701 fprintf (out_file, GTXT ("Largest write bytes %lld\n"),
1702 (long long) fDataTotal->getWLargestBytes ());
1703 fprintf (out_file,
1704 GTXT ("Total time %.6f (secs.)\n"),
1705 (double) (fDataTotal->getWriteTime () / (double) NANOSEC));
1706 fprintf (out_file, GTXT ("Total calls %d\n"),
1707 fDataTotal->getWriteCnt ());
1708 fprintf (out_file, GTXT ("Total bytes %lld\n"),
1709 (long long) fDataTotal->getWriteBytes ());
1710 }
1711
1712 if (fDataTotal->getReadCnt () > 0)
1713 {
1714 fprintf (out_file,
1715 GTXT ("\nRead Statistics\n"));
1716 fprintf (out_file,
1717 GTXT ("I/O Size Range Read Calls \n"));
1718 fprintf (out_file,
1719 "------------------------------------------------------\n");
1720 if (fDataTotal->getR0KB1KBCnt () > 0)
1721 fprintf (out_file, NTXT (" 0KB - 1KB %d\n"),
1722 fDataTotal->getR0KB1KBCnt ());
1723 if (fDataTotal->getR1KB8KBCnt () > 0)
1724 fprintf (out_file, NTXT (" 1KB - 8KB %d\n"),
1725 fDataTotal->getR1KB8KBCnt ());
1726 if (fDataTotal->getR8KB32KBCnt () > 0)
1727 fprintf (out_file, NTXT (" 8KB - 32KB %d\n"),
1728 fDataTotal->getR8KB32KBCnt ());
1729 if (fDataTotal->getR32KB128KBCnt () > 0)
1730 fprintf (out_file, NTXT (" 32KB - 128KB %d\n"),
1731 fDataTotal->getR32KB128KBCnt ());
1732 if (fDataTotal->getR128KB256KBCnt () > 0)
1733 fprintf (out_file, NTXT (" 128KB - 256KB %d\n"),
1734 fDataTotal->getR128KB256KBCnt ());
1735 if (fDataTotal->getR256KB512KBCnt () > 0)
1736 fprintf (out_file, NTXT (" 256KB - 512KB %d\n"),
1737 fDataTotal->getR256KB512KBCnt ());
1738 if (fDataTotal->getR512KB1000KBCnt () > 0)
1739 fprintf (out_file, NTXT (" 512KB - 1000KB %d\n"),
1740 fDataTotal->getR512KB1000KBCnt ());
1741 if (fDataTotal->getR1000KB10MBCnt () > 0)
1742 fprintf (out_file, NTXT (" 1000KB - 10MB %d\n"),
1743 fDataTotal->getR1000KB10MBCnt ());
1744 if (fDataTotal->getR10MB100MBCnt () > 0)
1745 fprintf (out_file, NTXT (" 10MB - 100MB %d\n"),
1746 fDataTotal->getR10MB100MBCnt ());
1747 if (fDataTotal->getR100MB1GBCnt () > 0)
1748 fprintf (out_file, NTXT (" 100MB - 1GB %d\n"),
1749 fDataTotal->getR100MB1GBCnt ());
1750 if (fDataTotal->getR1GB10GBCnt () > 0)
1751 fprintf (out_file, NTXT (" 1GB - 10GB %d\n"),
1752 fDataTotal->getR1GB10GBCnt ());
1753 if (fDataTotal->getR10GB100GBCnt () > 0)
1754 fprintf (out_file, NTXT (" 10GB - 100GB %d\n"),
1755 fDataTotal->getR10GB100GBCnt ());
1756 if (fDataTotal->getR100GB1TBCnt () > 0)
1757 fprintf (out_file, NTXT (" 100GB - 1TB %d\n"),
1758 fDataTotal->getR100GB1TBCnt ());
1759 if (fDataTotal->getR1TB10TBCnt () > 0)
1760 fprintf (out_file, NTXT (" 1TB - 10TB %d\n"),
1761 fDataTotal->getR1TB10TBCnt ());
1762 fprintf (out_file,
1763 GTXT ("\nLongest time %.6f (secs.)\n"),
1764 (double) (fDataTotal->getRSlowestBytes () / (double) NANOSEC));
1765 fprintf (out_file, GTXT ("Smallest read bytes %lld\n"),
1766 (long long) fDataTotal->getRSmallestBytes ());
1767 fprintf (out_file, GTXT ("Largest read bytes %lld\n"),
1768 (long long) fDataTotal->getRLargestBytes ());
1769 fprintf (out_file,
1770 GTXT ("Total time %.6f (secs.)\n"),
1771 (double) (fDataTotal->getReadTime () / (double) NANOSEC));
1772 fprintf (out_file, GTXT ("Total calls %d\n"),
1773 fDataTotal->getReadCnt ());
1774 fprintf (out_file, GTXT ("Total bytes %lld\n"),
1775 (long long) fDataTotal->getReadBytes ());
1776 }
1777
1778 if (fDataTotal->getOtherCnt () > 0)
1779 {
1780 fprintf (out_file, GTXT ("\nOther I/O Statistics\n"));
1781 fprintf (out_file,
1782 "-----------------------------------------------------\n");
1783 fprintf (out_file,
1784 GTXT ("Total time %.6f (secs.)\n"),
1785 (double) (fDataTotal->getOtherTime () / (double) NANOSEC));
1786 fprintf (out_file, GTXT ("Total calls %d \n"),
1787 fDataTotal->getOtherCnt ());
1788 }
1789 if (fDataTotal->getErrorCnt () > 0)
1790 {
1791 fprintf (out_file, GTXT ("\nI/O Error Statistics\n"));
1792 fprintf (out_file,
1793 "-----------------------------------------------------\n");
1794 fprintf (out_file,
1795 GTXT ("Total time %.6f (secs.)\n"),
1796 (double) (fDataTotal->getErrorTime () / (double) NANOSEC));
1797 fprintf (out_file, GTXT ("Total calls %d \n"),
1798 fDataTotal->getErrorCnt ());
1799 }
1800 fprintf (out_file, NTXT ("\n"));
1801 }
1802
1803 void
data_dump()1804 er_print_ioactivity::data_dump ()
1805 {
1806 // get the list of io events from DbeView
1807 int numExps = dbeSession->nexps ();
1808 if (!numExps)
1809 {
1810 fprintf (out_file,
1811 GTXT ("There is no IO event information in the experiments\n"));
1812 return;
1813 }
1814
1815 MetricList *mlist = dbev->get_metric_list (MET_IO);
1816 Hist_data *hist_data = dbev->get_hist_data (mlist, type, 0, Hist_data::ALL);
1817 if (type == Histable::IOCALLSTACK)
1818 printCallStacks (hist_data);
1819 else if (printStat)
1820 printStatistics (hist_data);
1821 else
1822 {
1823 Metric::HistMetric *hist_metric = hist_data->get_histmetrics ();
1824 hist_data->print_label (out_file, hist_metric, 0);
1825 hist_data->print_content (out_file, hist_metric, limit);
1826 fprintf (out_file, nl);
1827 }
1828 }
1829
er_print_experiment(DbeView * _dbev,int bgn_idx,int end_idx,bool show_load,bool show_header,bool show_stat,bool show_over,bool show_odetail)1830 er_print_experiment::er_print_experiment (DbeView *_dbev, int bgn_idx,
1831 int end_idx, bool show_load,
1832 bool show_header, bool show_stat,
1833 bool show_over, bool show_odetail)
1834 {
1835 dbev = _dbev;
1836 exp_idx1 = bgn_idx;
1837 exp_idx2 = end_idx;
1838 load = show_load;
1839 header = show_header;
1840 stat = show_stat;
1841 over = show_over;
1842 odetail = show_odetail;
1843 }
1844
1845 void
data_dump()1846 er_print_experiment::data_dump ()
1847 {
1848 int index, maxlen;
1849
1850 maxlen = 0;
1851
1852 if (stat)
1853 {
1854 max_len1 = 50;
1855 if (exp_idx2 > exp_idx1)
1856 {
1857 statistics_sum (maxlen);
1858 fprintf (out_file, nl);
1859 }
1860
1861 for (index = exp_idx1; index <= exp_idx2; index++)
1862 statistics_dump (index, maxlen);
1863 }
1864 else if (over)
1865 {
1866 max_len1 = 50;
1867 if (exp_idx2 > exp_idx1)
1868 {
1869 overview_sum (maxlen);
1870 fprintf (out_file, nl);
1871 }
1872
1873 for (index = exp_idx1; index <= exp_idx2; index++)
1874 overview_dump (index, maxlen);
1875 }
1876 else if (header)
1877 for (index = exp_idx1; index <= exp_idx2; index++)
1878 {
1879 if (index != exp_idx1)
1880 fprintf (out_file,
1881 "----------------------------------------------------------------\n");
1882 header_dump (index);
1883 }
1884 }
1885
1886 void
overview_sum(int & maxlen)1887 er_print_experiment::overview_sum (int &maxlen)
1888 {
1889 int index;
1890 Ovw_data *sum_data = new Ovw_data ();
1891 for (index = exp_idx1; index <= exp_idx2; index++)
1892 {
1893 Ovw_data *ovw_data = dbev->get_ovw_data (index);
1894 if (ovw_data == NULL)
1895 continue;
1896 sum_data->sum (ovw_data);
1897 delete ovw_data;
1898 }
1899
1900 fprintf (out_file, GTXT ("<Sum across selected experiments>"));
1901 fprintf (out_file, nl);
1902 overview_summary (sum_data, maxlen);
1903 fprintf (out_file, nl);
1904 delete sum_data;
1905 }
1906
1907 void
overview_dump(int exp_idx,int & maxlen)1908 er_print_experiment::overview_dump (int exp_idx, int &maxlen)
1909 {
1910 Ovw_data *ovw_data;
1911 Ovw_data::Ovw_item ovw_item_labels;
1912 Ovw_data::Ovw_item ovw_item;
1913 int index;
1914 int size;
1915
1916 ovw_data = dbev->get_ovw_data (exp_idx);
1917 if (ovw_data == NULL)
1918 return;
1919 if (pr_params.header)
1920 header_dump (exp_idx);
1921 else if (odetail)
1922 fprintf (out_file, GTXT ("Experiment: %s\n"),
1923 dbeSession->get_exp (exp_idx)->get_expt_name ());
1924
1925 overview_summary (ovw_data, maxlen);
1926 if (!odetail)
1927 {
1928 delete ovw_data;
1929 return;
1930 }
1931
1932 //Get the collection params for the sample selection and display them.
1933 fprintf (out_file, "\n\n%*s\n\n", max_len1, GTXT ("Individual samples"));
1934
1935 size = ovw_data->size ();
1936 ovw_item_labels = ovw_data->get_labels ();
1937
1938 for (index = 0; index < size; index++)
1939 {
1940 ovw_item = ovw_data->fetch (index);
1941 fprintf (out_file, "%*s: %d\n\n", max_len1, GTXT ("Sample Number"),
1942 ovw_item.number);
1943 overview_item (&ovw_item, &ovw_item_labels);
1944 fprintf (out_file, nl);
1945 }
1946
1947 delete ovw_data;
1948 }
1949
1950 void
overview_summary(Ovw_data * ovw_data,int & maxlen)1951 er_print_experiment::overview_summary (Ovw_data *ovw_data, int &maxlen)
1952 {
1953 char buf[128];
1954 int len;
1955 Ovw_data::Ovw_item totals;
1956 Ovw_data::Ovw_item ovw_item_labels;
1957 totals = ovw_data->get_totals ();
1958 len = snprintf (buf, sizeof (buf), "%.3lf", tstodouble (totals.total.t));
1959 if (maxlen < len)
1960 maxlen = len;
1961 max_len2 = maxlen;
1962 max_len3 = maxlen;
1963 fprintf (out_file, "%*s\n\n", max_len1,
1964 GTXT ("Aggregated statistics for selected samples"));
1965
1966 ovw_item_labels = ovw_data->get_labels ();
1967 overview_item (&totals, &ovw_item_labels);
1968 }
1969
1970 void
overview_item(Ovw_data::Ovw_item * ovw_item,Ovw_data::Ovw_item * ovw_item_labels)1971 er_print_experiment::overview_item (Ovw_data::Ovw_item *ovw_item,
1972 Ovw_data::Ovw_item *ovw_item_labels)
1973 {
1974 double start, end, total_value;
1975 int index, size;
1976 timestruc_t total_time = {0, 0};
1977
1978 start = tstodouble (ovw_item->start);
1979 end = tstodouble (ovw_item->end);
1980
1981 fprintf (out_file, "%*s: %s\n", max_len1, GTXT ("Start Label"),
1982 ovw_item->start_label);
1983 fprintf (out_file, "%*s: %s\n", max_len1, GTXT ("End Label"),
1984 ovw_item->end_label);
1985
1986 fprintf (out_file, "%*s: ", max_len1, GTXT ("Start Time (sec.)"));
1987 if (start == -1.0)
1988 fprintf (out_file, GTXT ("N/A"));
1989 else
1990 fprintf (out_file, "%*.3f", max_len2, start);
1991 fprintf (out_file, nl);
1992 fprintf (out_file, "%*s: ", max_len1, GTXT ("End Time (sec.)"));
1993 if (end == -1.0)
1994 fprintf (out_file, GTXT ("N/A"));
1995 else
1996 fprintf (out_file, "%*.3f", max_len2, end);
1997 fprintf (out_file, nl);
1998 fprintf (out_file, "%*s: ", max_len1, GTXT ("Duration (sec.)"));
1999 fprintf (out_file, "%*.3f", max_len2, tstodouble (ovw_item->duration));
2000 fprintf (out_file, NTXT ("\n"));
2001
2002 size = ovw_item->size;
2003 for (index = 0; index < size; index++)
2004 tsadd (&total_time, &ovw_item->values[index].t);
2005
2006 total_value = tstodouble (total_time);
2007 fprintf (out_file, "%*s: %*.3f", max_len1, GTXT ("Total Thread Time (sec.)"),
2008 max_len2, tstodouble (ovw_item->tlwp));
2009 fprintf (out_file, NTXT ("\n"));
2010 fprintf (out_file, "%*s: ", max_len1, GTXT ("Average number of Threads"));
2011 if (tstodouble (ovw_item->duration) != 0)
2012 fprintf (out_file, "%*.3f", max_len2, ovw_item->nlwp);
2013 else
2014 fprintf (out_file, GTXT ("N/A"));
2015 fprintf (out_file, NTXT ("\n\n"));
2016 fprintf (out_file, "%*s:\n", max_len1, GTXT ("Process Times (sec.)"));
2017 for (index = 1; index < size; index++)
2018 {
2019 overview_value (&ovw_item_labels->values[index], ovw_item_labels->type,
2020 total_value);
2021 overview_value (&ovw_item->values[index], ovw_item->type,
2022 total_value);
2023 fprintf (out_file, NTXT ("\n"));
2024 }
2025 }
2026
2027 void
overview_value(Value * value,ValueTag value_tag,double total_value)2028 er_print_experiment::overview_value (Value *value, ValueTag value_tag,
2029 double total_value)
2030 {
2031 double dvalue;
2032 switch (value_tag)
2033 {
2034 case VT_LABEL:
2035 fprintf (out_file, "%*s: ", max_len1, value->l);
2036 break;
2037 case VT_HRTIME:
2038 dvalue = tstodouble (value->t);
2039 if (dvalue == 0.0)
2040 fprintf (out_file, "%*s ( 0. %%)", max_len3, "0. ");
2041 else
2042 fprintf (out_file, "%*.3f (%5.1f%%)", max_len3, dvalue,
2043 100.0 * dvalue / total_value);
2044 break;
2045 case VT_INT:
2046 fprintf (out_file, NTXT ("%d"), value->i);
2047 break;
2048 default:
2049 fprintf (out_file, "%*.3f", max_len3, total_value);
2050 }
2051 }
2052
2053 void
statistics_sum(int & maxlen)2054 er_print_experiment::statistics_sum (int &maxlen)
2055 {
2056 int index;
2057 int size, len;
2058 Stats_data *sum_data = new Stats_data ();
2059 for (index = exp_idx1; index <= exp_idx2; index++)
2060 {
2061 Stats_data *stats_data = dbev->get_stats_data (index);
2062 if (stats_data == NULL)
2063 continue;
2064 sum_data->sum (stats_data);
2065 delete stats_data;
2066 }
2067
2068 // get the maximum width of values
2069 size = sum_data->size ();
2070 for (index = 0; index < size; index++)
2071 {
2072 len = (int) sum_data->fetch (index).value.get_len ();
2073 if (maxlen < len)
2074 maxlen = len;
2075 }
2076
2077 // print overview average
2078 overview_sum (maxlen);
2079
2080 // print statistics data
2081 max_len2 = maxlen;
2082 statistics_item (sum_data);
2083 delete sum_data;
2084 }
2085
2086 void
statistics_dump(int exp_idx,int & maxlen)2087 er_print_experiment::statistics_dump (int exp_idx, int &maxlen)
2088 {
2089 Stats_data *stats_data;
2090 int index;
2091 int size, len;
2092 stats_data = dbev->get_stats_data (exp_idx);
2093 if (stats_data == NULL)
2094 return;
2095 if (pr_params.header)
2096 {
2097 header_dump (exp_idx);
2098 fprintf (out_file, nl);
2099 }
2100 else
2101 fprintf (out_file, GTXT ("Experiment: %s\n"),
2102 dbeSession->get_exp (exp_idx)->get_expt_name ());
2103
2104 // get the maximum width of values
2105 size = stats_data->size ();
2106 for (index = 0; index < size; index++)
2107 {
2108 len = (int) stats_data->fetch (index).value.get_len ();
2109 if (maxlen < len)
2110 maxlen = len;
2111 }
2112
2113 // print overview average
2114 overview_dump (exp_idx, maxlen);
2115 fprintf (out_file, nl);
2116
2117 // print statistics data
2118 max_len2 = maxlen;
2119 statistics_item (stats_data);
2120 delete stats_data;
2121 }
2122
2123 void
statistics_item(Stats_data * stats_data)2124 er_print_experiment::statistics_item (Stats_data *stats_data)
2125 {
2126 int size, index;
2127 Stats_data::Stats_item stats_item;
2128 char buf[256];
2129 size = stats_data->size ();
2130 for (index = 0; index < size; index++)
2131 {
2132 stats_item = stats_data->fetch (index);
2133 fprintf (out_file, "%*s: %*s\n", max_len1, stats_item.label,
2134 max_len2, stats_item.value.to_str (buf, sizeof (buf)));
2135 }
2136 fprintf (out_file, nl);
2137 }
2138
2139 // Print annotated source or disassembly -- called by er_print only
2140 void
print_anno_file(char * name,const char * sel,const char * srcFile,bool isDisasm,FILE * dis_file,FILE * inp_file,FILE * out_file,DbeView * dbev,bool xdefault)2141 print_anno_file (char *name, const char *sel, const char *srcFile,
2142 bool isDisasm, FILE *dis_file, FILE *inp_file, FILE *out_file,
2143 DbeView *dbev, bool xdefault)
2144 {
2145 Histable *obj;
2146 Function *func;
2147 Module *module;
2148 Vector<int> *marks;
2149 Hist_data *hist_data;
2150 char *errstr;
2151 int index;
2152 SourceFile *fitem;
2153 int threshold;
2154 int compcom_bits;
2155 int src_visible;
2156 bool hex_visible;
2157 bool srcmetrics_visible;
2158
2159 if ((name == NULL) || (strlen (name) == 0))
2160 {
2161 fprintf (stderr, GTXT ("Error: No function or file has been specified.\n"));
2162 return;
2163 }
2164
2165 // find the function from the name
2166 if (!dbeSession->find_obj (dis_file, inp_file, obj, name, sel,
2167 Histable::FUNCTION, xdefault))
2168 return;
2169
2170 if (obj != NULL)
2171 {
2172 // source or disassembly for <Total>, <Unknown>, or @plt
2173 if (obj->get_type () != Histable::FUNCTION)
2174 {
2175 fprintf (stderr,
2176 GTXT ("Error: %s is not a real function; no source or disassembly available.\n"),
2177 name);
2178 return;
2179 }
2180
2181 func = (Function *) obj;
2182 if (func->flags & FUNC_FLAG_SIMULATED)
2183 {
2184 fprintf (stderr,
2185 GTXT ("Error: %s is not a real function; no source or disassembly available.\n"),
2186 name);
2187 return;
2188 }
2189 else if (dbev != NULL && isDisasm)
2190 dbev->set_func_scope (true);
2191
2192 // function found, set module
2193 module = func->module;
2194 int ix = module->loadobject->seg_idx;
2195 if (dbev->get_lo_expand (ix) == LIBEX_HIDE)
2196 {
2197 char *lo_name = module->loadobject->get_name ();
2198 fprintf (stderr,
2199 GTXT ("Error: No source or disassembly available for hidden object %s.\n"),
2200 lo_name);
2201 return;
2202 }
2203
2204 if (srcFile)
2205 {
2206 Vector<SourceFile*> *sources = func->get_sources ();
2207 bool found = false;
2208 if (sources == NULL)
2209 {
2210 fitem = func->getDefSrc ();
2211 found = (func->line_first > 0)
2212 && strcmp (basename (srcFile),
2213 basename (fitem->get_name ())) == 0;
2214 }
2215 else
2216 {
2217 Vec_loop (SourceFile*, sources, index, fitem)
2218 {
2219 if (strcmp (basename (srcFile), basename (fitem->get_name ())) == 0)
2220 {
2221 found = true;
2222 break;
2223 }
2224 }
2225 }
2226 if (!found)
2227 {
2228 fprintf (stderr, GTXT ("Error: Source file context %s does not contribute to function `%s'.\n"),
2229 srcFile, name);
2230 return;
2231 }
2232 }
2233 }
2234 else
2235 {
2236 // function not found
2237 if (sel && strrchr (sel, ':'))
2238 {
2239 // 'sel' was "@seg_num:address" or "file_name:address"
2240 fprintf (stderr,
2241 GTXT ("Error: No function with given name `%s %s' found.\n"),
2242 name, sel);
2243 return;
2244 }
2245 // search for a file of that name
2246 if (!dbeSession->find_obj (dis_file, inp_file, obj, name, sel,
2247 Histable::MODULE, xdefault))
2248 return;
2249
2250 if (obj == NULL)
2251 { // neither function nor file found
2252 fprintf (stderr, GTXT ("Error: No function or file with given name `%s' found.\n"),
2253 name);
2254 return;
2255 }
2256
2257 func = NULL;
2258 module = (Module *) obj;
2259 int ix = module->loadobject->seg_idx;
2260 if (dbev->get_lo_expand (ix) == LIBEX_HIDE)
2261 {
2262 char *lo_name = module->loadobject->get_name ();
2263 fprintf (stderr, GTXT ("Error: No source or disassembly available for hidden object %s.\n"),
2264 lo_name);
2265 return;
2266 }
2267 if (name)
2268 srcFile = name;
2269 }
2270
2271 if (module == NULL || module->get_name () == NULL)
2272 {
2273 fprintf (stderr, GTXT ("Error: Object name not recorded in experiment\n"));
2274 return;
2275 }
2276 module->read_stabs ();
2277
2278 if (!isDisasm && (module->file_name == NULL
2279 || (module->flags & MOD_FLAG_UNKNOWN) != 0
2280 || *module->file_name == 0))
2281 {
2282 fprintf (stderr, GTXT ("Error: Source location not recorded in experiment\n"));
2283 return;
2284 }
2285
2286 MetricList *metric_list = dbev->get_metric_list (MET_NORMAL);
2287 int sort_ref_index = metric_list->get_sort_ref_index ();
2288 if (isDisasm)
2289 metric_list->set_sort_ref_index (-1);
2290
2291 // Ask DbeView to generate function-level data
2292 // MSI: I think this is used only to get totals to compute percentages
2293 hist_data = dbev->get_hist_data (metric_list, Histable::FUNCTION, 0,
2294 Hist_data::ALL);
2295 MetricList *nmlist = hist_data->get_metric_list ();
2296 metric_list->set_sort_ref_index (sort_ref_index);
2297 if (nmlist->get_items ()->size () != 0
2298 && hist_data->get_status () != Hist_data::SUCCESS)
2299 {
2300 errstr = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
2301 if (errstr)
2302 {
2303 fprintf (stderr, GTXT ("Error: %s\n"), errstr);
2304 free (errstr);
2305 }
2306 return;
2307 }
2308
2309 marks = new Vector<int>;
2310 if (isDisasm)
2311 {
2312 threshold = dbev->get_thresh_dis ();
2313 compcom_bits = dbev->get_dis_compcom ();
2314 src_visible = dbev->get_src_visible ();
2315 hex_visible = dbev->get_hex_visible ();
2316 srcmetrics_visible = dbev->get_srcmetric_visible ();
2317 }
2318 else
2319 {
2320 threshold = dbev->get_thresh_src ();
2321 compcom_bits = dbev->get_src_compcom ();
2322 src_visible = SRC_NA;
2323 hex_visible = false;
2324 srcmetrics_visible = false;
2325 }
2326
2327 dump_anno_file (out_file, isDisasm ? Histable::INSTR : Histable::LINE,
2328 module, dbev, nmlist, hist_data->get_totals ()->value,
2329 srcFile, func, marks, threshold, compcom_bits,
2330 src_visible, hex_visible, srcmetrics_visible);
2331
2332 delete marks;
2333
2334 errstr = module->anno_str ();
2335 if (errstr)
2336 {
2337 fprintf (stderr, GTXT ("Error: %s\n"), errstr);
2338 free (errstr);
2339 }
2340 delete hist_data;
2341 }
2342
2343 void
print_html_title(FILE * out_file,char * title)2344 print_html_title (FILE *out_file, char *title)
2345 {
2346 // This will print a header row for the report
2347 fprintf (out_file, "<html><title>%s</title>\n", title);
2348 fprintf (out_file, "<center><h3>%s</h3></center>\n", title);
2349 }
2350
2351 void
print_html_label(FILE * out_file,MetricList * metrics_list)2352 print_html_label (FILE *out_file, MetricList *metrics_list)
2353 {
2354 int mlist_sz;
2355
2356 // This will print a header row for the metrics
2357 Vector<Metric*> *mlist = metrics_list->get_items ();
2358 mlist_sz = mlist->size ();
2359
2360 fprintf (out_file, "<style type=\"text/css\">\n");
2361 fprintf (out_file, "<!--\nBODY\n");
2362 fprintf (out_file, ".th_C { text-align:center; background-color:lightgoldenrodyellow; }\n");
2363 fprintf (out_file, ".th_CG { text-align:center; background-color:#ffff33; }\n");
2364 fprintf (out_file, ".th_L { text-align:left; background-color:lightgoldenrodyellow; }\n");
2365 fprintf (out_file, ".th_LG { text-align:left; background-color:#ffff33; }\n");
2366 fprintf (out_file, ".td_R { text-align:right; }\n");
2367 fprintf (out_file, ".td_RG { text-align:right; background-color:#ffff33; }\n");
2368 fprintf (out_file, ".td_L { text-align:left; }\n");
2369 fprintf (out_file, ".td_LG { text-align:left; background-color:#ffff33; }\n");
2370 fprintf (out_file, "-->\n</style>");
2371 fprintf (out_file, "<center><table border=1 cellspacing=2>\n<tr>");
2372
2373 for (int index = 0; index < mlist_sz; index++)
2374 {
2375 Metric *mitem = mlist->fetch (index);
2376 int ncols = 0;
2377 if (mitem->is_visible ())
2378 ncols++;
2379 if (mitem->is_tvisible ())
2380 ncols++;
2381 if (mitem->is_pvisible ())
2382 ncols++;
2383 if (ncols == 0)
2384 continue;
2385 char *name = strdup (mitem->get_name ());
2386 char *name2 = split_metric_name (name);
2387 const char *style = index == metrics_list->get_sort_ref_index () ? "G" : "";
2388
2389 // start the column, with colspan setting, legend, and sort metric indicator
2390 if (ncols == 1)
2391 {
2392 if (mitem->get_vtype () == VT_LABEL)
2393 // left-adjust the name metric
2394 fprintf (out_file,
2395 "<th class=\"th_L%s\">%s <br>%s %s <br>%s </th>",
2396 style, mitem->legend == NULL ? " " : mitem->legend,
2397 (index == metrics_list->get_sort_ref_index ()) ? "∇" : " ",
2398 name, name2 == NULL ? " " : name2);
2399 else
2400 // but center the others
2401 fprintf (out_file,
2402 "<th class=\"th_C%s\">%s <br>%s %s <br>%s </th>",
2403 style, mitem->legend == NULL ? " " : mitem->legend,
2404 (index == metrics_list->get_sort_ref_index ()) ?
2405 "∇" : " ",
2406 name, name2 == NULL ? NTXT (" ") : name2);
2407 }
2408 else
2409 // name metric can't span columns
2410 fprintf (out_file,
2411 "<th colspan=%d class=\"th_C%s\">%s <br>%s %s <br>%s </th>",
2412 ncols, style,
2413 mitem->legend == NULL ? " " : mitem->legend,
2414 index == metrics_list->get_sort_ref_index () ?
2415 "∇" : " ",
2416 name, name2 == NULL ? " " : name2);
2417
2418 free (name);
2419 }
2420
2421 // end this row, start the units row
2422 fprintf (out_file, NTXT ("</tr>\n<tr>"));
2423
2424 // now do the units row
2425 for (int index = 0; index < mlist_sz; index++)
2426 {
2427 Metric *mitem = mlist->fetch (index);
2428 const char *style = index == metrics_list->get_sort_ref_index () ? "G" : "";
2429
2430 if (mitem->is_tvisible ())
2431 fprintf (out_file, "<th class=\"th_C%s\"> (%s)</th>", style,
2432 GTXT ("sec."));
2433 if (mitem->is_visible ())
2434 {
2435 if (mitem->get_abbr_unit () == NULL)
2436 fprintf (out_file, "<th class=\"th_C%s\"> </th>", style);
2437 else
2438 fprintf (out_file, "<th class=\"th_C%s\">(%s)</th>", style,
2439 mitem->get_abbr_unit () == NULL ? " "
2440 : mitem->get_abbr_unit ());
2441 }
2442 if (mitem->is_pvisible ())
2443 fprintf (out_file, "<th class=\"th_C%s\"> (%%)</th>", style);
2444 }
2445 fprintf (out_file, NTXT ("</tr>\n"));
2446 }
2447
2448 void
print_html_content(FILE * out_file,Hist_data * data,MetricList * metrics_list,int limit,Histable::NameFormat nfmt)2449 print_html_content (FILE *out_file, Hist_data *data, MetricList *metrics_list,
2450 int limit, Histable::NameFormat nfmt)
2451 {
2452 Hist_data::HistItem *item;
2453
2454 // printing contents.
2455 for (int i = 0; i < limit; i++)
2456 {
2457 item = data->fetch (i);
2458 print_html_one (out_file, data, item, metrics_list, nfmt);
2459 }
2460 }
2461
2462 void
print_html_one(FILE * out_file,Hist_data * data,Hist_data::HistItem * item,MetricList * metrics_list,Histable::NameFormat nfmt)2463 print_html_one (FILE *out_file, Hist_data *data, Hist_data::HistItem *item,
2464 MetricList *metrics_list, Histable::NameFormat nfmt)
2465 {
2466 Metric *mitem;
2467 int index;
2468 int visible, tvisible, pvisible;
2469 TValue *value;
2470 double percent;
2471
2472 fprintf (out_file, NTXT ("<tr>"));
2473 Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
2474 {
2475 visible = mitem->is_visible ();
2476 tvisible = mitem->is_tvisible ();
2477 pvisible = mitem->is_pvisible ();
2478 const char *style = index == metrics_list->get_sort_ref_index () ? "G" : "";
2479
2480 if (tvisible)
2481 {
2482 value = &(item->value[index]);
2483 if (value->ll == 0LL)
2484 fprintf (out_file,
2485 "<td class=\"td_R%s\"><tt>0. </tt></td>",
2486 style);
2487 else
2488 fprintf (out_file, "<td class=\"td_R%s\"><tt>%4.3lf</tt></td>",
2489 style, 1.e-6 * value->ll / dbeSession->get_clock (-1));
2490 }
2491
2492 if (visible)
2493 {
2494 if (mitem->get_vtype () == VT_LABEL)
2495 {
2496 value = &(item->value[index]);
2497 char *r;
2498 if (value->tag == VT_OFFSET)
2499 r = ((DataObject*) (item->obj))->get_offset_name ();
2500 else
2501 r = item->obj->get_name (nfmt);
2502 char *n = html_ize_name (r);
2503 fprintf (out_file, NTXT ("<td class=\"td_L%s\">%s</td>"), style, n);
2504 free (n);
2505 }
2506 else
2507 {
2508 value = &(item->value[index]);
2509 switch (value->tag)
2510 {
2511 case VT_DOUBLE:
2512 if (value->d == 0.0)
2513 fprintf (out_file,
2514 "<td class=\"td_R%s\"><tt>0. </tt></td>",
2515 style);
2516 else
2517 fprintf (out_file,
2518 "<td class=\"td_R%s\"><tt>%4.3lf</tt></td>", style,
2519 value->d);
2520 break;
2521 case VT_INT:
2522 fprintf (out_file, "<td class=\"td_R%s\"><tt>%d</tt></td>",
2523 style, value->i);
2524 break;
2525 case VT_LLONG:
2526 fprintf (out_file, "<td class=\"td_R%s\"><tt>%lld</td></tt>",
2527 style, value->ll);
2528 break;
2529 case VT_ULLONG:
2530 fprintf (out_file, "<td class=\"td_R%s\"><tt>%llu</td></tt>",
2531 style, value->ull);
2532 break;
2533 case VT_ADDRESS:
2534 fprintf (out_file,
2535 "<td class=\"td_R%s\"><tt>%u:0x%08x</tt></td>", style,
2536 ADDRESS_SEG (value->ll), ADDRESS_OFF (value->ll));
2537 break;
2538 case VT_FLOAT:
2539 if (value->f == 0.0)
2540 fprintf (out_file,
2541 "<td class=\"td_R%s\"><tt>0. </tt></td>",
2542 style);
2543 else
2544 fprintf (out_file,
2545 "<td class=\"td_R%s\"><tt>%4.3f</tt></td>",
2546 style, value->f);
2547 break;
2548 case VT_SHORT:
2549 fprintf (out_file, "<td class=\"td_R%s\"><tt>%d</tt></td>",
2550 style, value->s);
2551 break;
2552 // ignoring the following cases (why?)
2553 case VT_HRTIME:
2554 case VT_LABEL:
2555 case VT_OFFSET:
2556 break;
2557 }
2558 }
2559 }
2560
2561 if (pvisible)
2562 {
2563 percent = data->get_percentage (item->value[index].to_double (), index);
2564 if (percent == 0.0)
2565 // adjust to change format from xx.yy%
2566 fprintf (out_file, "<td class=\"td_R%s\">0. </td>",
2567 style);
2568 else
2569 // adjust format below to change format from xx.yy%
2570 fprintf (out_file, "<td class=\"td_R%s\">%3.2f</td>", style,
2571 (100.0 * percent));
2572 }
2573 }
2574 fprintf (out_file, NTXT ("</tr>\n"));
2575 }
2576
2577 void
print_html_trailer(FILE * out_file)2578 print_html_trailer (FILE *out_file)
2579 {
2580 fprintf (out_file, NTXT ("</table></center></html>\n"));
2581 }
2582
2583 static char *
del_delim(char * s)2584 del_delim (char *s)
2585 {
2586 size_t len = strlen (s);
2587 if (len > 0)
2588 s[len - 1] = 0;
2589 return s;
2590 }
2591
2592 void
print_delim_label(FILE * out_file,MetricList * metrics_list,char delim)2593 print_delim_label (FILE *out_file, MetricList *metrics_list, char delim)
2594 {
2595 char line0[2 * MAX_LEN], line1[2 * MAX_LEN];
2596 char line2[2 * MAX_LEN], line3[2 * MAX_LEN];
2597 size_t len;
2598
2599 // This will print four header rows for the metrics
2600 line0[0] = 0;
2601 line1[0] = 0;
2602 line2[0] = 0;
2603 line3[0] = 0;
2604 Vector<Metric*> *mlist = metrics_list->get_items ();
2605 for (int index = 0, mlist_sz = mlist->size (); index < mlist_sz; index++)
2606 {
2607 Metric *mitem = mlist->fetch (index);
2608 if (!(mitem->is_visible () || mitem->is_tvisible ()
2609 || mitem->is_pvisible ()))
2610 continue;
2611 char *name = strdup (mitem->get_name ());
2612 char *name2 = split_metric_name (name);
2613
2614 if (mitem->is_tvisible ())
2615 {
2616 len = strlen (line0);
2617 snprintf (line0 + len, sizeof (line0) - len, NTXT ("\"%s\"%c"),
2618 mitem->legend == NULL ? NTXT ("") : mitem->legend, delim);
2619 len = strlen (line1);
2620 snprintf (line1 + len, sizeof (line1) - len, NTXT ("\"%s\"%c"),
2621 name, delim);
2622 len = strlen (line2);
2623 snprintf (line2 + len, sizeof (line2) - len, NTXT ("\"%s\"%c"),
2624 name2 == NULL ? NTXT ("") : name2, delim);
2625 len = strlen (line3);
2626 if (index == metrics_list->get_sort_ref_index ())
2627 snprintf (line3 + len, sizeof (line3) - len, NTXT ("\"V %s\"%c"),
2628 GTXT ("(sec.)"), delim);
2629 else
2630 snprintf (line3 + len, sizeof (line3) - len, NTXT ("\" %s\"%c"),
2631 GTXT ("(sec.)"), delim);
2632 }
2633 if (mitem->is_visible ())
2634 {
2635 len = strlen (line0);
2636 snprintf (line0 + len, sizeof (line0) - len, "\"%s\"%c",
2637 mitem->legend == NULL ? "" : mitem->legend, delim);
2638
2639 len = strlen (line1);
2640 snprintf (line1 + len, sizeof (line1) - len, "\"%s\"%c",
2641 name, delim);
2642
2643 len = strlen (line2);
2644 snprintf (line2 + len, sizeof (line2) - len, "\"%s\"%c",
2645 name2 == NULL ? NTXT ("") : name2, delim);
2646
2647 len = strlen (line3);
2648 char *au = mitem->get_abbr_unit ();
2649
2650 if (index == metrics_list->get_sort_ref_index ())
2651 {
2652 if (au == NULL)
2653 snprintf (line3 + len, sizeof (line3) - len, "\"V \"%c", delim);
2654 else
2655 snprintf (line3 + len, sizeof (line3) - len, "\"V (%s)\"%c",
2656 au, delim);
2657 }
2658 else
2659 {
2660 if (au == NULL)
2661 snprintf (line3 + len, sizeof (line3) - len, "\" \"%c",
2662 delim);
2663 else
2664 snprintf (line3 + len, sizeof (line3) - len, "\" (%s)\"%c",
2665 au, delim);
2666 }
2667 }
2668 if (mitem->is_pvisible ())
2669 {
2670 len = strlen (line0);
2671 snprintf (line0 + len, sizeof (line0) - len, NTXT ("\"%s\"%c"),
2672 mitem->legend == NULL ? NTXT ("") : mitem->legend, delim);
2673
2674 len = strlen (line1);
2675 snprintf (line1 + len, sizeof (line1) - len, NTXT ("\"%s\"%c"),
2676 name, delim);
2677
2678 len = strlen (line2);
2679 snprintf (line2 + len, sizeof (line2) - len, NTXT ("\"%s\"%c"),
2680 name2 == NULL ? NTXT ("") : name2, delim);
2681
2682 len = strlen (line3);
2683 if (index == metrics_list->get_sort_ref_index ())
2684 snprintf (line3 + len, sizeof (line3) - len, NTXT ("\"V %s\"%c"),
2685 NTXT ("%%"), delim);
2686 else
2687 snprintf (line3 + len, sizeof (line3) - len, NTXT ("\" %s\"%c"),
2688 NTXT ("%%"), delim);
2689 }
2690 free (name);
2691 }
2692 // now remove the trailing delimiter, and print the four lines
2693 fprintf (out_file, NTXT ("%s\n"), del_delim (line0));
2694 fprintf (out_file, NTXT ("%s\n"), del_delim (line1));
2695 fprintf (out_file, NTXT ("%s\n"), del_delim (line2));
2696 fprintf (out_file, NTXT ("%s\n"), del_delim (line3));
2697 }
2698
2699 void
print_delim_content(FILE * out_file,Hist_data * data,MetricList * metrics_list,int limit,Histable::NameFormat nfmt,char delim)2700 print_delim_content (FILE *out_file, Hist_data *data, MetricList *metrics_list,
2701 int limit, Histable::NameFormat nfmt, char delim)
2702 {
2703 Hist_data::HistItem *item;
2704 int i;
2705
2706 // printing contents.
2707 for (i = 0; i < limit; i++)
2708 {
2709 item = data->fetch (i);
2710 print_delim_one (out_file, data, item, metrics_list, nfmt, delim);
2711 }
2712 }
2713
2714 void
print_delim_trailer(FILE *,char)2715 print_delim_trailer (FILE */*out_file*/, char /*delim*/) { }
2716
2717 // EUGENE does this function work properly when "-compare ratio" is used?
2718 // how about when the ratio is nonzero-divided-by-zero?
2719 // EUGENE actually, review this entire file
2720
2721 void
print_delim_one(FILE * out_file,Hist_data * data,Hist_data::HistItem * item,MetricList * metrics_list,Histable::NameFormat nfmt,char delim)2722 print_delim_one (FILE *out_file, Hist_data *data, Hist_data::HistItem *item,
2723 MetricList *metrics_list, Histable::NameFormat nfmt,
2724 char delim)
2725 {
2726 Metric *mitem;
2727 int index;
2728 int visible, tvisible, pvisible;
2729 TValue *value;
2730 double percent;
2731 size_t len;
2732
2733 char line1[2 * MAX_LEN];
2734 *line1 = 0;
2735 Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
2736 {
2737 visible = mitem->is_visible ();
2738 tvisible = mitem->is_tvisible ();
2739 pvisible = mitem->is_pvisible ();
2740 if (tvisible)
2741 {
2742 value = &(item->value[index]);
2743 len = strlen (line1);
2744 if (value->ll == 0LL)
2745 snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c", delim);
2746 else
2747 snprintf (line1 + len, sizeof (line1) - len, "\"%4.3lf\"%c",
2748 1.e-6 * value->ll / dbeSession->get_clock (-1),
2749 delim);
2750 }
2751
2752 if (visible)
2753 {
2754 len = strlen (line1);
2755 if (mitem->get_vtype () == VT_LABEL)
2756 {
2757 value = &(item->value[index]);
2758 char *r;
2759 if (value->tag == VT_OFFSET)
2760 r = ((DataObject*) (item->obj))->get_offset_name ();
2761 else
2762 r = item->obj->get_name (nfmt);
2763 char *p = csv_ize_name (r, delim);
2764 snprintf (line1 + len, sizeof (line1) - len, "\"%s\"%c", p, delim);
2765 free (p);
2766 }
2767 else
2768 {
2769 value = &(item->value[index]);
2770 switch (value->tag)
2771 {
2772 case VT_DOUBLE:
2773 if (value->d == 0.0)
2774 snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c",
2775 delim);
2776 else
2777 snprintf (line1 + len, sizeof (line1) - len, "\"%4.3lf\"%c",
2778 value->d, delim);
2779 break;
2780 case VT_INT:
2781 snprintf (line1 + len, sizeof (line1) - len, "\"%d\"%c",
2782 value->i, delim);
2783 break;
2784 case VT_LLONG:
2785 snprintf (line1 + len, sizeof (line1) - len, "\"%lld\"%c",
2786 value->ll, delim);
2787 break;
2788 case VT_ULLONG:
2789 snprintf (line1 + len, sizeof (line1) - len, "\"%llu\"%c",
2790 value->ull, delim);
2791 break;
2792 case VT_ADDRESS:
2793 snprintf (line1 + len, sizeof (line1) - len, "\"%u:0x%08x\"%c",
2794 ADDRESS_SEG (value->ll),
2795 ADDRESS_OFF (value->ll), delim);
2796 break;
2797 case VT_FLOAT:
2798 if (value->f == 0.0)
2799 snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c",
2800 delim);
2801 else
2802 snprintf (line1 + len, sizeof (line1) - len, "\"%4.3f\"%c",
2803 value->f, delim);
2804 break;
2805 case VT_SHORT:
2806 snprintf (line1 + len, sizeof (line1) - len, "\"%d\"%c",
2807 value->s, delim);
2808 break;
2809 // ignoring the following cases (why?)
2810 case VT_HRTIME:
2811 case VT_LABEL:
2812 case VT_OFFSET:
2813 break;
2814 }
2815 }
2816 }
2817
2818 if (pvisible)
2819 {
2820 len = strlen (line1);
2821 percent = data->get_percentage (item->value[index].to_double (), index);
2822 if (percent == 0.0)
2823 // adjust to change format from xx.yy%
2824 snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c", delim);
2825 else
2826 // adjust format below to change format from xx.yy%
2827 snprintf (line1 + len, sizeof (line1) - len, "\"%3.2f\"%c",
2828 (100.0 * percent), delim);
2829 }
2830 }
2831 fprintf (out_file, NTXT ("%s\n"), del_delim (line1));
2832 }
2833
2834 char *
html_ize_name(char * name)2835 html_ize_name (char *name)
2836 {
2837 StringBuilder sb;
2838 for (size_t i = 0; i < strlen (name); i++)
2839 {
2840 switch (name[i])
2841 {
2842 case ' ': sb.append (NTXT (" "));
2843 break;
2844 case '"': sb.append (NTXT ("""));
2845 break;
2846 case '&': sb.append (NTXT ("&"));
2847 break;
2848 case '<': sb.append (NTXT ("<"));
2849 break;
2850 case '>': sb.append (NTXT (">"));
2851 break;
2852 default: sb.append (name[i]);
2853 break;
2854 }
2855 }
2856 char *ret = sb.toString ();
2857 return ret;
2858 }
2859
2860 char *
csv_ize_name(char * name,char)2861 csv_ize_name (char *name, char /*delim*/)
2862 {
2863 StringBuilder sb;
2864 for (size_t i = 0; i < strlen (name); i++)
2865 sb.append (name[i]);
2866 char *ret = sb.toString ();
2867 return ret;
2868 }
2869
2870 // Split a metric name into two parts, replacing a blank with
2871 // a zero and returning pointer to the rest of the string, or
2872 // leaving the string unchanged, and returning NULL;
2873
2874 char *
split_metric_name(char * name)2875 split_metric_name (char *name)
2876 {
2877 // figure out the most even split of the name
2878 size_t len = strlen (name);
2879 char *middle = &name[len / 2];
2880
2881 // find the first blank
2882 char *first = strchr (name, (int) ' ');
2883 if (first == NULL) // no blanks
2884 return NULL;
2885 char *last = first;
2886 char *p = first;
2887 for (;;)
2888 {
2889 p = strchr (p + 1, (int) ' ');
2890 if (p == NULL)
2891 break;
2892 if (p < middle)
2893 {
2894 first = p;
2895 last = p;
2896 }
2897 else
2898 {
2899 last = p;
2900 break;
2901 }
2902 }
2903 // pick the better of the two
2904 char *ret;
2905 int f = (int) (middle - first);
2906 int l = (int) (last - middle);
2907 if ((first == last) || (f <= l))
2908 {
2909 *first = '\0';
2910 ret = first + 1;
2911 }
2912 else
2913 {
2914 *last = '\0';
2915 ret = last + 1;
2916 }
2917 return ret;
2918 }
2919