Automatic date update in version.in
[binutils-gdb.git] / gprofng / src / Print.cc
blobd6662df4745a790a3c5e98a19b8fba54c9d3f9bd
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2 Contributed by Oracle.
4 This file is part of GNU Binutils.
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.
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.
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. */
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 <libgen.h>
29 #include <unistd.h>
30 #include <stdio.h>
31 #include <fcntl.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
35 #include "util.h"
36 #include "Dbe.h"
37 #include "StringBuilder.h"
38 #include "DbeSession.h"
39 #include "DbeView.h"
40 #include "Settings.h"
41 #include "Print.h"
42 #include "DbeView.h"
43 #include "Experiment.h"
44 #include "MetricList.h"
45 #include "Module.h"
46 #include "Function.h"
47 #include "DataSpace.h"
48 #include "DataObject.h"
49 #include "FilterExp.h"
50 #include "LoadObject.h"
51 #include "Emsg.h"
52 #include "Table.h"
53 #include "DbeFile.h"
54 #include "CallStack.h"
56 int
57 er_print_common_display::open (Print_params *params)
59 pr_params = *params;
60 pr_params.name = dbe_strdup (params->name);
61 if (params->dest == DEST_PRINTER)
63 tmp_file = dbeSession->get_tmp_file_name (NTXT ("print"), false);
64 dbeSession->tmp_files->append (strdup (tmp_file));
65 out_file = fopen (tmp_file, NTXT ("w"));
67 else if (params->dest == DEST_OPEN_FILE)
68 out_file = pr_params.openfile;
69 else
70 out_file = fopen (pr_params.name, NTXT ("w"));
72 if (out_file == NULL)
73 // Failure
74 return 1;
75 return 0;
78 bool
79 er_print_common_display::print_output ()
81 char *sys_call;
82 bool ret = true;
83 if (pr_params.dest != DEST_OPEN_FILE)
84 fclose (out_file);
86 if (pr_params.dest == DEST_PRINTER)
88 if (streq ((char *) pr_params.name, NTXT ("")))
89 sys_call = dbe_sprintf ("(/usr/bin/lp -c -n%d %s) 2>/dev/null 1>&2",
90 pr_params.ncopies, tmp_file);
91 else
92 sys_call = dbe_sprintf ("(/usr/bin/lp -c -d%s -n%d %s) 2>/dev/null 1>&2",
93 pr_params.name, pr_params.ncopies, tmp_file);
94 if (system (sys_call) != 0)
95 ret = false;
96 unlink (tmp_file);
97 free (sys_call);
100 return ret;
103 // Return the report. If the report size is greater than max, return truncated report
104 // Allocates memory, so the caller should free this memory.
106 char *
107 er_print_common_display::get_output (int maxsize)
109 off_t max = (off_t) maxsize;
110 if (out_file != (FILE *) NULL)
112 fclose (out_file); // close tmp_file
113 out_file = (FILE *) NULL;
115 struct stat sbuf;
116 int st = stat (tmp_file, &sbuf);
117 if (st == 0)
119 off_t sz = sbuf.st_size;
120 if (sz > max)
121 return dbe_sprintf (GTXT ("Error: report is too long.\n"));
122 if (sz <= 0)
123 return dbe_sprintf (GTXT ("Error: empty temporary file: %s\n"),
124 tmp_file);
125 max = sz;
128 FILE *f = fopen (tmp_file, "r");
129 if (f == NULL)
130 return dbe_sprintf (GTXT ("Error: cannot open temporary file: %s\n"),
131 tmp_file);
132 char *report = (char *) malloc (max);
133 if (report)
135 if (1 != fread (report, max - 1, 1, f))
137 fclose (f);
138 free (report);
139 return dbe_sprintf (GTXT ("Error: cannot read temporary file: %s\n"),
140 tmp_file);
142 report[max - 1] = 0;
144 fclose (f);
145 return report;
148 void
149 er_print_common_display::header_dump (int exp_idx)
151 if (load && (exp_idx == exp_idx1))
153 load = false;
154 print_load_object (out_file);
156 print_header (dbeSession->get_exp (exp_idx), out_file);
159 char *
160 pr_load_objects (Vector<LoadObject*> *loadobjects, char *lead)
162 int size, i;
163 LoadObject *lo;
164 Emsg *m;
165 char *msg;
166 StringBuilder sb;
167 char *lo_name;
168 size = loadobjects->size ();
169 for (i = 0; i < size; i++)
171 lo = loadobjects->fetch (i);
172 lo_name = lo->get_name ();
173 if (lo_name != NULL)
175 size_t len = strlen (lo_name);
176 if (len > 7 && streq (lo_name + len - 7, NTXT (".class>")))
177 continue;
180 // print the segment name
181 sb.append (lead);
182 sb.append (NTXT (" "));
183 sb.append (lo->get_name ());
184 sb.append (NTXT (" ("));
185 sb.append (lo->get_pathname ());
186 sb.append (NTXT (")\n"));
188 // and any warnings
189 m = lo->fetch_warnings ();
190 if (m != NULL)
192 msg = pr_mesgs (m, NULL, NTXT (" "));
193 sb.append (msg);
194 free (msg);
197 return sb.toString ();
200 char *
201 pr_mesgs (Emsg *msg, const char *null_str, const char *lead)
203 Emsg *m;
204 StringBuilder sb;
205 if (msg == NULL)
206 return dbe_strdup (null_str);
207 for (m = msg; m; m = m->next)
209 sb.append (lead);
210 sb.append (m->get_msg ());
211 sb.append (NTXT ("\n"));
213 return sb.toString ();
216 void
217 print_load_object (FILE *out_file)
219 Vector<LoadObject*> *loadobjects = dbeSession->get_text_segments ();
220 char *msg = pr_load_objects (loadobjects, NTXT ("\t"));
221 fprintf (out_file, GTXT ("Load Object Coverage:\n"));
222 fprintf (out_file, NTXT ("%s"), msg);
223 fprintf (out_file,
224 "----------------------------------------------------------------\n");
225 free (msg);
226 delete loadobjects;
229 void
230 print_header (Experiment *exp, FILE *out_file)
232 fprintf (out_file, GTXT ("Experiment: %s\n"), exp->get_expt_name ());
233 char *msg = pr_mesgs (exp->fetch_notes (), NTXT (""), NTXT (""));
234 fprintf (out_file, NTXT ("%s"), msg);
235 free (msg);
237 msg = pr_mesgs (exp->fetch_errors (), GTXT ("No errors\n"), NTXT (""));
238 fprintf (out_file, NTXT ("%s"), msg);
239 free (msg);
241 msg = pr_mesgs (exp->fetch_warnings (), GTXT ("No warnings\n"), NTXT (""));
242 fprintf (out_file, NTXT ("%s"), msg);
243 free (msg);
245 msg = pr_mesgs (exp->fetch_comments (), NTXT (""), NTXT (""));
246 fprintf (out_file, NTXT ("%s"), msg);
247 free (msg);
249 msg = pr_mesgs (exp->fetch_pprocq (), NTXT (""), NTXT (""));
250 fprintf (out_file, NTXT ("%s"), msg);
251 free (msg);
254 void
255 get_width (Hist_data *data,
256 MetricList *metrics_list, Metric::HistMetric *hist_metric)
258 Metric *mitem;
259 Metric::HistMetric *hitem;
260 int last_column;
261 int index;
263 // find the last visible column.
264 last_column = 0;
265 Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
267 if (mitem->is_visible () || mitem->is_tvisible () || mitem->is_pvisible ())
268 last_column = index;
271 // find the width for each column.
273 Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
275 hitem = &hist_metric[index];
277 if (mitem->is_visible ())
279 if (mitem->get_vtype () == VT_LABEL)
281 if (index == last_column)
282 hitem->maxvalue_width = 0;
283 else
284 hitem->maxvalue_width = data->name_maxlen ();
285 // truncate names which will be too long
286 if (hitem->maxvalue_width > MAX_LEN - 3)
287 hitem->maxvalue_width = MAX_LEN - 3;
289 else if (mitem->get_vtype () == VT_ADDRESS)
291 hitem->maxvalue_width = data->value_maxlen (index);
292 if (hitem->maxvalue_width < 13)
293 hitem->maxvalue_width = 13;
295 else
296 hitem->maxvalue_width = data->value_maxlen (index);
298 else
299 hitem->maxvalue_width = 0;
301 if (mitem->is_tvisible ())
303 if (mitem->get_visbits () & VAL_RATIO)
304 hitem->maxtime_width = data->value_maxlen (index);
305 else
306 hitem->maxtime_width = data->time_maxlen (index,
307 dbeSession->get_clock (-1));
309 else
311 hitem->maxtime_width = 0;
316 void
317 get_format (char **fmt_int, char **fmt_real0, char **fmt_real1,
318 MetricList *metrics_list, Metric::HistMetric *hist_metric,
319 int nspace)
321 Metric *mitem;
322 Metric::HistMetric *hitem;
323 int index;
324 int visible, tvisible, pvisible;
325 size_t maxlen;
326 bool prev;
327 char numstr[MAX_LEN], pstr_int[MAX_LEN],
328 pstr_real0[MAX_LEN], pstr_real1[MAX_LEN];
330 // find the width for each column.
331 Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
333 hitem = &hist_metric[index];
334 visible = mitem->is_visible ();
335 tvisible = mitem->is_tvisible ();
336 pvisible = mitem->is_pvisible ();
337 *pstr_int = *pstr_real0 = *pstr_real1 = '\0';
339 // Get 'Show Value' format
340 const char *sign = (mitem->get_visbits () & VAL_DELTA) ? "+" : "";
341 if (visible)
343 maxlen = hitem->maxvalue_width;
344 switch (mitem->get_vtype2 ())
346 case VT_DOUBLE:
347 if (mitem->get_visbits () & VAL_RATIO)
349 snprintf (numstr, sizeof (numstr), "x %%#%d.0lf ",
350 (int) (maxlen - 3));
351 snprintf (pstr_real0, sizeof (pstr_real0), numstr, 0.0);
352 snprintf (pstr_real1, sizeof (pstr_real1), "x%%s%%%d.3lf ",
353 (int) maxlen);
355 else
357 snprintf (numstr, sizeof (numstr), "%%#%s%d.0lf ", sign,
358 (int) (maxlen - 3));
359 snprintf (pstr_real0, sizeof (pstr_real0), numstr, 0.0);
360 snprintf (pstr_real1, sizeof (pstr_real1), "%%s%%%s%d.3lf ",
361 sign, (int) maxlen);
363 break;
364 case VT_INT:
365 snprintf (pstr_int, sizeof (pstr_int), "%%%s%dd ", sign,
366 (int) maxlen);
367 break;
368 case VT_LLONG:
369 snprintf (pstr_int, sizeof (pstr_int), "%%%s%dlld ", sign,
370 (int) maxlen);
371 break;
372 case VT_ULLONG:
373 snprintf (pstr_int, sizeof (pstr_int), "%%%s%dllu ", sign,
374 (int) maxlen);
375 break;
376 case VT_ADDRESS:
377 if (maxlen <= 13)
379 snprintf (pstr_int, sizeof (pstr_int), "%%%dd:0x%%08x", 2);
381 else
383 snprintf (pstr_int, sizeof (pstr_int), "%%%dd:0x%%08x",
384 (int) (maxlen - 13));
386 break;
387 case VT_FLOAT:
388 snprintf (numstr, sizeof (numstr), "%%#%d.0f ",
389 (int) (maxlen - 3));
390 snprintf (pstr_real0, sizeof (pstr_real0), numstr, 0.0);
391 snprintf (pstr_real1, sizeof (pstr_real1), "%%%d.3f ",
392 (int) maxlen);
393 break;
394 case VT_SHORT:
395 snprintf (pstr_int, sizeof (pstr_int), "%%%dhu ", (int) maxlen);
396 break;
397 case VT_LABEL:
398 if (maxlen == 0) // last column
399 snprintf (pstr_int, sizeof (pstr_int), NTXT ("%%s%%s"));
400 else if (maxlen + nspace >= MAX_LEN - 3)
401 snprintf (pstr_int, sizeof (pstr_int), NTXT ("%%s%%-%d.%ds "),
402 MAX_LEN - 7, MAX_LEN - 7);
403 else
404 snprintf (pstr_int, sizeof (pstr_int), NTXT ("%%s%%-%ds "),
405 (int) (maxlen + nspace));
406 break;
407 default:
408 break;
412 // Get 'Show Time' format
413 if (tvisible)
415 maxlen = hitem->maxtime_width;
416 if (mitem->get_visbits () & VAL_RATIO)
418 snprintf (numstr, sizeof (numstr), " %%%s#%d.0lf ",
419 sign, (int) (maxlen - 3));
420 snprintf (pstr_real0, sizeof (pstr_real0), numstr, 0.0);
421 snprintf (pstr_real1, sizeof (pstr_real1), "%%s%%%s%d.3lf ",
422 sign, (int) maxlen);
424 else
426 snprintf (numstr, sizeof (numstr), "%%%s#%d.0lf ",
427 sign, (int) (maxlen - 3));
428 snprintf (pstr_real0, sizeof (pstr_real0), numstr, 0.0);
429 snprintf (pstr_real1, sizeof (pstr_real1), "%%s%%%s%d.3lf ",
430 sign, (int) maxlen);
434 // Copy format
435 if (*pstr_int)
436 fmt_int[index] = dbe_strdup (pstr_int);
437 else
438 fmt_int[index] = NULL;
440 if (*pstr_real0)
441 fmt_real0[index] = dbe_strdup (pstr_real0);
442 else
443 fmt_real0[index] = NULL;
445 if (*pstr_real1)
446 fmt_real1[index] = dbe_strdup (pstr_real1);
447 else
448 fmt_real1[index] = NULL;
450 // Set total width
451 hitem->width = 0;
452 if (hitem->maxvalue_width > 0)
454 hitem->width += hitem->maxvalue_width;
455 prev = true;
457 else
458 prev = false;
460 if (hitem->maxtime_width > 0)
462 if (prev)
463 hitem->width++;
464 hitem->width += hitem->maxtime_width;
465 prev = true;
468 if (pvisible)
470 if (prev)
471 hitem->width++;
472 hitem->width += 6; // adjust to change format from xx.yy%
474 if (visible || tvisible || pvisible)
475 mitem->legend_width (hitem, 2);
479 static char *
480 delTrailingBlanks (char *s)
482 for (int i = (int) strlen (s) - 1; i >= 0 && s[i] == ' '; i--)
483 s[i] = 0;
484 return s;
488 * Print the 3-line header with column heads for the metrics
489 * Return offset of "Name" column (this is needed to print Callers-Callees)
492 print_label (FILE *out_file, MetricList *metrics_list,
493 Metric::HistMetric *hist_metric, int space)
495 char line0[2 * MAX_LEN], line1[2 * MAX_LEN];
496 char line2[2 * MAX_LEN], line3[2 * MAX_LEN];
497 int name_offset = 0;
498 *line0 = *line1 = *line2 = *line3 = '\0';
499 Vector<Metric*> *mlist = metrics_list->get_items ();
500 for (int index = 0, mlist_sz = mlist->size (); index < mlist_sz; index++)
502 Metric *mitem = mlist->fetch (index);
503 if (mitem->is_visible () || mitem->is_tvisible () || mitem->is_pvisible ())
505 Metric::HistMetric *hitem = hist_metric + index;
506 char *fmt;
507 if (index > 0 && mitem->get_type () == Metric::ONAME)
509 fmt = NTXT (" %-*s");
510 name_offset = strlen (line1);
512 else
513 fmt = NTXT ("%-*s");
514 int width = (int) hitem->width;
515 size_t len = strlen (line1);
516 snprintf (line1 + len, sizeof (line1) - len, fmt, width,
517 hitem->legend1);
518 len = strlen (line2);
519 snprintf (line2 + len, sizeof (line2) - len, fmt, width,
520 hitem->legend2);
521 len = strlen (line3);
522 snprintf (line3 + len, sizeof (line3) - len, fmt, width,
523 hitem->legend3);
524 len = strlen (line0);
525 snprintf (line0 + len, sizeof (line0) - len, fmt, width,
526 mitem->legend ? mitem->legend : NTXT (""));
529 char *s = delTrailingBlanks (line0);
530 if (*s)
531 fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), s);
532 fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line1));
533 fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line2));
534 fprintf (out_file, NTXT ("%*s%s\n"), space, NTXT (""), delTrailingBlanks (line3));
535 return name_offset;
538 static int
539 print_one_visible (FILE *out_file, char *fmt_int, char *fmt_real0, char *fmt_real1,
540 TValue *value, int visbits)
542 int nc = 0;
543 switch (value->tag)
545 case VT_DOUBLE:
546 if (value->d == 0.0)
547 nc = fprintf (out_file, fmt_real0);
548 else
550 if (visbits & VAL_RATIO)
552 if (value->d > 99.999)
553 nc = fprintf (out_file, fmt_real1, NTXT (">"), 99.999);
554 else
555 nc = fprintf (out_file, fmt_real1, NTXT (" "), value->d);
557 else
558 nc = fprintf (out_file, fmt_real1, NTXT (""), value->d);
560 break;
561 case VT_INT:
562 nc = fprintf (out_file, fmt_int, value->i);
563 break;
564 case VT_LLONG:
565 case VT_ULLONG:
566 nc = fprintf (out_file, fmt_int, value->ll);
567 break;
568 case VT_ADDRESS:
569 nc = fprintf (out_file, fmt_int, ADDRESS_SEG (value->ll),
570 ADDRESS_OFF (value->ll));
571 break;
572 case VT_FLOAT:
573 if (value->f == 0.0)
574 nc = fprintf (out_file, fmt_real0);
575 else
576 nc = fprintf (out_file, fmt_real1, value->f);
577 break;
578 case VT_SHORT:
579 nc = fprintf (out_file, fmt_int, value->s);
580 break;
581 // ignoring the following cases (why?)
582 case VT_HRTIME:
583 case VT_LABEL:
584 case VT_OFFSET:
585 break;
587 return nc;
590 static int
591 print_one_tvisible (FILE *out_file, char *fmt_real0, char *fmt_real1,
592 TValue *value, int visbits, int clock)
594 int nc;
595 if (value->ll == 0LL)
596 nc = fprintf (out_file, fmt_real0);
597 else
599 if (visbits & VAL_RATIO)
601 if (value->d > 99.999)
602 nc = fprintf (out_file, fmt_real1, NTXT (">"), 99.999);
603 else
604 nc = fprintf (out_file, fmt_real1, NTXT (" "), value->d);
606 else
607 nc = fprintf (out_file, fmt_real1, "", 1.e-6 * value->ll / clock);
609 return nc;
612 static void
613 print_one (FILE *out_file, Hist_data *data, Hist_data::HistItem *item,
614 char **fmt_int, char **fmt_real0, char **fmt_real1,
615 MetricList *metrics_list, Metric::HistMetric *hist_metric,
616 char *mark, Histable::NameFormat nfmt)
618 Metric *mitem;
619 Metric::HistMetric *hitem;
620 int index, nc, np, i;
621 int visible, tvisible, pvisible;
622 TValue *value;
623 double percent;
625 if (item->type == Module::AT_EMPTY)
627 fprintf (out_file, nl);
628 return;
631 // set name_is_Total
632 int name_is_Total = 0;
634 Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
636 if (mitem->get_type () != Metric::ONAME)
637 continue;
638 name_is_Total = strcmp (item->obj->get_name (), GTXT ("<Total>")) == 0;
639 break;
642 np = 0;
643 Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
645 visible = mitem->is_visible ();
646 tvisible = mitem->is_tvisible ();
647 pvisible = mitem->is_pvisible ();
649 // alignment
650 for (i = 0; i < np; i++)
651 fputc (' ', out_file);
653 hitem = &hist_metric[index];
654 nc = 0;
655 if (tvisible)
657 value = &(item->value[index]);
658 nc = print_one_tvisible (out_file, fmt_real0[index], fmt_real1[index],
659 value, mitem->get_visbits (),
660 dbeSession->get_clock (-1));
662 else
663 nc = 0;
665 if (visible)
667 if (mitem->get_vtype () == VT_LABEL)
669 value = &(item->value[index]);
670 if (value->tag == VT_OFFSET)
671 nc += fprintf (out_file, fmt_int[index], mark,
672 ((DataObject*) (item->obj))->get_offset_name ());
673 else
674 nc += fprintf (out_file, fmt_int[index], mark,
675 item->obj->get_name (nfmt));
677 else if (name_is_Total &&
678 (strcmp (mitem->get_username (), "Block Covered %") == 0
679 || strcmp (mitem->get_username (), "Instr Covered %") == 0))
681 char stmp[128];
682 snprintf (stmp, sizeof (stmp), fmt_int[index], 0);
684 /* and now blank that '0' out */
685 for (int ii = 0; ii < 128; ii++)
687 if (stmp[ii] != '0')
688 continue;
689 stmp[ii] = ' ';
690 break;
692 nc += fprintf (out_file, stmp);
694 else
695 nc += print_one_visible (out_file, fmt_int[index], fmt_real0[index],
696 fmt_real1[index], &(item->value[index]),
697 mitem->get_visbits ());
700 if (pvisible)
702 percent = data->get_percentage (item->value[index].to_double (), index);
703 if (percent == 0.0)
704 // adjust to change format from xx.yy%
705 nc += fprintf (out_file, NTXT ("%#4.0f "), 0.);
706 else
707 // adjust format below to change format from xx.yy%
708 nc += fprintf (out_file, NTXT ("%6.2f "), (100.0 * percent));
710 np = (int) (hitem->width - nc);
712 fprintf (out_file, nl);
715 void
716 print_content (FILE *out_file, Hist_data *data,
717 char **fmt_int, char **fmt_real0, char **fmt_real1,
718 MetricList *metrics_list, Metric::HistMetric *hist_metric,
719 int limit, Histable::NameFormat nfmt)
721 // printing contents.
722 for (int i = 0; i < limit; i++)
724 Hist_data::HistItem *item = data->fetch (i);
725 print_one (out_file, data, item, fmt_int, fmt_real0, fmt_real1,
726 metrics_list, hist_metric, NTXT (" "), nfmt);
730 er_print_histogram::er_print_histogram (DbeView *_dbev, Hist_data *data,
731 MetricList *metrics_list,
732 Print_mode disp_type, int limit,
733 char *sort_name, Histable *sobj,
734 bool show_load, bool show_header)
736 hist_data = data;
737 mlist = metrics_list;
738 type = disp_type;
739 number_entries = limit;
740 sort_metric = sort_name;
741 sel_obj = sobj;
742 dbev = _dbev;
743 exp_idx1 = 0;
744 exp_idx2 = dbeSession->nexps () - 1;
745 load = show_load;
746 header = show_header;
749 void
750 er_print_histogram::dump_list (int limit)
752 Histable::NameFormat nfmt = dbev->get_name_format ();
753 StringBuilder sb;
754 char *title = NULL; // No title for some formats
755 enum PrintMode pm = dbev->get_printmode ();
757 // create a header line, except for delimiter-separated list output
758 if (pm != PM_DELIM_SEP_LIST)
760 if (hist_data->type == Histable::FUNCTION)
761 sb.append (GTXT ("Functions sorted by metric: "));
762 else if (hist_data->type == Histable::INSTR)
763 sb.append (GTXT ("PCs sorted by metric: "));
764 else if (hist_data->type == Histable::LINE)
765 sb.append (GTXT ("Lines sorted by metric: "));
766 else if (hist_data->type == Histable::DOBJECT)
767 sb.append (GTXT ("Dataobjects sorted by metric: "));
768 else
769 sb.append (GTXT ("Objects sorted by metric: "));
770 sb.append (sort_metric);
771 title = sb.toString ();
774 switch (pm)
776 case PM_TEXT:
778 Metric::HistMetric *hist_metric = hist_data->get_histmetrics ();
779 fprintf (out_file, NTXT ("%s\n\n"), title); //print title
780 hist_data->print_label (out_file, hist_metric, 0);
781 hist_data->print_content (out_file, hist_metric, limit);
782 fprintf (out_file, nl);
783 break;
785 case PM_HTML:
787 print_html_title (out_file, title);
788 print_html_label (out_file, mlist);
789 print_html_content (out_file, hist_data, mlist, limit, nfmt);
790 print_html_trailer (out_file);
791 break;
793 case PM_DELIM_SEP_LIST:
795 char delim = dbev->get_printdelimiter ();
796 print_delim_label (out_file, mlist, delim);
797 print_delim_content (out_file, hist_data, mlist, limit, nfmt, delim);
798 print_delim_trailer (out_file, delim);
799 break;
802 free (title);
805 void
806 er_print_histogram::dump_annotated_dataobjects (Vector<int> *marks,
807 int ithreshold)
809 Metric::HistMetric *hist_metric;
810 char **fmt_int, **fmt_real0, **fmt_real1;
811 int no_metrics = mlist->get_items ()->size ();
812 int name_index = -1;
813 Histable::NameFormat nfmt = dbev->get_name_format ();
814 if (!dbeSession->is_datamode_available ())
815 fprintf (out_file,
816 GTXT ("No dataspace information recorded in experiments\n\n"));
818 Hist_data *layout_data = dbev->get_data_space ()->get_layout_data (hist_data, marks, ithreshold);
820 for (int mind = 0; mind < no_metrics; mind++)
821 if (mlist->get_items ()->fetch (mind)->get_type () == Metric::ONAME)
822 name_index = mind;
824 fmt_int = new char*[no_metrics];
825 fmt_real0 = new char*[no_metrics];
826 fmt_real1 = new char*[no_metrics];
827 hist_metric = new Metric::HistMetric[no_metrics];
829 // use new layout_data to set metric format
830 get_width (hist_data, mlist, hist_metric);
831 get_format (fmt_int, fmt_real0, fmt_real1, mlist, hist_metric, 0);
832 snprintf (hist_metric[name_index].legend2, MAX_LEN, GTXT ("* +offset .element"));
833 print_label (out_file, mlist, hist_metric, 3);
834 fprintf (out_file, nl);
835 for (long i = 0; i < layout_data->size (); i++)
837 Hist_data::HistItem* item = layout_data->fetch (i);
838 if (marks->find (i) != -1)
839 fprintf (out_file, NTXT ("## "));
840 else
841 fprintf (out_file, NTXT (" "));
842 print_one (out_file, layout_data, item, fmt_int, fmt_real0, fmt_real1,
843 mlist, hist_metric, NTXT (" "), nfmt);
845 fprintf (out_file, nl);
847 // free format strings.
848 for (int i = 0; i < no_metrics; i++)
850 free (fmt_int[i]);
851 free (fmt_real0[i]);
852 free (fmt_real1[i]);
854 delete[] fmt_int;
855 delete[] fmt_real0;
856 delete[] fmt_real1;
857 delete[] hist_metric;
858 delete layout_data;
861 void
862 er_print_histogram::dump_detail (int limit)
864 Histable *obj;
865 Hist_data *current_data;
866 Histable::Type htype;
867 TValue *values;
868 double dvalue, percent;
869 MetricList *prop_mlist = new MetricList (mlist);
870 Metric *mitem;
871 int index, i;
872 size_t max_len, len, smax_len, slen;
873 Vaddr pc;
874 Module *module;
875 LoadObject *loadobject;
876 char *sname, *oname, *lname, *alias, *mangle;
877 char fmt_name[MAX_LEN];
878 char fmt_elem[MAX_LEN];
879 char fmt_real1[MAX_LEN], fmt_real2[MAX_LEN];
880 char fmt_int1[MAX_LEN], fmt_int2[MAX_LEN];
881 char fmt_long1[MAX_LEN], fmt_long2[MAX_LEN], fmt_long3[MAX_LEN];
882 char fmt_int0[MAX_LEN], fmt_long0[MAX_LEN];
883 char numstr[MAX_LEN];
885 Histable::NameFormat nfmt = dbev->get_name_format ();
887 // Check max. length of metrics names
888 max_len = smax_len = 0;
890 Vec_loop (Metric*, prop_mlist->get_items (), index, mitem)
892 mitem->set_vvisible (true);
893 if (mitem->get_vtype () == VT_LABEL)
894 continue;
896 if (mitem->get_subtype () != Metric::STATIC)
898 mitem->set_pvisible (true);
899 len = hist_data->value_maxlen (index);
900 if (max_len < len)
901 max_len = len;
902 slen = strlen (mitem->get_name ());
903 if (smax_len < slen)
904 smax_len = slen;
908 // now get the length of the other (non-performance-data) messages
909 if (hist_data->type == Histable::FUNCTION)
911 slen = strlen (GTXT ("Source File"));
912 if (smax_len < slen)
913 smax_len = slen;
914 slen = strlen (GTXT ("Object File"));
915 if (smax_len < slen)
916 smax_len = slen;
917 slen = strlen (GTXT ("Load Object"));
918 if (smax_len < slen)
919 smax_len = slen;
920 slen = strlen (GTXT ("Mangled Name"));
921 if (smax_len < slen)
922 smax_len = slen;
923 slen = strlen (GTXT ("Aliases"));
924 if (smax_len < slen)
925 smax_len = slen;
927 else if (hist_data->type == Histable::DOBJECT)
929 slen = strlen (GTXT ("Scope"));
930 if (smax_len < slen)
931 smax_len = slen;
932 slen = strlen (GTXT ("Type"));
933 if (smax_len < slen)
934 smax_len = slen;
935 slen = strlen (GTXT ("Member of"));
936 if (smax_len < slen)
937 smax_len = slen;
938 slen = strlen (GTXT ("Offset (bytes)"));
939 if (smax_len < slen)
940 smax_len = slen;
941 slen = strlen (GTXT ("Size (bytes)"));
942 if (smax_len < slen)
943 smax_len = slen;
944 slen = strlen (GTXT ("Elements"));
945 if (smax_len < slen)
946 smax_len = slen;
948 snprintf (fmt_name, sizeof (fmt_name), NTXT ("\t%%%ds: "), (int) smax_len);
949 snprintf (fmt_elem, sizeof (fmt_elem), NTXT ("\t%%%ds "), (int) smax_len);
950 snprintf (numstr, sizeof (numstr), "%%#%d.0lf ( %#1.0f %%%%%%%%)\n",
951 (int) (max_len - 3), 0.);
952 snprintf (fmt_real1, sizeof (fmt_real1), numstr, 0.0);
953 snprintf (fmt_real2, sizeof (fmt_real2), NTXT ("%%%d.3lf (%%5.1f%%%%)\n"),
954 (int) max_len);
955 snprintf (fmt_int0, sizeof (fmt_int0), NTXT ("%%%dd\n"), (int) max_len);
956 snprintf (numstr, sizeof (numstr), NTXT ("%%%dd ( %#1.0f %%%%%%%%)\n"),
957 (int) max_len, 0.);
958 snprintf (fmt_int1, sizeof (fmt_int1), numstr, 0);
959 snprintf (fmt_int2, sizeof (fmt_int2), NTXT ("%%%dd (%%5.1f%%%%)\n"),
960 (int) max_len);
961 snprintf (fmt_long0, sizeof (fmt_long0), NTXT ("%%%dllu\n"), (int) max_len);
962 snprintf (numstr, sizeof (numstr), NTXT ("%%%dd ( %#1.0f %%%%%%%%)\n"),
963 (int) max_len, 0.);
964 snprintf (fmt_long1, sizeof (fmt_long1), numstr, 0);
965 snprintf (fmt_long2, sizeof (fmt_long2), "%%%dllu (%%5.1f%%%%)\n",
966 (int) max_len);
967 snprintf (numstr, sizeof (numstr), NTXT ("\t%%%ds %%%%%dllu\n"),
968 (int) (smax_len + 1), (int) max_len);
969 snprintf (fmt_long3, sizeof (fmt_long3), numstr, GTXT ("Count:"));
970 snprintf (numstr, sizeof (numstr), "%%%dd ( %#1.0f %%%%%%%%) %%#%d.0lf\n",
971 (int) max_len, 0., (int) (max_len - 6));
973 // now loop over the objects
974 int num_printed_items = 0;
975 for (i = 0; i < hist_data->size (); i++)
977 if (hist_data->type == Histable::FUNCTION)
979 if (num_printed_items >= limit)
980 break;
981 obj = sel_obj ? sel_obj : hist_data->fetch (i)->obj;
982 htype = obj->get_type ();
984 // ask the view for all the data for the object
985 // xxxxx may be expensive to rescan all packets via get_hist_data()
986 current_data = dbev->get_hist_data (prop_mlist,
987 htype, 0, Hist_data::SELF, obj);
988 if (current_data->size () == 0)
989 continue;
990 values = current_data->fetch (0)->value;
992 else
994 obj = hist_data->fetch (i)->obj;
995 DataObject *dobj = (DataObject*) obj;
996 if (sel_obj)
998 // print selected item and its members
999 if (sel_obj != obj
1000 && (DataObject*) sel_obj != dobj->get_parent ())
1001 // not a match, advance to next item
1002 continue;
1004 else if (num_printed_items >= limit)
1005 break;
1006 htype = obj->get_type ();
1007 values = hist_data->fetch (i)->value;
1008 current_data = hist_data;
1011 if (num_printed_items)
1012 // if this isn't the first one, add a blank line
1013 fprintf (out_file, NTXT ("\n"));
1014 num_printed_items++;
1016 // Print full object name
1017 if (htype != Histable::DOBJECT)
1018 fprintf (out_file, NTXT ("%s\n"), obj->get_name (nfmt));
1019 else
1021 DataObject *dobj = (DataObject*) obj;
1022 if (!dobj->get_parent ())
1023 fprintf (out_file, NTXT ("%s\n"), obj->get_name (nfmt));
1024 else
1025 fprintf (out_file, NTXT (" %s\n"), obj->get_name (nfmt));
1028 Vec_loop (Metric*, prop_mlist->get_items (), index, mitem)
1030 if (mitem->get_vtype () == VT_LABEL)
1031 continue;
1032 if (mitem->get_subtype () == Metric::STATIC
1033 && htype == Histable::DOBJECT)
1034 continue;
1035 fprintf (out_file, fmt_name, mitem->get_name ());
1037 if (mitem->get_value_styles () & VAL_PERCENT)
1039 dvalue = values[index].to_double ();
1040 switch (mitem->get_vtype ())
1042 case VT_DOUBLE:
1043 if (dvalue == 0.0)
1044 fprintf (out_file, fmt_real1);
1045 else
1046 fprintf (out_file, fmt_real2, dvalue, 100.0
1047 * current_data->get_percentage (dvalue, index));
1048 break;
1049 case VT_INT:
1050 if (dvalue == 0.0)
1051 fprintf (out_file, fmt_int1);
1052 else
1053 fprintf (out_file, fmt_int2, (int) dvalue, 100.0
1054 * current_data->get_percentage (dvalue, index));
1055 break;
1056 case VT_LLONG:
1057 case VT_ULLONG:
1058 if (values[index].ll == 0LL)
1060 if (mitem->is_time_val ())
1062 fprintf (out_file, fmt_real1);
1063 fprintf (out_file, fmt_long3, 0LL);
1065 else
1066 fprintf (out_file, fmt_long1);
1068 else
1070 percent = 100.0 *
1071 current_data->get_percentage (dvalue, index);
1072 if (mitem->is_time_val ())
1074 dvalue /= 1.e+6 * dbeSession->get_clock (-1);
1075 fprintf (out_file, fmt_real2, dvalue, percent);
1076 fprintf (out_file, fmt_long3, values[index].ll);
1078 else
1079 fprintf (out_file, fmt_long2, values[index].ll,
1080 percent);
1082 break;
1083 default:
1084 break;
1087 else
1089 switch (mitem->get_vtype ())
1091 case VT_INT:
1092 fprintf (out_file, fmt_int0, values[index].i);
1093 break;
1094 case VT_LLONG:
1095 case VT_ULLONG:
1096 fprintf (out_file, fmt_long0, values[index].ll);
1097 break;
1098 case VT_ADDRESS:
1099 pc = values[index].ll;
1100 fprintf (out_file, NTXT ("%u:0x%08x\n"), ADDRESS_SEG (pc),
1101 ADDRESS_OFF (pc));
1102 break;
1103 case VT_DOUBLE:
1104 if (values[index].d == 0.0)
1105 fprintf (out_file, fmt_real1);
1106 else
1107 fprintf (out_file, "\t%*.3lf\n", (int) (max_len - 5), values[index].d);
1108 break;
1109 default:
1110 break;
1115 // now add the descriptive information about the object
1116 if (htype != Histable::DOBJECT)
1118 Function *func = (Function*) obj->convertto (Histable::FUNCTION);
1119 if (func && func->get_type () == Histable::FUNCTION)
1121 // Print the source/object/load-object files & aliases
1122 oname = lname = alias = NULL;
1123 sname = func->getDefSrcName ();
1124 mangle = func->get_mangled_name ();
1125 if (mangle && streq (func->get_name (), mangle))
1126 mangle = NULL;
1127 module = func->module;
1128 if (module)
1130 oname = module->get_name ();
1131 loadobject = module->loadobject;
1132 if (loadobject)
1134 lname = loadobject->get_pathname ();
1135 alias = loadobject->get_alias (func);
1139 if (htype == Histable::INSTR && dbeSession->is_datamode_available ())
1140 alias = ((DbeInstr*) obj)->get_descriptor ();
1142 fprintf (out_file, fmt_name, GTXT ("Source File"));
1143 if (sname)
1144 fprintf (out_file, NTXT ("%s"), sname);
1145 fprintf (out_file, NTXT ("\n"));
1147 fprintf (out_file, fmt_name, GTXT ("Object File"));
1148 if (oname)
1149 fprintf (out_file, NTXT ("%s"), oname);
1150 fprintf (out_file, NTXT ("\n"));
1152 fprintf (out_file, fmt_name, GTXT ("Load Object"));
1153 if (lname)
1154 fprintf (out_file, NTXT ("%s"), lname);
1155 fprintf (out_file, NTXT ("\n"));
1157 fprintf (out_file, fmt_name, GTXT ("Mangled Name"));
1158 if (mangle)
1159 fprintf (out_file, NTXT ("%s"), mangle);
1160 fprintf (out_file, NTXT ("\n"));
1161 fprintf (out_file, fmt_name, GTXT ("Aliases"));
1162 if (alias)
1163 fprintf (out_file, NTXT ("%s"), alias);
1164 fprintf (out_file, NTXT ("\n"));
1167 else
1169 // Print the dataobject information
1170 DataObject *dobj = (DataObject*) obj;
1171 Histable *scope = dobj->get_scope ();
1173 // print the scope
1174 fprintf (out_file, fmt_name, GTXT ("Scope"));
1175 if (!scope)
1176 fprintf (out_file, GTXT ("(Global)\n"));
1177 else switch (scope->get_type ())
1179 case Histable::FUNCTION:
1180 fprintf (out_file, NTXT ("%s(%s)\n"),
1181 ((Function*) scope)->module->get_name (),
1182 scope->get_name ());
1183 break;
1184 case Histable::LOADOBJECT:
1185 case Histable::MODULE:
1186 default:
1187 fprintf (out_file, NTXT ("%s\n"), scope->get_name ());
1190 // print the type name
1191 fprintf (out_file, fmt_name, GTXT ("Type"));
1192 if (dobj->get_typename ())
1193 fprintf (out_file, NTXT ("%s\n"), dobj->get_typename ());
1194 else
1195 fprintf (out_file, GTXT ("(Synthetic)\n"));
1197 // print the offset
1198 if (dobj->get_offset () != -1)
1200 if (dobj->get_parent ())
1202 fprintf (out_file, fmt_name, GTXT ("Member of"));
1203 fprintf (out_file, NTXT ("%s\n"), dobj->get_parent ()->get_name ());
1205 fprintf (out_file, fmt_name, GTXT ("Offset (bytes)"));
1206 fprintf (out_file, NTXT ("%lld\n"), (long long) dobj->get_offset ());
1208 // print the size
1209 if (dobj->get_size ())
1211 fprintf (out_file, fmt_name, GTXT ("Size (bytes)"));
1212 fprintf (out_file, NTXT ("%lld\n"), (long long) dobj->get_size ());
1215 if (hist_data->type == Histable::FUNCTION)
1216 delete current_data;
1218 if (num_printed_items == 0 && sel_obj)
1219 fprintf (stderr,
1220 GTXT ("Error: Specified item `%s' had no recorded metrics.\n"),
1221 sel_obj->get_name ());
1222 delete prop_mlist;
1225 static Metric::HistMetric *
1226 allocateHistMetric (int no_metrics)
1228 Metric::HistMetric *hist_metric = new Metric::HistMetric[no_metrics];
1229 for (int i = 0; i < no_metrics; i++)
1231 Metric::HistMetric *hm = &hist_metric[i];
1232 hm->init ();
1234 return hist_metric;
1237 void
1238 er_print_histogram::dump_gprof (int limit)
1240 StringBuilder sb;
1241 Histable *obj;
1242 Hist_data *callers;
1243 Hist_data *callees;
1244 Hist_data *center;
1246 int no_metrics = mlist->get_items ()->size ();
1247 Metric::HistMetric *hist_metric = allocateHistMetric (no_metrics);
1248 for (int i = 0; i < limit; i++)
1250 obj = sel_obj ? sel_obj : hist_data->fetch (i)->obj;
1251 callers = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1252 Hist_data::CALLERS, obj);
1253 callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1254 Hist_data::CALLEES, obj);
1255 center = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1256 Hist_data::SELF, obj);
1257 callers->update_max (hist_metric);
1258 callees->update_max (hist_metric);
1259 center->update_max (hist_metric);
1260 callers->update_legend_width (hist_metric);
1261 callers->print_label (out_file, hist_metric, 0);
1262 callers->print_content (out_file, hist_metric, callers->size ());
1264 if (center->size () > 0)
1266 center->update_total (callers->get_totals ());
1267 sb.setLength (0);
1268 center->print_row (&sb, 0, hist_metric, NTXT ("*"));
1269 sb.toFileLn (out_file);
1271 callees->print_content (out_file, hist_metric, callees->size ());
1272 fprintf (out_file, nl);
1273 delete callers;
1274 delete callees;
1275 delete center;
1277 delete[] hist_metric;
1280 // dump an annotated file
1281 void
1282 dump_anno_file (FILE *fp, Histable::Type type, Module *module, DbeView *dbev,
1283 MetricList *mlist, TValue *ftotal, const char *srcFile,
1284 Function *func, Vector<int> *marks, int threshold, int vis_bits,
1285 int src_visible, bool hex_visible, bool src_only)
1287 int no_metrics, lspace, mspace, tspace,
1288 remain, mindex, next_mark, hidx,
1289 index;
1290 Metric *mitem;
1291 char **fmt_int, **fmt_real0, **fmt_real1, buf[MAX_LEN];
1292 Hist_data::HistItem *item;
1294 SourceFile *srcContext = NULL;
1295 bool func_scope = dbev == NULL ? false : dbev->get_func_scope ();
1296 if (srcFile)
1298 srcContext = module->findSource (srcFile, false);
1299 if (srcContext == NULL)
1301 Vector<SourceFile*> *includes = module->includes;
1302 char *bname = get_basename (srcFile);
1303 for (int i = 0, sz = includes ? includes->size () : 0; i < sz; i++)
1305 SourceFile *sf = includes->fetch (i);
1306 if (streq (get_basename (sf->get_name ()), bname))
1308 srcContext = sf;
1309 break;
1313 if (func)
1314 func_scope = true;
1316 else if (func)
1317 srcContext = func->getDefSrc ();
1319 Hist_data *hdata = module->get_data (dbev, mlist, type, ftotal, srcContext,
1320 func, marks, threshold, vis_bits,
1321 src_visible, hex_visible,
1322 func_scope, src_only);
1324 if (hdata == NULL)
1325 return;
1327 // force the name metric to be invisible
1328 MetricList *nmlist = hdata->get_metric_list ();
1329 nmlist->find_metric (GTXT ("name"), Metric::STATIC)->clear_all_visbits ();
1330 no_metrics = nmlist->get_items ()->size ();
1331 fmt_int = new char*[no_metrics];
1332 fmt_real0 = new char*[no_metrics];
1333 fmt_real1 = new char*[no_metrics];
1334 Metric::HistMetric *hist_metric = hdata->get_histmetrics ();
1336 // lspace is for max line number that's inserted; use to set width
1337 int max_lineno = 0;
1338 Vec_loop (Hist_data::HistItem*, hdata, hidx, item)
1340 if (!item->obj)
1341 continue;
1342 if (item->obj->get_type () == Histable::LINE
1343 && ((DbeLine*) item->obj)->lineno > max_lineno)
1344 max_lineno = ((DbeLine*) item->obj)->lineno;
1345 else if (item->obj->get_type () == Histable::INSTR
1346 && ((DbeInstr*) item->obj)->lineno > max_lineno)
1347 max_lineno = ((DbeInstr*) item->obj)->lineno;
1350 lspace = snprintf (buf, sizeof (buf), NTXT ("%d"), max_lineno);
1352 // mspace is the space needed for all metrics, and the mark, if any
1353 mspace = 0;
1354 if (nmlist->get_items ()->size () > 0)
1356 mspace = 3; // mark "## "
1357 Vec_loop (Metric*, nmlist->get_items (), index, mitem)
1359 if (mitem->is_visible () || mitem->is_tvisible ()
1360 || mitem->is_pvisible ())
1361 mspace += (int) hist_metric[index].width;
1364 tspace = 0;
1365 remain = (mspace + lspace + 3) % 8; // " " before, ". " after line#
1366 if (remain)
1367 { // tab alignment
1368 tspace = 8 - remain;
1369 mspace += tspace;
1371 mindex = 0;
1372 next_mark = (mindex < marks->size ()) ? marks->fetch (mindex) : -1;
1374 // Print the header for this list
1375 SourceFile *sf = srcContext ? srcContext : module->getMainSrc ();
1376 char *src_name = sf->dbeFile->get_location_info ();
1377 DbeFile *df = module->dbeFile;
1378 if (df == NULL || (df->filetype & DbeFile::F_JAVACLASS) == 0)
1379 df = module->loadobject->dbeFile;
1380 char *lo_name = df->get_location_info ();
1381 char *dot_o_name = lo_name;
1382 if (module->dot_o_file)
1383 dot_o_name = module->dot_o_file->dbeFile->get_location_info ();
1384 fprintf (fp, GTXT ("Source file: %s\nObject file: %s\nLoad Object: %s\n\n"),
1385 src_name, dot_o_name, lo_name);
1387 // Print metric labels
1388 if (nmlist->get_items ()->size () != 0)
1389 print_label (fp, nmlist, hist_metric, 3);
1391 // determine the name metric (not printed as a metric, though)
1392 int lind = nmlist->get_listorder (GTXT ("name"), Metric::STATIC);
1394 // now loop over the data rows -- the lines in the annotated source/disasm,
1395 // including index lines, compiler commentary, etc.
1396 StringBuilder sb;
1397 Vec_loop (Hist_data::HistItem*, hdata, hidx, item)
1399 sb.setLength (0);
1400 if (item->type == Module::AT_DIS || item->type == Module::AT_QUOTE
1401 || item->type == Module::AT_SRC)
1403 // does this line get a high-metric mark?
1404 if (hidx == next_mark)
1406 sb.append (NTXT ("## "));
1407 mindex++;
1408 next_mark = (mindex < marks->size ()) ? marks->fetch (mindex) : -1;
1410 else
1411 sb.append (NTXT (" "));
1413 hdata->print_row (&sb, hidx, hist_metric, NTXT (" "));
1414 sb.toFile (fp);
1415 for (int i = sb.length (); i < mspace; i++)
1417 fputc (' ', fp);
1420 else
1421 // this line does not get any metrics; insert blanks in lieu of them
1422 for (int i = 0; i < mspace; i++)
1423 fputc (' ', fp);
1425 switch (item->type)
1427 case Module::AT_SRC_ONLY:
1428 if (item->obj == NULL)
1429 fprintf (fp, NTXT ("%*s. "), lspace + 1, "?");
1430 else
1431 fprintf (fp, "%*d. ", lspace + 1, ((DbeLine*) item->obj)->lineno);
1432 break;
1434 case Module::AT_SRC:
1435 fprintf (fp, "%*d. ", lspace + 1, ((DbeLine*) item->obj)->lineno);
1436 break;
1437 case Module::AT_FUNC:
1438 case Module::AT_QUOTE:
1439 fprintf (fp, NTXT ("%*c"), lspace + 3, ' ');
1440 break;
1441 case Module::AT_DIS:
1442 case Module::AT_DIS_ONLY:
1443 if (item->obj == NULL || ((DbeInstr*) item->obj)->lineno == -1)
1444 fprintf (fp, "%*c[%*s] ", lspace + 3, ' ', lspace, "?");
1445 else
1446 fprintf (fp, "%*c[%*d] ", lspace + 3, ' ', lspace,
1447 ((DbeInstr*) item->obj)->lineno);
1448 break;
1449 case Module::AT_COM:
1450 case Module::AT_EMPTY:
1451 break;
1454 if (item->value[lind].l == NULL)
1455 item->value[lind].l = dbe_strdup (GTXT ("INTERNAL ERROR: missing line text"));
1456 fprintf (fp, NTXT ("%s\n"), item->value[lind].l);
1458 delete[] fmt_int;
1459 delete[] fmt_real0;
1460 delete[] fmt_real1;
1461 delete hdata;
1464 void
1465 er_print_histogram::dump_annotated ()
1467 Vector<int> *marks = new Vector<int>;
1468 Function *anno_func = (Function *) sel_obj;
1469 Module *module = anno_func ? anno_func->module : NULL;
1471 if (hist_data->type == Histable::DOBJECT)
1472 dump_annotated_dataobjects (marks, number_entries); // threshold
1473 else if (number_entries == 0)
1474 // Annotated source
1475 dump_anno_file (out_file, Histable::LINE, module, dbev, mlist,
1476 hist_data->get_totals ()->value, NULL, anno_func, marks,
1477 dbev->get_thresh_src (), dbev->get_src_compcom (),
1478 dbev->get_src_visible (), dbev->get_hex_visible (), true);
1479 else
1480 // Annotated disassembly
1481 dump_anno_file (out_file, Histable::INSTR, module, dbev, mlist,
1482 hist_data->get_totals ()->value, NULL, anno_func, marks,
1483 dbev->get_thresh_dis (), dbev->get_dis_compcom (),
1484 dbev->get_src_visible (), dbev->get_hex_visible (), true);
1487 void
1488 er_print_histogram::data_dump ()
1490 int limit;
1491 if (hist_data->get_status () == Hist_data::SUCCESS)
1493 if (sort_metric[0] == '\n')
1494 { // csingle Callers-Callees entry
1495 sort_metric++;
1496 fprintf (out_file, NTXT ("%s\n\n"), sort_metric);
1498 else if (!sel_obj && type != MODE_LIST)
1500 if (hist_data->type == Histable::FUNCTION)
1501 fprintf (out_file,
1502 GTXT ("Functions sorted by metric: %s\n\n"), sort_metric);
1503 else if (hist_data->type == Histable::DOBJECT)
1504 fprintf (out_file, GTXT ("Dataobjects sorted by metric: %s\n\n"),
1505 sort_metric);
1506 else
1507 fprintf (out_file,
1508 GTXT ("Objects sorted by metric: %s\n\n"), sort_metric);
1510 limit = hist_data->size ();
1511 if ((number_entries > 0) && (number_entries < limit))
1512 limit = number_entries;
1514 switch (type)
1516 case MODE_LIST:
1517 dump_list (limit);
1518 break;
1519 case MODE_DETAIL:
1520 dump_detail (limit);
1521 break;
1522 case MODE_GPROF:
1523 dump_gprof (limit);
1524 break;
1525 case MODE_ANNOTATED:
1526 dump_annotated ();
1527 break;
1530 else
1531 fprintf (out_file, GTXT ("Get_Hist_data call failed %d\n"),
1532 (int) hist_data->get_status ());
1536 * Class er_print_ctree to print functions call tree
1538 er_print_ctree::er_print_ctree (DbeView *_dbev, Vector<Histable*> *_cstack,
1539 Histable *_sobj, int _limit)
1541 dbev = _dbev;
1542 cstack = _cstack;
1543 sobj = _sobj;
1544 limit = _limit;
1545 print_row = 0;
1546 exp_idx1 = 0;
1547 exp_idx2 = dbeSession->nexps () - 1;
1548 load = false;
1549 header = false;
1552 void
1553 er_print_ctree::data_dump ()
1555 StringBuilder sb;
1556 Hist_data::HistItem *total;
1557 sb.append (GTXT ("Functions Call Tree. Metric: "));
1558 char *s = dbev->getSort (MET_CALL_AGR);
1559 sb.append (s);
1560 free (s);
1561 sb.toFileLn (out_file);
1562 fprintf (out_file, NTXT ("\n"));
1563 mlist = dbev->get_metric_list (MET_CALL_AGR);
1565 // Change cstack: add sobj to the end of cstack
1566 cstack->append (sobj);
1567 Hist_data *center = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1568 Hist_data::SELF, cstack);
1569 Hist_data *callers = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1570 Hist_data::CALLERS, cstack);
1571 Hist_data *callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1572 Hist_data::CALLEES, cstack);
1574 // Restore cstack
1575 int last = cstack->size () - 1;
1576 cstack->remove (last);
1578 // Prepare formats
1579 int no_metrics = mlist->size ();
1581 // calculate max. width using data from callers, callees, center
1582 hist_metric = allocateHistMetric (no_metrics);
1583 callers->update_max (hist_metric);
1584 callees->update_max (hist_metric);
1585 center->update_max (hist_metric);
1586 callers->update_legend_width (hist_metric);
1587 callers->print_label (out_file, hist_metric, 0); // returns Name column offset
1589 print_row = 0;
1590 // Pass real total to print_children()
1591 total = center->get_totals ();
1592 print_children (center, 0, sobj, NTXT (" "), total);
1594 // Free memory
1595 cstack->reset ();
1596 delete callers;
1597 delete callees;
1598 delete center;
1599 delete[] hist_metric;
1603 * Recursive method print_children prints Call Tree elements.
1605 void
1606 er_print_ctree::print_children (Hist_data *data, int index, Histable *my_obj,
1607 char * prefix, Hist_data::HistItem *total)
1609 StringBuilder buf;
1610 const char *P0 = "+-";
1611 const char *P2 = " |";
1612 const char *P1 = " ";
1614 // If limit exceeded - return
1615 ++print_row;
1616 if (limit > 0 && print_row > limit)
1617 return;
1619 if (my_obj == NULL)
1620 return; // should never happen
1622 // Prepare prefix
1623 buf.append (prefix);
1624 if (buf.endsWith (P2))
1626 int len = buf.length () - 1;
1627 buf.setLength (len);
1629 buf.append (P0);
1631 // Change cstack: add my_obj to the end of cstack
1632 cstack->append (my_obj);
1634 // Print current node info
1635 char * my_prefix = buf.toString ();
1637 // Replace parent's total values with real total values
1638 data->update_total (total); // Needed to to calculate percentage only
1639 buf.setLength (0);
1640 data->print_row (&buf, index, hist_metric, my_prefix);
1641 buf.toFileLn (out_file);
1642 free (my_prefix);
1644 // Get children
1645 Hist_data *callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1646 Hist_data::CALLEES, cstack);
1647 int nc = callees->size ();
1648 if (nc > 0)
1650 // Print children
1651 Hist_data::HistItem *item;
1652 Histable *ch_obj;
1653 char *ch_prefix;
1654 buf.setLength (0);
1655 buf.append (prefix);
1656 buf.append (P2);
1657 ch_prefix = buf.toString ();
1658 for (int i = 0; i < nc - 1; i++)
1660 item = callees->fetch (i);
1661 ch_obj = item->obj;
1662 print_children (callees, i, ch_obj, ch_prefix, total);
1664 free (ch_prefix);
1665 buf.setLength (0);
1666 buf.append (prefix);
1667 buf.append (P1);
1668 ch_prefix = buf.toString ();
1669 item = callees->fetch (nc - 1);
1670 ch_obj = item->obj;
1671 print_children (callees, nc - 1, ch_obj, ch_prefix, total);
1672 free (ch_prefix);
1675 // Restore cstack
1676 int last = cstack->size () - 1;
1677 cstack->remove (last);
1678 delete callees;
1679 return;
1682 er_print_gprof::er_print_gprof (DbeView *_dbev, Vector<Histable*> *_cstack)
1684 dbev = _dbev;
1685 cstack = _cstack;
1686 exp_idx1 = 0;
1687 exp_idx2 = dbeSession->nexps () - 1;
1688 load = false;
1689 header = false;
1692 void
1693 er_print_gprof::data_dump ()
1695 StringBuilder sb;
1696 sb.append (GTXT ("Callers and callees sorted by metric: "));
1697 char *s = dbev->getSort (MET_CALL);
1698 sb.append (s);
1699 free (s);
1700 sb.toFileLn (out_file);
1701 fprintf (out_file, NTXT ("\n"));
1703 MetricList *mlist = dbev->get_metric_list (MET_CALL);
1704 Hist_data *center = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1705 Hist_data::SELF, cstack);
1706 Hist_data *callers = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1707 Hist_data::CALLERS, cstack);
1708 Hist_data *callees = dbev->get_hist_data (mlist, Histable::FUNCTION, 0,
1709 Hist_data::CALLEES, cstack);
1711 mlist = center->get_metric_list ();
1712 int no_metrics = mlist->get_items ()->size ();
1714 // update max. width for callers/callees/center function item
1715 Metric::HistMetric *hist_metric = allocateHistMetric (no_metrics);
1716 callers->update_max (hist_metric);
1717 callees->update_max (hist_metric);
1718 center->update_max (hist_metric);
1720 callers->update_legend_width (hist_metric);
1721 int name_offset = callers->print_label (out_file, hist_metric, 0); // returns Name column offset
1722 // Print Callers
1723 sb.setLength (0);
1724 for (int i = 0; i < name_offset; i++)
1725 sb.append (NTXT ("="));
1726 if (name_offset > 0)
1727 sb.append (NTXT (" "));
1728 char *line1 = sb.toString ();
1729 char *line2;
1730 if (callers->size () > 0)
1731 line2 = GTXT ("Callers");
1732 else
1733 line2 = GTXT ("No Callers");
1734 fprintf (out_file, NTXT ("%s%s\n"), line1, line2);
1735 callers->print_content (out_file, hist_metric, callers->size ());
1737 // Print Stack Fragment
1738 line2 = GTXT ("Stack Fragment");
1739 fprintf (out_file, NTXT ("\n%s%s\n"), line1, line2);
1741 for (long i = 0, last = cstack->size () - 1; i <= last; ++i)
1743 sb.setLength (0);
1744 if (i == last && center->size () > 0)
1746 center->update_total (callers->get_totals ()); // Needed to to calculate percentage only
1747 center->print_row (&sb, center->size () - 1, hist_metric, NTXT (" "));
1749 else
1751 for (int n = name_offset; n > 0; n--)
1752 sb.append (NTXT (" "));
1753 if (name_offset > 0)
1754 sb.append (NTXT (" "));
1755 sb.append (cstack->get (i)->get_name ());
1757 sb.toFileLn (out_file);
1760 // Print Callees
1761 if (callees->size () > 0)
1762 line2 = GTXT ("Callees");
1763 else
1764 line2 = GTXT ("No Callees");
1765 fprintf (out_file, NTXT ("\n%s%s\n"), line1, line2);
1766 callees->print_content (out_file, hist_metric, callees->size ());
1767 fprintf (out_file, nl);
1768 free (line1);
1769 delete callers;
1770 delete callees;
1771 delete center;
1772 delete[] hist_metric;
1775 er_print_leaklist::er_print_leaklist (DbeView *_dbev, bool show_leak,
1776 bool show_alloca, int _limit)
1778 dbev = _dbev;
1779 leak = show_leak;
1780 alloca = show_alloca;
1781 limit = _limit;
1784 // Output routine for leak list only
1785 void
1786 er_print_leaklist::data_dump ()
1788 CStack_data *lam;
1789 CStack_data::CStack_item *lae;
1790 int index;
1791 if (!dbeSession->is_leaklist_available ())
1792 fprintf (out_file, GTXT ("No leak or allocation information recorded in experiments\n\n"));
1794 MetricList *origmlist = dbev->get_metric_list (MET_NORMAL);
1795 if (leak)
1797 // make a copy of the metric list, and set metrics for leaks
1798 MetricList *nmlist = new MetricList (origmlist);
1799 nmlist->set_metrics ("e.heapleakbytes:e.heapleakcnt:name", true,
1800 dbev->get_derived_metrics ());
1802 // now make a compacted version of it to get the right indices
1803 MetricList *mlist = new MetricList (nmlist);
1804 delete nmlist;
1806 // fetch the callstack data
1807 lam = dbev->get_cstack_data (mlist);
1809 // now print it
1810 if (lam && lam->size () != 0)
1812 fprintf (out_file, GTXT ("Summary Results: Distinct Leaks = %d, Total Instances = %lld, Total Bytes Leaked = %lld\n\n"),
1813 (int) lam->size (), lam->total->value[1].ll,
1814 lam->total->value[0].ll);
1816 Vec_loop (CStack_data::CStack_item*, lam->cstack_items, index, lae)
1818 fprintf (out_file,
1819 GTXT ("Leak #%d, Instances = %lld, Bytes Leaked = %lld\n"),
1820 index + 1, lae->value[1].ll, lae->value[0].ll);
1821 if (lae->stack != NULL)
1822 for (int i = lae->stack->size () - 1; i >= 0; i--)
1824 DbeInstr *instr = lae->stack->fetch (i);
1825 fprintf (out_file, NTXT (" %s\n"), instr->get_name ());
1827 fprintf (out_file, NTXT ("\n"));
1828 if (index + 1 == limit) break;
1831 else
1832 fprintf (out_file, GTXT ("No leak information\n\n"));
1833 delete lam;
1834 delete mlist;
1837 if (alloca)
1839 // make a copy of the metric list, and set metrics for leaks
1840 MetricList *nmlist = new MetricList (origmlist);
1841 nmlist->set_metrics ("e.heapallocbytes:e.heapalloccnt:name",
1842 true, dbev->get_derived_metrics ());
1844 // now make a compacted version of it to get the right indices
1845 MetricList *mlist = new MetricList (nmlist);
1846 delete nmlist;
1848 // fetch the callstack data
1849 lam = dbev->get_cstack_data (mlist);
1851 // now print it
1852 if (lam && lam->size () != 0)
1854 fprintf (out_file, GTXT ("Summary Results: Distinct Allocations = %d, Total Instances = %lld, Total Bytes Allocated = %lld\n\n"),
1855 (int) lam->size (), lam->total->value[1].ll,
1856 lam->total->value[0].ll);
1857 Vec_loop (CStack_data::CStack_item*, lam->cstack_items, index, lae)
1859 fprintf (out_file, GTXT ("Allocation #%d, Instances = %lld, Bytes Allocated = %lld\n"),
1860 index + 1, lae->value[1].ll, lae->value[0].ll);
1861 if (lae->stack != NULL)
1862 for (int i = lae->stack->size () - 1; i >= 0; i--)
1864 DbeInstr *instr = lae->stack->fetch (i);
1865 fprintf (out_file, NTXT (" %s\n"), instr->get_name ());
1867 fprintf (out_file, NTXT ("\n"));
1868 if (index + 1 == limit) break;
1871 else
1872 fprintf (out_file, GTXT ("No allocation information\n\n"));
1873 delete lam;
1874 delete mlist;
1878 er_print_heapactivity::er_print_heapactivity (DbeView *_dbev,
1879 Histable::Type _type,
1880 bool _printStat, int _limit)
1882 dbev = _dbev;
1883 type = _type;
1884 printStat = _printStat;
1885 limit = _limit;
1888 void
1889 er_print_heapactivity::printCallStacks (Hist_data *hist_data)
1891 Hist_data::HistItem *hi;
1892 HeapData *hData;
1893 long stackId;
1894 int size = hist_data->size ();
1895 if (limit > 0 && limit < size)
1896 size = limit;
1898 Histable::NameFormat fmt = dbev->get_name_format ();
1899 for (int i = 0; i < size; i++)
1901 hi = hist_data->fetch (i);
1902 hData = (HeapData*) hi->obj;
1903 stackId = hData->id;
1904 if (i != 0)
1905 fprintf (out_file, NTXT ("\n"));
1907 fprintf (out_file, NTXT ("%s\n"), hData->get_name (fmt));
1908 if (hData->getAllocCnt () > 0)
1910 fprintf (out_file, GTXT ("Instances = %d "),
1911 (int) (hData->getAllocCnt ()));
1912 fprintf (out_file, GTXT ("Bytes Allocated = %lld\n"),
1913 (long long) hData->getAllocBytes ());
1916 if (hData->getLeakCnt () > 0)
1918 fprintf (out_file, GTXT ("Instances = %d "),
1919 (int) (hData->getLeakCnt ()));
1920 fprintf (out_file, GTXT ("Bytes Leaked = %lld\n"),
1921 (long long) hData->getLeakBytes ());
1924 // There is no stack trace for <Total>
1925 if (i == 0)
1926 continue;
1928 // LIBRARY VISIBILITY pass extra argument if necessary to get hide stack
1929 Vector<Histable*> *instrs = CallStack::getStackPCs ((void *) stackId);
1930 if (instrs != NULL)
1932 int stSize = instrs->size ();
1933 for (int j = 0; j < stSize; j++)
1935 Histable *instr = instrs->fetch (j);
1936 if (instr != NULL)
1937 fprintf (out_file, NTXT (" %s\n"), instr->get_name ());
1939 delete instrs;
1944 void
1945 er_print_heapactivity::printStatistics (Hist_data *hist_data)
1947 Hist_data::HistItem *hi;
1948 HeapData *hDataTotal;
1949 hi = hist_data->fetch (0);
1950 hDataTotal = (HeapData*) hi->obj;
1951 Vector<hrtime_t> *pTimestamps;
1952 if (hDataTotal->getPeakMemUsage () > 0)
1954 fprintf (out_file, GTXT ("\nProcess With Highest Peak Memory Usage\n"));
1955 fprintf (out_file,
1956 "-------------------------------------------------------\n");
1957 fprintf (out_file, GTXT ("Heap size bytes %lld\n"),
1958 (long long) hDataTotal->getPeakMemUsage ());
1959 fprintf (out_file, GTXT ("Experiment Id %d\n"),
1960 (int) (hDataTotal->getUserExpId ()));
1961 fprintf (out_file, GTXT ("Process Id %d\n"),
1962 (int) (hDataTotal->getPid ()));
1963 pTimestamps = hDataTotal->getPeakTimestamps ();
1964 if (pTimestamps != NULL)
1965 for (int i = 0; i < pTimestamps->size (); i++)
1966 fprintf (out_file,
1967 GTXT ("Time of peak %.3f (secs.)\n"),
1968 (double) (pTimestamps->fetch (i) / (double) NANOSEC));
1971 if (hDataTotal->getAllocCnt () > 0)
1973 fprintf (out_file, GTXT ("\nMemory Allocations Statistics\n"));
1974 fprintf (out_file,
1975 GTXT ("Allocation Size Range Allocations \n"));
1976 fprintf (out_file,
1977 "-------------------------------------------------------\n");
1978 if (hDataTotal->getA0KB1KBCnt () > 0)
1979 fprintf (out_file, NTXT (" 0KB - 1KB %d\n"),
1980 hDataTotal->getA0KB1KBCnt ());
1981 if (hDataTotal->getA1KB8KBCnt () > 0)
1982 fprintf (out_file, NTXT (" 1KB - 8KB %d\n"),
1983 hDataTotal->getA1KB8KBCnt ());
1984 if (hDataTotal->getA8KB32KBCnt () > 0)
1985 fprintf (out_file, NTXT (" 8KB - 32KB %d\n"),
1986 hDataTotal->getA8KB32KBCnt ());
1987 if (hDataTotal->getA32KB128KBCnt () > 0)
1988 fprintf (out_file, NTXT (" 32KB - 128KB %d\n"),
1989 hDataTotal->getA32KB128KBCnt ());
1990 if (hDataTotal->getA128KB256KBCnt () > 0)
1991 fprintf (out_file, NTXT (" 128KB - 256KB %d\n"),
1992 hDataTotal->getA128KB256KBCnt ());
1993 if (hDataTotal->getA256KB512KBCnt () > 0)
1994 fprintf (out_file, NTXT (" 256KB - 512KB %d\n"),
1995 hDataTotal->getA256KB512KBCnt ());
1996 if (hDataTotal->getA512KB1000KBCnt () > 0)
1997 fprintf (out_file, NTXT (" 512KB - 1000KB %d\n"),
1998 hDataTotal->getA512KB1000KBCnt ());
1999 if (hDataTotal->getA1000KB10MBCnt () > 0)
2000 fprintf (out_file, NTXT (" 1000KB - 10MB %d\n"),
2001 hDataTotal->getA1000KB10MBCnt ());
2002 if (hDataTotal->getA10MB100MBCnt () > 0)
2003 fprintf (out_file, NTXT (" 10MB - 100MB %d\n"),
2004 hDataTotal->getA10MB100MBCnt ());
2005 if (hDataTotal->getA100MB1GBCnt () > 0)
2006 fprintf (out_file, NTXT (" 100MB - 1GB %d\n"),
2007 hDataTotal->getA100MB1GBCnt ());
2008 if (hDataTotal->getA1GB10GBCnt () > 0)
2009 fprintf (out_file, NTXT (" 1GB - 10GB %d\n"),
2010 hDataTotal->getA1GB10GBCnt ());
2011 if (hDataTotal->getA10GB100GBCnt () > 0)
2012 fprintf (out_file, NTXT (" 10GB - 100GB %d\n"),
2013 hDataTotal->getA10GB100GBCnt ());
2014 if (hDataTotal->getA100GB1TBCnt () > 0)
2015 fprintf (out_file, NTXT (" 100GB - 1TB %d\n"),
2016 hDataTotal->getA100GB1TBCnt ());
2017 if (hDataTotal->getA1TB10TBCnt () > 0)
2018 fprintf (out_file, NTXT (" 1TB - 10TB %d\n"),
2019 hDataTotal->getA1TB10TBCnt ());
2020 fprintf (out_file, GTXT ("\nSmallest allocation bytes %lld\n"),
2021 (long long) hDataTotal->getASmallestBytes ());
2022 fprintf (out_file, GTXT ("Largest allocation bytes %lld\n"),
2023 (long long) hDataTotal->getALargestBytes ());
2024 fprintf (out_file, GTXT ("Total allocations %d\n"),
2025 hDataTotal->getAllocCnt ());
2026 fprintf (out_file, GTXT ("Total bytes %lld\n"),
2027 (long long) hDataTotal->getAllocBytes ());
2030 if (hDataTotal->getLeakCnt () > 0)
2032 fprintf (out_file, GTXT ("\nMemory Leaks Statistics\n"));
2033 fprintf (out_file,
2034 GTXT ("Leak Size Range Leaks \n"));
2035 fprintf (out_file,
2036 "-------------------------------------------------------\n");
2037 if (hDataTotal->getL0KB1KBCnt () > 0)
2038 fprintf (out_file, NTXT (" 0KB - 1KB %d\n"),
2039 hDataTotal->getL0KB1KBCnt ());
2040 if (hDataTotal->getL1KB8KBCnt () > 0)
2041 fprintf (out_file, NTXT (" 1KB - 8KB %d\n"),
2042 hDataTotal->getL1KB8KBCnt ());
2043 if (hDataTotal->getL8KB32KBCnt () > 0)
2044 fprintf (out_file, NTXT (" 8KB - 32KB %d\n"),
2045 hDataTotal->getL8KB32KBCnt ());
2046 if (hDataTotal->getL32KB128KBCnt () > 0)
2047 fprintf (out_file, NTXT (" 32KB - 128KB %d\n"),
2048 hDataTotal->getL32KB128KBCnt ());
2049 if (hDataTotal->getL128KB256KBCnt () > 0)
2050 fprintf (out_file, NTXT (" 128KB - 256KB %d\n"),
2051 hDataTotal->getL128KB256KBCnt ());
2052 if (hDataTotal->getL256KB512KBCnt () > 0)
2053 fprintf (out_file, NTXT (" 256KB - 512KB %d\n"),
2054 hDataTotal->getL256KB512KBCnt ());
2055 if (hDataTotal->getL512KB1000KBCnt () > 0)
2056 fprintf (out_file, NTXT (" 512KB - 1000KB %d\n"),
2057 hDataTotal->getL512KB1000KBCnt ());
2058 if (hDataTotal->getL1000KB10MBCnt () > 0)
2059 fprintf (out_file, NTXT (" 1000KB - 10MB %d\n"),
2060 hDataTotal->getL1000KB10MBCnt ());
2061 if (hDataTotal->getL10MB100MBCnt () > 0)
2062 fprintf (out_file, NTXT (" 10MB - 100MB %d\n"),
2063 hDataTotal->getL10MB100MBCnt ());
2064 if (hDataTotal->getL100MB1GBCnt () > 0)
2065 fprintf (out_file, NTXT (" 100MB - 1GB %d\n"),
2066 hDataTotal->getL100MB1GBCnt ());
2067 if (hDataTotal->getL1GB10GBCnt () > 0)
2068 fprintf (out_file, NTXT (" 1GB - 10GB %d\n"),
2069 hDataTotal->getL1GB10GBCnt ());
2070 if (hDataTotal->getL10GB100GBCnt () > 0)
2071 fprintf (out_file, NTXT (" 10GB - 100GB %d\n"),
2072 hDataTotal->getL10GB100GBCnt ());
2073 if (hDataTotal->getL100GB1TBCnt () > 0)
2074 fprintf (out_file, NTXT (" 100GB - 1TB %d\n"),
2075 hDataTotal->getL100GB1TBCnt ());
2076 if (hDataTotal->getL1TB10TBCnt () > 0)
2077 fprintf (out_file, NTXT (" 1TB - 10TB %d\n"),
2078 hDataTotal->getL1TB10TBCnt ());
2079 fprintf (out_file, GTXT ("\nSmallest leaked bytes %lld\n"),
2080 (long long) hDataTotal->getLSmallestBytes ());
2081 fprintf (out_file, GTXT ("Largest leaked bytes %lld\n"),
2082 (long long) hDataTotal->getLLargestBytes ());
2083 fprintf (out_file, GTXT ("Total leaked %d \n"),
2084 hDataTotal->getLeakCnt ());
2085 fprintf (out_file, GTXT ("Total bytes %lld\n"),
2086 (long long) hDataTotal->getLeakBytes ());
2088 fprintf (out_file, NTXT ("\n"));
2091 void
2092 er_print_heapactivity::data_dump ()
2094 // get the list of heap events from DbeView
2095 int numExps = dbeSession->nexps ();
2096 if (!numExps)
2098 fprintf (out_file,
2099 GTXT ("There is no heap event information in the experiments\n"));
2100 return;
2102 MetricList *mlist = dbev->get_metric_list (MET_HEAP);
2103 Hist_data *hist_data;
2104 hist_data = dbev->get_hist_data (mlist, type, 0, Hist_data::ALL);
2105 if (printStat)
2106 printStatistics (hist_data);
2107 else
2108 printCallStacks (hist_data);
2111 er_print_ioactivity::er_print_ioactivity (DbeView *_dbev, Histable::Type _type,
2112 bool _printStat, int _limit)
2114 dbev = _dbev;
2115 type = _type;
2116 printStat = _printStat;
2117 limit = _limit;
2120 void
2121 er_print_ioactivity::printCallStacks (Hist_data *hist_data)
2123 Hist_data::HistItem *hi;
2124 FileData *fData;
2125 long stackId;
2126 int size = hist_data->size ();
2127 if (limit > 0 && limit < size)
2128 size = limit;
2130 for (int i = 0; i < size; i++)
2132 hi = hist_data->fetch (i);
2133 fData = (FileData*) hi->obj;
2134 stackId = fData->id;
2135 if (i != 0)
2136 fprintf (out_file, NTXT ("\n"));
2137 fprintf (out_file, NTXT ("%s\n"), fData->getFileName ());
2138 if (fData->getWriteCnt () > 0)
2140 fprintf (out_file, GTXT ("Write Time=%.6f (secs.) "),
2141 (double) (fData->getWriteTime () / (double) NANOSEC));
2142 fprintf (out_file, GTXT ("Write Bytes=%lld "),
2143 (long long) fData->getWriteBytes ());
2144 fprintf (out_file, GTXT ("Write Count=%d\n"),
2145 (int) (fData->getWriteCnt ()));
2147 if (fData->getReadCnt () > 0)
2149 fprintf (out_file, GTXT ("Read Time=%.6f (secs.) "),
2150 (double) (fData->getReadTime () / (double) NANOSEC));
2151 fprintf (out_file, GTXT ("Read Bytes=%lld "),
2152 (long long) fData->getReadBytes ());
2153 fprintf (out_file, GTXT ("Read Count=%d\n"),
2154 (int) fData->getReadCnt ());
2156 if (fData->getOtherCnt () > 0)
2158 fprintf (out_file, GTXT ("Other I/O Time=%.6f (secs.) "),
2159 (double) (fData->getOtherTime () / (double) NANOSEC));
2160 fprintf (out_file, GTXT ("Other I/O Count=%d\n"),
2161 (int) (fData->getOtherCnt ()));
2163 if (fData->getErrorCnt () > 0)
2165 fprintf (out_file, GTXT ("I/O Error Time=%.6f (secs.) "),
2166 (double) (fData->getErrorTime () / (double) NANOSEC));
2167 fprintf (out_file, GTXT ("I/O Error Count=%d\n"),
2168 (int) (fData->getErrorCnt ()));
2171 // There is no stack trace for <Total>
2172 if (i == 0)
2173 continue;
2175 // LIBRARY VISIBILITY pass extra argument if necessary to get hide stack
2176 Vector<Histable*> *instrs = CallStack::getStackPCs ((void *) stackId);
2177 if (instrs != NULL)
2179 int stSize = instrs->size ();
2180 for (int j = 0; j < stSize; j++)
2182 Histable *instr = instrs->fetch (j);
2183 if (instr != NULL)
2184 fprintf (out_file, " %s\n", instr->get_name ());
2186 delete instrs;
2191 void
2192 er_print_ioactivity::printStatistics (Hist_data *hist_data)
2194 Hist_data::HistItem *hi;
2195 FileData *fDataTotal;
2197 hi = hist_data->fetch (0);
2198 fDataTotal = (FileData*) hi->obj;
2200 if (fDataTotal->getWriteCnt () > 0)
2202 fprintf (out_file,
2203 GTXT ("\nWrite Statistics\n"));
2204 fprintf (out_file,
2205 GTXT ("I/O Size Range Write Calls \n"));
2206 fprintf (out_file,
2207 "-------------------------------------------------------\n");
2208 if (fDataTotal->getW0KB1KBCnt () > 0)
2209 fprintf (out_file, NTXT (" 0KB - 1KB %d\n"),
2210 fDataTotal->getW0KB1KBCnt ());
2211 if (fDataTotal->getW1KB8KBCnt () > 0)
2212 fprintf (out_file, NTXT (" 1KB - 8KB %d\n"),
2213 fDataTotal->getW1KB8KBCnt ());
2214 if (fDataTotal->getW8KB32KBCnt () > 0)
2215 fprintf (out_file, NTXT (" 8KB - 32KB %d\n"),
2216 fDataTotal->getW8KB32KBCnt ());
2217 if (fDataTotal->getW32KB128KBCnt () > 0)
2218 fprintf (out_file, NTXT (" 32KB - 128KB %d\n"),
2219 fDataTotal->getW32KB128KBCnt ());
2220 if (fDataTotal->getW128KB256KBCnt () > 0)
2221 fprintf (out_file, NTXT (" 128KB - 256KB %d\n"),
2222 fDataTotal->getW128KB256KBCnt ());
2223 if (fDataTotal->getW256KB512KBCnt () > 0)
2224 fprintf (out_file, NTXT (" 256KB - 512KB %d\n"),
2225 fDataTotal->getW256KB512KBCnt ());
2226 if (fDataTotal->getW512KB1000KBCnt () > 0)
2227 fprintf (out_file, NTXT (" 512KB - 1000KB %d\n"),
2228 fDataTotal->getW512KB1000KBCnt ());
2229 if (fDataTotal->getW1000KB10MBCnt () > 0)
2230 fprintf (out_file, NTXT (" 1000KB - 10MB %d\n"),
2231 fDataTotal->getW1000KB10MBCnt ());
2232 if (fDataTotal->getW10MB100MBCnt () > 0)
2233 fprintf (out_file, NTXT (" 10MB - 100MB %d\n"),
2234 fDataTotal->getW10MB100MBCnt ());
2235 if (fDataTotal->getW100MB1GBCnt () > 0)
2236 fprintf (out_file, NTXT (" 100MB - 1GB %d\n"),
2237 fDataTotal->getW100MB1GBCnt ());
2238 if (fDataTotal->getW1GB10GBCnt () > 0)
2239 fprintf (out_file, NTXT (" 1GB - 10GB %d\n"),
2240 fDataTotal->getW1GB10GBCnt ());
2241 if (fDataTotal->getW10GB100GBCnt () > 0)
2242 fprintf (out_file, NTXT (" 10GB - 100GB %d\n"),
2243 fDataTotal->getW10GB100GBCnt ());
2244 if (fDataTotal->getW100GB1TBCnt () > 0)
2245 fprintf (out_file, NTXT (" 100GB - 1TB %d\n"),
2246 fDataTotal->getW100GB1TBCnt ());
2247 if (fDataTotal->getW1TB10TBCnt () > 0)
2248 fprintf (out_file, NTXT (" 1TB - 10TB %d\n"),
2249 fDataTotal->getW1TB10TBCnt ());
2250 fprintf (out_file,
2251 GTXT ("\nLongest write %.6f (secs.)\n"),
2252 (double) (fDataTotal->getWSlowestBytes () / (double) NANOSEC));
2253 fprintf (out_file, GTXT ("Smallest write bytes %lld\n"),
2254 (long long) fDataTotal->getWSmallestBytes ());
2255 fprintf (out_file, GTXT ("Largest write bytes %lld\n"),
2256 (long long) fDataTotal->getWLargestBytes ());
2257 fprintf (out_file,
2258 GTXT ("Total time %.6f (secs.)\n"),
2259 (double) (fDataTotal->getWriteTime () / (double) NANOSEC));
2260 fprintf (out_file, GTXT ("Total calls %d\n"),
2261 fDataTotal->getWriteCnt ());
2262 fprintf (out_file, GTXT ("Total bytes %lld\n"),
2263 (long long) fDataTotal->getWriteBytes ());
2266 if (fDataTotal->getReadCnt () > 0)
2268 fprintf (out_file,
2269 GTXT ("\nRead Statistics\n"));
2270 fprintf (out_file,
2271 GTXT ("I/O Size Range Read Calls \n"));
2272 fprintf (out_file,
2273 "------------------------------------------------------\n");
2274 if (fDataTotal->getR0KB1KBCnt () > 0)
2275 fprintf (out_file, NTXT (" 0KB - 1KB %d\n"),
2276 fDataTotal->getR0KB1KBCnt ());
2277 if (fDataTotal->getR1KB8KBCnt () > 0)
2278 fprintf (out_file, NTXT (" 1KB - 8KB %d\n"),
2279 fDataTotal->getR1KB8KBCnt ());
2280 if (fDataTotal->getR8KB32KBCnt () > 0)
2281 fprintf (out_file, NTXT (" 8KB - 32KB %d\n"),
2282 fDataTotal->getR8KB32KBCnt ());
2283 if (fDataTotal->getR32KB128KBCnt () > 0)
2284 fprintf (out_file, NTXT (" 32KB - 128KB %d\n"),
2285 fDataTotal->getR32KB128KBCnt ());
2286 if (fDataTotal->getR128KB256KBCnt () > 0)
2287 fprintf (out_file, NTXT (" 128KB - 256KB %d\n"),
2288 fDataTotal->getR128KB256KBCnt ());
2289 if (fDataTotal->getR256KB512KBCnt () > 0)
2290 fprintf (out_file, NTXT (" 256KB - 512KB %d\n"),
2291 fDataTotal->getR256KB512KBCnt ());
2292 if (fDataTotal->getR512KB1000KBCnt () > 0)
2293 fprintf (out_file, NTXT (" 512KB - 1000KB %d\n"),
2294 fDataTotal->getR512KB1000KBCnt ());
2295 if (fDataTotal->getR1000KB10MBCnt () > 0)
2296 fprintf (out_file, NTXT (" 1000KB - 10MB %d\n"),
2297 fDataTotal->getR1000KB10MBCnt ());
2298 if (fDataTotal->getR10MB100MBCnt () > 0)
2299 fprintf (out_file, NTXT (" 10MB - 100MB %d\n"),
2300 fDataTotal->getR10MB100MBCnt ());
2301 if (fDataTotal->getR100MB1GBCnt () > 0)
2302 fprintf (out_file, NTXT (" 100MB - 1GB %d\n"),
2303 fDataTotal->getR100MB1GBCnt ());
2304 if (fDataTotal->getR1GB10GBCnt () > 0)
2305 fprintf (out_file, NTXT (" 1GB - 10GB %d\n"),
2306 fDataTotal->getR1GB10GBCnt ());
2307 if (fDataTotal->getR10GB100GBCnt () > 0)
2308 fprintf (out_file, NTXT (" 10GB - 100GB %d\n"),
2309 fDataTotal->getR10GB100GBCnt ());
2310 if (fDataTotal->getR100GB1TBCnt () > 0)
2311 fprintf (out_file, NTXT (" 100GB - 1TB %d\n"),
2312 fDataTotal->getR100GB1TBCnt ());
2313 if (fDataTotal->getR1TB10TBCnt () > 0)
2314 fprintf (out_file, NTXT (" 1TB - 10TB %d\n"),
2315 fDataTotal->getR1TB10TBCnt ());
2316 fprintf (out_file,
2317 GTXT ("\nLongest time %.6f (secs.)\n"),
2318 (double) (fDataTotal->getRSlowestBytes () / (double) NANOSEC));
2319 fprintf (out_file, GTXT ("Smallest read bytes %lld\n"),
2320 (long long) fDataTotal->getRSmallestBytes ());
2321 fprintf (out_file, GTXT ("Largest read bytes %lld\n"),
2322 (long long) fDataTotal->getRLargestBytes ());
2323 fprintf (out_file,
2324 GTXT ("Total time %.6f (secs.)\n"),
2325 (double) (fDataTotal->getReadTime () / (double) NANOSEC));
2326 fprintf (out_file, GTXT ("Total calls %d\n"),
2327 fDataTotal->getReadCnt ());
2328 fprintf (out_file, GTXT ("Total bytes %lld\n"),
2329 (long long) fDataTotal->getReadBytes ());
2332 if (fDataTotal->getOtherCnt () > 0)
2334 fprintf (out_file, GTXT ("\nOther I/O Statistics\n"));
2335 fprintf (out_file,
2336 "-----------------------------------------------------\n");
2337 fprintf (out_file,
2338 GTXT ("Total time %.6f (secs.)\n"),
2339 (double) (fDataTotal->getOtherTime () / (double) NANOSEC));
2340 fprintf (out_file, GTXT ("Total calls %d \n"),
2341 fDataTotal->getOtherCnt ());
2343 if (fDataTotal->getErrorCnt () > 0)
2345 fprintf (out_file, GTXT ("\nI/O Error Statistics\n"));
2346 fprintf (out_file,
2347 "-----------------------------------------------------\n");
2348 fprintf (out_file,
2349 GTXT ("Total time %.6f (secs.)\n"),
2350 (double) (fDataTotal->getErrorTime () / (double) NANOSEC));
2351 fprintf (out_file, GTXT ("Total calls %d \n"),
2352 fDataTotal->getErrorCnt ());
2354 fprintf (out_file, NTXT ("\n"));
2357 void
2358 er_print_ioactivity::data_dump ()
2360 // get the list of io events from DbeView
2361 int numExps = dbeSession->nexps ();
2362 if (!numExps)
2364 fprintf (out_file,
2365 GTXT ("There is no IO event information in the experiments\n"));
2366 return;
2369 MetricList *mlist = dbev->get_metric_list (MET_IO);
2370 Hist_data *hist_data = dbev->get_hist_data (mlist, type, 0, Hist_data::ALL);
2371 if (type == Histable::IOCALLSTACK)
2372 printCallStacks (hist_data);
2373 else if (printStat)
2374 printStatistics (hist_data);
2375 else
2377 Metric::HistMetric *hist_metric = hist_data->get_histmetrics ();
2378 hist_data->print_label (out_file, hist_metric, 0);
2379 hist_data->print_content (out_file, hist_metric, limit);
2380 fprintf (out_file, nl);
2384 er_print_experiment::er_print_experiment (DbeView *_dbev, int bgn_idx,
2385 int end_idx, bool show_load,
2386 bool show_header, bool show_stat,
2387 bool show_over, bool show_odetail)
2389 dbev = _dbev;
2390 exp_idx1 = bgn_idx;
2391 exp_idx2 = end_idx;
2392 load = show_load;
2393 header = show_header;
2394 stat = show_stat;
2395 over = show_over;
2396 odetail = show_odetail;
2399 void
2400 er_print_experiment::data_dump ()
2402 int index, maxlen;
2404 maxlen = 0;
2406 if (stat)
2408 snprintf (fmt1, sizeof (fmt1), NTXT ("%%50s"));
2409 if (exp_idx2 > exp_idx1)
2411 statistics_sum (maxlen);
2412 fprintf (out_file, nl);
2415 for (index = exp_idx1; index <= exp_idx2; index++)
2416 statistics_dump (index, maxlen);
2418 else if (over)
2420 snprintf (fmt1, sizeof (fmt1), NTXT ("%%30s"));
2421 if (exp_idx2 > exp_idx1)
2423 overview_sum (maxlen);
2424 fprintf (out_file, nl);
2427 for (index = exp_idx1; index <= exp_idx2; index++)
2428 overview_dump (index, maxlen);
2430 else if (header)
2431 for (index = exp_idx1; index <= exp_idx2; index++)
2433 if (index != exp_idx1)
2434 fprintf (out_file,
2435 "----------------------------------------------------------------\n");
2436 header_dump (index);
2440 void
2441 er_print_experiment::overview_sum (int &maxlen)
2443 int index;
2444 Ovw_data *sum_data = new Ovw_data ();
2445 for (index = exp_idx1; index <= exp_idx2; index++)
2447 Ovw_data *ovw_data = dbev->get_ovw_data (index);
2448 if (ovw_data == NULL)
2449 continue;
2450 sum_data->sum (ovw_data);
2451 delete ovw_data;
2454 fprintf (out_file, GTXT ("<Sum across selected experiments>"));
2455 fprintf (out_file, nl);
2456 overview_summary (sum_data, maxlen);
2457 fprintf (out_file, nl);
2458 delete sum_data;
2461 void
2462 er_print_experiment::overview_dump (int exp_idx, int &maxlen)
2464 Ovw_data *ovw_data;
2465 Ovw_data::Ovw_item ovw_item_labels;
2466 Ovw_data::Ovw_item ovw_item;
2467 int index;
2468 int size;
2470 ovw_data = dbev->get_ovw_data (exp_idx);
2471 if (ovw_data == NULL)
2472 return;
2473 if (pr_params.header)
2474 header_dump (exp_idx);
2475 else if (odetail)
2476 fprintf (out_file, GTXT ("Experiment: %s\n"),
2477 dbeSession->get_exp (exp_idx)->get_expt_name ());
2479 overview_summary (ovw_data, maxlen);
2480 if (!odetail)
2482 delete ovw_data;
2483 return;
2486 //Get the collection params for the sample selection and display them.
2487 fprintf (out_file, NTXT ("\n\n"));
2488 fprintf (out_file, fmt1, GTXT ("Individual samples"));
2489 fprintf (out_file, NTXT ("\n\n"));
2491 size = ovw_data->size ();
2492 ovw_item_labels = ovw_data->get_labels ();
2494 for (index = 0; index < size; index++)
2496 ovw_item = ovw_data->fetch (index);
2497 fprintf (out_file, fmt1, GTXT ("Sample Number"));
2498 fprintf (out_file, NTXT (": %d\n\n"), ovw_item.number);
2499 overview_item (&ovw_item, &ovw_item_labels);
2500 fprintf (out_file, nl);
2503 delete ovw_data;
2506 void
2507 er_print_experiment::overview_summary (Ovw_data *ovw_data, int &maxlen)
2509 char buf[128];
2510 int len;
2511 Ovw_data::Ovw_item totals;
2512 Ovw_data::Ovw_item ovw_item_labels;
2513 totals = ovw_data->get_totals ();
2514 len = snprintf (buf, sizeof (buf), "%.3lf", tstodouble (totals.total.t));
2515 if (maxlen < len)
2516 maxlen = len;
2517 snprintf (buf, sizeof (buf), NTXT ("%%#%d.0lf ( %#1.0f %%%%%%%%)"),
2518 maxlen - 3, 0.);
2519 snprintf (fmt2, sizeof (fmt2), NTXT ("%%%d.3lf"), maxlen);
2520 snprintf (fmt3, sizeof (fmt3), buf, 0.0);
2521 snprintf (fmt4, sizeof (fmt4), NTXT ("%%%d.3lf (%%5.1f%%%%)"), maxlen);
2522 fprintf (out_file, fmt1, GTXT ("Aggregated statistics for selected samples"));
2523 fprintf (out_file, NTXT ("\n\n"));
2525 ovw_item_labels = ovw_data->get_labels ();
2526 overview_item (&totals, &ovw_item_labels);
2529 void
2530 er_print_experiment::overview_item (Ovw_data::Ovw_item *ovw_item,
2531 Ovw_data::Ovw_item *ovw_item_labels)
2533 double start, end, total_value;
2534 int index, size;
2535 timestruc_t total_time = {0, 0};
2537 start = tstodouble (ovw_item->start);
2538 end = tstodouble (ovw_item->end);
2540 fprintf (out_file, fmt1, GTXT ("Start Label"));
2541 fprintf (out_file, NTXT (": "));
2542 fprintf (out_file, NTXT ("%s"), ovw_item->start_label);
2543 fprintf (out_file, nl);
2544 fprintf (out_file, fmt1, GTXT ("End Label"));
2545 fprintf (out_file, NTXT (": %s\n"), ovw_item->end_label);
2547 fprintf (out_file, fmt1, GTXT ("Start Time (sec.)"));
2548 fprintf (out_file, NTXT (": "));
2549 if (start == -1.0)
2550 fprintf (out_file, GTXT ("N/A"));
2551 else
2552 fprintf (out_file, fmt2, start);
2553 fprintf (out_file, nl);
2554 fprintf (out_file, fmt1, GTXT ("End Time (sec.)"));
2555 fprintf (out_file, NTXT (": "));
2556 if (end == -1.0)
2557 fprintf (out_file, GTXT ("N/A"));
2558 else
2559 fprintf (out_file, fmt2, end);
2560 fprintf (out_file, nl);
2561 fprintf (out_file, fmt1, GTXT ("Duration (sec.)"));
2562 fprintf (out_file, NTXT (": "));
2563 fprintf (out_file, fmt2, tstodouble (ovw_item->duration));
2564 fprintf (out_file, NTXT ("\n"));
2566 size = ovw_item->size;
2567 for (index = 0; index < size; index++)
2568 tsadd (&total_time, &ovw_item->values[index].t);
2570 total_value = tstodouble (total_time);
2571 fprintf (out_file, fmt1, GTXT ("Total Thread Time (sec.)"));
2572 fprintf (out_file, NTXT (": "));
2573 fprintf (out_file, fmt2, tstodouble (ovw_item->tlwp));
2574 fprintf (out_file, NTXT ("\n"));
2575 fprintf (out_file, fmt1, GTXT ("Average number of Threads"));
2576 fprintf (out_file, NTXT (": "));
2577 if (tstodouble (ovw_item->duration) != 0)
2578 fprintf (out_file, fmt2, ovw_item->nlwp);
2579 else
2580 fprintf (out_file, GTXT ("N/A"));
2581 fprintf (out_file, NTXT ("\n\n"));
2582 fprintf (out_file, fmt1, GTXT ("Process Times (sec.)"));
2583 fprintf (out_file, NTXT (":\n"));
2584 for (index = 1; index < size; index++)
2586 overview_value (&ovw_item_labels->values[index], ovw_item_labels->type,
2587 total_value);
2588 overview_value (&ovw_item->values[index], ovw_item->type,
2589 total_value);
2590 fprintf (out_file, NTXT ("\n"));
2594 void
2595 er_print_experiment::overview_value (Value *value, ValueTag value_tag,
2596 double total_value)
2598 double dvalue;
2599 switch (value_tag)
2601 case VT_LABEL:
2602 fprintf (out_file, fmt1, value->l);
2603 fprintf (out_file, NTXT (": "));
2604 break;
2605 case VT_HRTIME:
2606 dvalue = tstodouble (value->t);
2607 if (dvalue == 0.0)
2608 fprintf (out_file, fmt3, 0., 0.);
2609 else
2610 fprintf (out_file, fmt4, dvalue, 100.0 * dvalue / total_value);
2611 break;
2612 case VT_INT:
2613 fprintf (out_file, NTXT ("%d"), value->i);
2614 break;
2615 default:
2616 fprintf (out_file, fmt3);
2620 void
2621 er_print_experiment::statistics_sum (int &maxlen)
2623 int index;
2624 int size, len;
2625 Stats_data *sum_data = new Stats_data ();
2626 for (index = exp_idx1; index <= exp_idx2; index++)
2628 Stats_data *stats_data = dbev->get_stats_data (index);
2629 if (stats_data == NULL)
2630 continue;
2631 sum_data->sum (stats_data);
2632 delete stats_data;
2635 // get the maximum width of values
2636 size = sum_data->size ();
2637 for (index = 0; index < size; index++)
2639 len = (int) sum_data->fetch (index).value.get_len ();
2640 if (maxlen < len)
2641 maxlen = len;
2644 // print overview average
2645 overview_sum (maxlen);
2647 // print statistics data
2648 snprintf (fmt2, sizeof (fmt2), NTXT (": %%%ds\n"), maxlen);
2649 statistics_item (sum_data);
2650 delete sum_data;
2653 void
2654 er_print_experiment::statistics_dump (int exp_idx, int &maxlen)
2656 Stats_data *stats_data;
2657 int index;
2658 int size, len;
2659 stats_data = dbev->get_stats_data (exp_idx);
2660 if (stats_data == NULL)
2661 return;
2662 if (pr_params.header)
2664 header_dump (exp_idx);
2665 fprintf (out_file, nl);
2667 else
2668 fprintf (out_file, GTXT ("Experiment: %s\n"),
2669 dbeSession->get_exp (exp_idx)->get_expt_name ());
2671 // get the maximum width of values
2672 size = stats_data->size ();
2673 for (index = 0; index < size; index++)
2675 len = (int) stats_data->fetch (index).value.get_len ();
2676 if (maxlen < len)
2677 maxlen = len;
2680 // print overview average
2681 overview_dump (exp_idx, maxlen);
2682 fprintf (out_file, nl);
2684 // print statistics data
2685 snprintf (fmt2, sizeof (fmt2), NTXT (": %%%ds\n"), maxlen);
2686 statistics_item (stats_data);
2687 delete stats_data;
2690 void
2691 er_print_experiment::statistics_item (Stats_data *stats_data)
2693 int size, index;
2694 Stats_data::Stats_item stats_item;
2695 char buf[256];
2696 size = stats_data->size ();
2697 for (index = 0; index < size; index++)
2699 stats_item = stats_data->fetch (index);
2700 fprintf (out_file, fmt1, stats_item.label);
2701 fprintf (out_file, fmt2, stats_item.value.to_str (buf, sizeof (buf)));
2703 fprintf (out_file, nl);
2706 // Print annotated source or disassembly -- called by er_print only
2707 void
2708 print_anno_file (char *name, const char *sel, const char *srcFile,
2709 bool isDisasm, FILE *dis_file, FILE *inp_file, FILE *out_file,
2710 DbeView *dbev, bool xdefault)
2712 Histable *obj;
2713 Function *func;
2714 Module *module;
2715 Vector<int> *marks;
2716 Hist_data *hist_data;
2717 char *errstr;
2718 int index;
2719 SourceFile *fitem;
2720 int threshold;
2721 int compcom_bits;
2722 int src_visible;
2723 bool hex_visible;
2724 bool srcmetrics_visible;
2726 if ((name == NULL) || (strlen (name) == 0))
2728 fprintf (stderr, GTXT ("Error: No function or file has been specified.\n"));
2729 return;
2732 // find the function from the name
2733 if (!dbeSession->find_obj (dis_file, inp_file, obj, name, sel,
2734 Histable::FUNCTION, xdefault))
2735 return;
2737 if (obj != NULL)
2739 // source or disassembly for <Total>, <Unknown>, or @plt
2740 if (obj->get_type () != Histable::FUNCTION)
2742 fprintf (stderr,
2743 GTXT ("Error: %s is not a real function; no source or disassembly available.\n"),
2744 name);
2745 return;
2748 func = (Function *) obj;
2749 if (func->flags & FUNC_FLAG_SIMULATED)
2751 fprintf (stderr,
2752 GTXT ("Error: %s is not a real function; no source or disassembly available.\n"),
2753 name);
2754 return;
2756 else if (dbev != NULL && isDisasm)
2757 dbev->set_func_scope (true);
2759 // function found, set module
2760 module = func->module;
2761 int ix = module->loadobject->seg_idx;
2762 if (dbev->get_lo_expand (ix) == LIBEX_HIDE)
2764 char *lo_name = module->loadobject->get_name ();
2765 fprintf (stderr,
2766 GTXT ("Error: No source or disassembly available for hidden object %s.\n"),
2767 lo_name);
2768 return;
2771 if (srcFile)
2773 Vector<SourceFile*> *sources = func->get_sources ();
2774 bool found = false;
2775 if (sources == NULL)
2777 fitem = func->getDefSrc ();
2778 found = (func->line_first > 0)
2779 && strcmp (basename (srcFile),
2780 basename (fitem->get_name ())) == 0;
2782 else
2784 Vec_loop (SourceFile*, sources, index, fitem)
2786 if (strcmp (basename (srcFile), basename (fitem->get_name ())) == 0)
2788 found = true;
2789 break;
2793 if (!found)
2795 fprintf (stderr, GTXT ("Error: Source file context %s does not contribute to function `%s'.\n"),
2796 srcFile, name);
2797 return;
2801 else
2803 // function not found
2804 if (sel && strrchr (sel, ':'))
2806 // 'sel' was "@seg_num:address" or "file_name:address"
2807 fprintf (stderr,
2808 GTXT ("Error: No function with given name `%s %s' found.\n"),
2809 name, sel);
2810 return;
2812 // search for a file of that name
2813 if (!dbeSession->find_obj (dis_file, inp_file, obj, name, sel,
2814 Histable::MODULE, xdefault))
2815 return;
2817 if (obj == NULL)
2818 { // neither function nor file found
2819 fprintf (stderr, GTXT ("Error: No function or file with given name `%s' found.\n"),
2820 name);
2821 return;
2824 func = NULL;
2825 module = (Module *) obj;
2826 int ix = module->loadobject->seg_idx;
2827 if (dbev->get_lo_expand (ix) == LIBEX_HIDE)
2829 char *lo_name = module->loadobject->get_name ();
2830 fprintf (stderr, GTXT ("Error: No source or disassembly available for hidden object %s.\n"),
2831 lo_name);
2832 return;
2834 if (name)
2835 srcFile = name;
2838 if (module == NULL || module->get_name () == NULL)
2840 fprintf (stderr, GTXT ("Error: Object name not recorded in experiment\n"));
2841 return;
2843 module->read_stabs ();
2845 if (!isDisasm && (module->file_name == NULL
2846 || (module->flags & MOD_FLAG_UNKNOWN) != 0
2847 || *module->file_name == 0))
2849 fprintf (stderr, GTXT ("Error: Source location not recorded in experiment\n"));
2850 return;
2853 MetricList *metric_list = dbev->get_metric_list (MET_NORMAL);
2854 int sort_ref_index = metric_list->get_sort_ref_index ();
2855 if (isDisasm)
2856 metric_list->set_sort_ref_index (-1);
2858 // Ask DbeView to generate function-level data
2859 // MSI: I think this is used only to get totals to compute percentages
2860 hist_data = dbev->get_hist_data (metric_list, Histable::FUNCTION, 0,
2861 Hist_data::ALL);
2862 MetricList *nmlist = hist_data->get_metric_list ();
2863 metric_list->set_sort_ref_index (sort_ref_index);
2864 if (nmlist->get_items ()->size () != 0
2865 && hist_data->get_status () != Hist_data::SUCCESS)
2867 errstr = DbeView::status_str (DbeView::DBEVIEW_NO_DATA);
2868 if (errstr)
2870 fprintf (stderr, GTXT ("Error: %s\n"), errstr);
2871 free (errstr);
2873 return;
2876 marks = new Vector<int>;
2877 if (isDisasm)
2879 threshold = dbev->get_thresh_dis ();
2880 compcom_bits = dbev->get_dis_compcom ();
2881 src_visible = dbev->get_src_visible ();
2882 hex_visible = dbev->get_hex_visible ();
2883 srcmetrics_visible = dbev->get_srcmetric_visible ();
2885 else
2887 threshold = dbev->get_thresh_src ();
2888 compcom_bits = dbev->get_src_compcom ();
2889 src_visible = SRC_NA;
2890 hex_visible = false;
2891 srcmetrics_visible = false;
2894 dump_anno_file (out_file, isDisasm ? Histable::INSTR : Histable::LINE,
2895 module, dbev, nmlist, hist_data->get_totals ()->value,
2896 srcFile, func, marks, threshold, compcom_bits,
2897 src_visible, hex_visible, srcmetrics_visible);
2899 delete marks;
2901 errstr = module->anno_str ();
2902 if (errstr)
2904 fprintf (stderr, GTXT ("Error: %s\n"), errstr);
2905 free (errstr);
2907 delete hist_data;
2910 void
2911 print_html_title (FILE *out_file, char *title)
2913 // This will print a header row for the report
2914 fprintf (out_file, "<html><title>%s</title>\n", title);
2915 fprintf (out_file, "<center><h3>%s</h3></center>\n", title);
2918 void
2919 print_html_label (FILE *out_file, MetricList *metrics_list)
2921 int mlist_sz;
2923 // This will print a header row for the metrics
2924 Vector<Metric*> *mlist = metrics_list->get_items ();
2925 mlist_sz = mlist->size ();
2927 fprintf (out_file, "<style type=\"text/css\">\n");
2928 fprintf (out_file, "<!--\nBODY\n");
2929 fprintf (out_file, ".th_C { text-align:center; background-color:lightgoldenrodyellow; }\n");
2930 fprintf (out_file, ".th_CG { text-align:center; background-color:#ffff33; }\n");
2931 fprintf (out_file, ".th_L { text-align:left; background-color:lightgoldenrodyellow; }\n");
2932 fprintf (out_file, ".th_LG { text-align:left; background-color:#ffff33; }\n");
2933 fprintf (out_file, ".td_R { text-align:right; }\n");
2934 fprintf (out_file, ".td_RG { text-align:right; background-color:#ffff33; }\n");
2935 fprintf (out_file, ".td_L { text-align:left; }\n");
2936 fprintf (out_file, ".td_LG { text-align:left; background-color:#ffff33; }\n");
2937 fprintf (out_file, "-->\n</style>");
2938 fprintf (out_file, "<center><table border=1 cellspacing=2>\n<tr>");
2940 for (int index = 0; index < mlist_sz; index++)
2942 Metric *mitem = mlist->fetch (index);
2943 int ncols = 0;
2944 if (mitem->is_visible ())
2945 ncols++;
2946 if (mitem->is_tvisible ())
2947 ncols++;
2948 if (mitem->is_pvisible ())
2949 ncols++;
2950 if (ncols == 0)
2951 continue;
2952 char *name = strdup (mitem->get_name ());
2953 char *name2 = split_metric_name (name);
2954 const char *style = index == metrics_list->get_sort_ref_index () ? "G" : "";
2956 // start the column, with colspan setting, legend, and sort metric indicator
2957 if (ncols == 1)
2959 if (mitem->get_vtype () == VT_LABEL)
2960 // left-adjust the name metric
2961 fprintf (out_file,
2962 "<th class=\"th_L%s\">%s&nbsp;<br>%s&nbsp;%s&nbsp;<br>%s&nbsp;</th>",
2963 style, mitem->legend == NULL ? "&nbsp;" : mitem->legend,
2964 (index == metrics_list->get_sort_ref_index ()) ? "&nabla;" : "&nbsp;",
2965 name, name2 == NULL ? "&nbsp;" : name2);
2966 else
2967 // but center the others
2968 fprintf (out_file,
2969 "<th class=\"th_C%s\">%s&nbsp;<br>%s&nbsp;%s&nbsp;<br>%s&nbsp;</th>",
2970 style, mitem->legend == NULL ? "&nbsp;" : mitem->legend,
2971 (index == metrics_list->get_sort_ref_index ()) ?
2972 "&nabla;" : "&nbsp;",
2973 name, name2 == NULL ? NTXT ("&nbsp;") : name2);
2975 else
2976 // name metric can't span columns
2977 fprintf (out_file,
2978 "<th colspan=%d class=\"th_C%s\">%s&nbsp;<br>%s&nbsp;%s&nbsp;<br>%s&nbsp;</th>",
2979 ncols, style,
2980 mitem->legend == NULL ? "&nbsp;" : mitem->legend,
2981 index == metrics_list->get_sort_ref_index () ?
2982 "&nabla;" : "&nbsp;",
2983 name, name2 == NULL ? "&nbsp;" : name2);
2985 free (name);
2988 // end this row, start the units row
2989 fprintf (out_file, NTXT ("</tr>\n<tr>"));
2991 // now do the units row
2992 for (int index = 0; index < mlist_sz; index++)
2994 Metric *mitem = mlist->fetch (index);
2995 const char *style = index == metrics_list->get_sort_ref_index () ? "G" : "";
2997 if (mitem->is_tvisible ())
2998 fprintf (out_file, "<th class=\"th_C%s\">&nbsp;(%s)</th>", style,
2999 GTXT ("sec."));
3000 if (mitem->is_visible ())
3002 if (mitem->get_abbr_unit () == NULL)
3003 fprintf (out_file, "<th class=\"th_C%s\">&nbsp;</th>", style);
3004 else
3005 fprintf (out_file, "<th class=\"th_C%s\">(%s)</th>", style,
3006 mitem->get_abbr_unit () == NULL ? "&nbsp;"
3007 : mitem->get_abbr_unit ());
3009 if (mitem->is_pvisible ())
3010 fprintf (out_file, "<th class=\"th_C%s\">&nbsp;(%%)</th>", style);
3012 fprintf (out_file, NTXT ("</tr>\n"));
3015 void
3016 print_html_content (FILE *out_file, Hist_data *data, MetricList *metrics_list,
3017 int limit, Histable::NameFormat nfmt)
3019 Hist_data::HistItem *item;
3021 // printing contents.
3022 for (int i = 0; i < limit; i++)
3024 item = data->fetch (i);
3025 print_html_one (out_file, data, item, metrics_list, nfmt);
3029 void
3030 print_html_one (FILE *out_file, Hist_data *data, Hist_data::HistItem *item,
3031 MetricList *metrics_list, Histable::NameFormat nfmt)
3033 Metric *mitem;
3034 int index;
3035 int visible, tvisible, pvisible;
3036 TValue *value;
3037 double percent;
3039 fprintf (out_file, NTXT ("<tr>"));
3040 Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
3042 visible = mitem->is_visible ();
3043 tvisible = mitem->is_tvisible ();
3044 pvisible = mitem->is_pvisible ();
3045 const char *style = index == metrics_list->get_sort_ref_index () ? "G" : "";
3047 if (tvisible)
3049 value = &(item->value[index]);
3050 if (value->ll == 0LL)
3051 fprintf (out_file,
3052 "<td class=\"td_R%s\"><tt>0.&nbsp;&nbsp;&nbsp;</tt></td>",
3053 style);
3054 else
3055 fprintf (out_file, "<td class=\"td_R%s\"><tt>%4.3lf</tt></td>",
3056 style, 1.e-6 * value->ll / dbeSession->get_clock (-1));
3059 if (visible)
3061 if (mitem->get_vtype () == VT_LABEL)
3063 value = &(item->value[index]);
3064 char *r;
3065 if (value->tag == VT_OFFSET)
3066 r = ((DataObject*) (item->obj))->get_offset_name ();
3067 else
3068 r = item->obj->get_name (nfmt);
3069 char *n = html_ize_name (r);
3070 fprintf (out_file, NTXT ("<td class=\"td_L%s\">%s</td>"), style, n);
3071 free (n);
3073 else
3075 value = &(item->value[index]);
3076 switch (value->tag)
3078 case VT_DOUBLE:
3079 if (value->d == 0.0)
3080 fprintf (out_file,
3081 "<td class=\"td_R%s\"><tt>0.&nbsp;&nbsp;&nbsp;</tt></td>",
3082 style);
3083 else
3084 fprintf (out_file,
3085 "<td class=\"td_R%s\"><tt>%4.3lf</tt></td>", style,
3086 value->d);
3087 break;
3088 case VT_INT:
3089 fprintf (out_file, "<td class=\"td_R%s\"><tt>%d</tt></td>",
3090 style, value->i);
3091 break;
3092 case VT_LLONG:
3093 fprintf (out_file, "<td class=\"td_R%s\"><tt>%lld</td></tt>",
3094 style, value->ll);
3095 break;
3096 case VT_ULLONG:
3097 fprintf (out_file, "<td class=\"td_R%s\"><tt>%llu</td></tt>",
3098 style, value->ull);
3099 break;
3100 case VT_ADDRESS:
3101 fprintf (out_file,
3102 "<td class=\"td_R%s\"><tt>%u:0x%08x</tt></td>", style,
3103 ADDRESS_SEG (value->ll), ADDRESS_OFF (value->ll));
3104 break;
3105 case VT_FLOAT:
3106 if (value->f == 0.0)
3107 fprintf (out_file,
3108 "<td class=\"td_R%s\"><tt>0.&nbsp;&nbsp;&nbsp;</tt></td>",
3109 style);
3110 else
3111 fprintf (out_file,
3112 "<td class=\"td_R%s\"><tt>%4.3f</tt></td>",
3113 style, value->f);
3114 break;
3115 case VT_SHORT:
3116 fprintf (out_file, "<td class=\"td_R%s\"><tt>%d</tt></td>",
3117 style, value->s);
3118 break;
3119 // ignoring the following cases (why?)
3120 case VT_HRTIME:
3121 case VT_LABEL:
3122 case VT_OFFSET:
3123 break;
3128 if (pvisible)
3130 percent = data->get_percentage (item->value[index].to_double (), index);
3131 if (percent == 0.0)
3132 // adjust to change format from xx.yy%
3133 fprintf (out_file, "<td class=\"td_R%s\">0.&nbsp;&nbsp;&nbsp;</td>",
3134 style);
3135 else
3136 // adjust format below to change format from xx.yy%
3137 fprintf (out_file, "<td class=\"td_R%s\">%3.2f</td>", style,
3138 (100.0 * percent));
3141 fprintf (out_file, NTXT ("</tr>\n"));
3144 void
3145 print_html_trailer (FILE *out_file)
3147 fprintf (out_file, NTXT ("</table></center></html>\n"));
3150 static char *
3151 del_delim (char *s)
3153 size_t len = strlen (s);
3154 if (len > 0)
3155 s[len - 1] = 0;
3156 return s;
3159 void
3160 print_delim_label (FILE *out_file, MetricList *metrics_list, char delim)
3162 char line0[2 * MAX_LEN], line1[2 * MAX_LEN];
3163 char line2[2 * MAX_LEN], line3[2 * MAX_LEN];
3164 size_t len;
3166 // This will print four header rows for the metrics
3167 line0[0] = 0;
3168 line1[0] = 0;
3169 line2[0] = 0;
3170 line3[0] = 0;
3171 Vector<Metric*> *mlist = metrics_list->get_items ();
3172 for (int index = 0, mlist_sz = mlist->size (); index < mlist_sz; index++)
3174 Metric *mitem = mlist->fetch (index);
3175 if (!(mitem->is_visible () || mitem->is_tvisible ()
3176 || mitem->is_pvisible ()))
3177 continue;
3178 char *name = strdup (mitem->get_name ());
3179 char *name2 = split_metric_name (name);
3181 if (mitem->is_tvisible ())
3183 len = strlen (line0);
3184 snprintf (line0 + len, sizeof (line0) - len, NTXT ("\"%s\"%c"),
3185 mitem->legend == NULL ? NTXT ("") : mitem->legend, delim);
3186 len = strlen (line1);
3187 snprintf (line1 + len, sizeof (line1) - len, NTXT ("\"%s\"%c"),
3188 name, delim);
3189 len = strlen (line2);
3190 snprintf (line2 + len, sizeof (line2) - len, NTXT ("\"%s\"%c"),
3191 name2 == NULL ? NTXT ("") : name2, delim);
3192 len = strlen (line3);
3193 if (index == metrics_list->get_sort_ref_index ())
3194 snprintf (line3 + len, sizeof (line3) - len, NTXT ("\"V %s\"%c"),
3195 GTXT ("(sec.)"), delim);
3196 else
3197 snprintf (line3 + len, sizeof (line3) - len, NTXT ("\" %s\"%c"),
3198 GTXT ("(sec.)"), delim);
3200 if (mitem->is_visible ())
3202 len = strlen (line0);
3203 snprintf (line0 + len, sizeof (line0) - len, "\"%s\"%c",
3204 mitem->legend == NULL ? "" : mitem->legend, delim);
3206 len = strlen (line1);
3207 snprintf (line1 + len, sizeof (line1) - len, "\"%s\"%c",
3208 name, delim);
3210 len = strlen (line2);
3211 snprintf (line2 + len, sizeof (line2) - len, "\"%s\"%c",
3212 name2 == NULL ? NTXT ("") : name2, delim);
3214 len = strlen (line3);
3215 char *au = mitem->get_abbr_unit ();
3217 if (index == metrics_list->get_sort_ref_index ())
3219 if (au == NULL)
3220 snprintf (line3 + len, sizeof (line3) - len, "\"V \"%c", delim);
3221 else
3222 snprintf (line3 + len, sizeof (line3) - len, "\"V (%s)\"%c",
3223 au, delim);
3225 else
3227 if (au == NULL)
3228 snprintf (line3 + len, sizeof (line3) - len, "\" \"%c",
3229 delim);
3230 else
3231 snprintf (line3 + len, sizeof (line3) - len, "\" (%s)\"%c",
3232 au, delim);
3235 if (mitem->is_pvisible ())
3237 len = strlen (line0);
3238 snprintf (line0 + len, sizeof (line0) - len, NTXT ("\"%s\"%c"),
3239 mitem->legend == NULL ? NTXT ("") : mitem->legend, delim);
3241 len = strlen (line1);
3242 snprintf (line1 + len, sizeof (line1) - len, NTXT ("\"%s\"%c"),
3243 name, delim);
3245 len = strlen (line2);
3246 snprintf (line2 + len, sizeof (line2) - len, NTXT ("\"%s\"%c"),
3247 name2 == NULL ? NTXT ("") : name2, delim);
3249 len = strlen (line3);
3250 if (index == metrics_list->get_sort_ref_index ())
3251 snprintf (line3 + len, sizeof (line3) - len, NTXT ("\"V %s\"%c"),
3252 NTXT ("%%"), delim);
3253 else
3254 snprintf (line3 + len, sizeof (line3) - len, NTXT ("\" %s\"%c"),
3255 NTXT ("%%"), delim);
3257 free (name);
3259 // now remove the trailing delimiter, and print the four lines
3260 fprintf (out_file, NTXT ("%s\n"), del_delim (line0));
3261 fprintf (out_file, NTXT ("%s\n"), del_delim (line1));
3262 fprintf (out_file, NTXT ("%s\n"), del_delim (line2));
3263 fprintf (out_file, NTXT ("%s\n"), del_delim (line3));
3266 void
3267 print_delim_content (FILE *out_file, Hist_data *data, MetricList *metrics_list,
3268 int limit, Histable::NameFormat nfmt, char delim)
3270 Hist_data::HistItem *item;
3271 int i;
3273 // printing contents.
3274 for (i = 0; i < limit; i++)
3276 item = data->fetch (i);
3277 print_delim_one (out_file, data, item, metrics_list, nfmt, delim);
3281 void
3282 print_delim_trailer (FILE */*out_file*/, char /*delim*/) { }
3284 // EUGENE does this function work properly when "-compare ratio" is used?
3285 // how about when the ratio is nonzero-divided-by-zero?
3286 // EUGENE actually, review this entire file
3288 void
3289 print_delim_one (FILE *out_file, Hist_data *data, Hist_data::HistItem *item,
3290 MetricList *metrics_list, Histable::NameFormat nfmt,
3291 char delim)
3293 Metric *mitem;
3294 int index;
3295 int visible, tvisible, pvisible;
3296 TValue *value;
3297 double percent;
3298 size_t len;
3300 char line1[2 * MAX_LEN];
3301 *line1 = 0;
3302 Vec_loop (Metric*, metrics_list->get_items (), index, mitem)
3304 visible = mitem->is_visible ();
3305 tvisible = mitem->is_tvisible ();
3306 pvisible = mitem->is_pvisible ();
3307 if (tvisible)
3309 value = &(item->value[index]);
3310 len = strlen (line1);
3311 if (value->ll == 0LL)
3312 snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c", delim);
3313 else
3314 snprintf (line1 + len, sizeof (line1) - len, "\"%4.3lf\"%c",
3315 1.e-6 * value->ll / dbeSession->get_clock (-1),
3316 delim);
3319 if (visible)
3321 len = strlen (line1);
3322 if (mitem->get_vtype () == VT_LABEL)
3324 value = &(item->value[index]);
3325 char *r;
3326 if (value->tag == VT_OFFSET)
3327 r = ((DataObject*) (item->obj))->get_offset_name ();
3328 else
3329 r = item->obj->get_name (nfmt);
3330 char *p = csv_ize_name (r, delim);
3331 snprintf (line1 + len, sizeof (line1) - len, "\"%s\"%c", p, delim);
3332 free (p);
3334 else
3336 value = &(item->value[index]);
3337 switch (value->tag)
3339 case VT_DOUBLE:
3340 if (value->d == 0.0)
3341 snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c",
3342 delim);
3343 else
3344 snprintf (line1 + len, sizeof (line1) - len, "\"%4.3lf\"%c",
3345 value->d, delim);
3346 break;
3347 case VT_INT:
3348 snprintf (line1 + len, sizeof (line1) - len, "\"%d\"%c",
3349 value->i, delim);
3350 break;
3351 case VT_LLONG:
3352 snprintf (line1 + len, sizeof (line1) - len, "\"%lld\"%c",
3353 value->ll, delim);
3354 break;
3355 case VT_ULLONG:
3356 snprintf (line1 + len, sizeof (line1) - len, "\"%llu\"%c",
3357 value->ull, delim);
3358 break;
3359 case VT_ADDRESS:
3360 snprintf (line1 + len, sizeof (line1) - len, "\"%u:0x%08x\"%c",
3361 ADDRESS_SEG (value->ll),
3362 ADDRESS_OFF (value->ll), delim);
3363 break;
3364 case VT_FLOAT:
3365 if (value->f == 0.0)
3366 snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c",
3367 delim);
3368 else
3369 snprintf (line1 + len, sizeof (line1) - len, "\"%4.3f\"%c",
3370 value->f, delim);
3371 break;
3372 case VT_SHORT:
3373 snprintf (line1 + len, sizeof (line1) - len, "\"%d\"%c",
3374 value->s, delim);
3375 break;
3376 // ignoring the following cases (why?)
3377 case VT_HRTIME:
3378 case VT_LABEL:
3379 case VT_OFFSET:
3380 break;
3385 if (pvisible)
3387 len = strlen (line1);
3388 percent = data->get_percentage (item->value[index].to_double (), index);
3389 if (percent == 0.0)
3390 // adjust to change format from xx.yy%
3391 snprintf (line1 + len, sizeof (line1) - len, "\"0.\"%c", delim);
3392 else
3393 // adjust format below to change format from xx.yy%
3394 snprintf (line1 + len, sizeof (line1) - len, "\"%3.2f\"%c",
3395 (100.0 * percent), delim);
3398 fprintf (out_file, NTXT ("%s\n"), del_delim (line1));
3401 char *
3402 html_ize_name (char *name)
3404 StringBuilder sb;
3405 for (size_t i = 0; i < strlen (name); i++)
3407 switch (name[i])
3409 case ' ': sb.append (NTXT ("&nbsp;"));
3410 break;
3411 case '"': sb.append (NTXT ("&quot;"));
3412 break;
3413 case '&': sb.append (NTXT ("&amp;"));
3414 break;
3415 case '<': sb.append (NTXT ("&lt;"));
3416 break;
3417 case '>': sb.append (NTXT ("&gt;"));
3418 break;
3419 default: sb.append (name[i]);
3420 break;
3423 char *ret = sb.toString ();
3424 return ret;
3427 char *
3428 csv_ize_name (char *name, char /*delim*/)
3430 StringBuilder sb;
3431 for (size_t i = 0; i < strlen (name); i++)
3432 sb.append (name[i]);
3433 char *ret = sb.toString ();
3434 return ret;
3437 // Split a metric name into two parts, replacing a blank with
3438 // a zero and returning pointer to the rest of the string, or
3439 // leaving the string unchanged, and returning NULL;
3441 char *
3442 split_metric_name (char *name)
3444 // figure out the most even split of the name
3445 size_t len = strlen (name);
3446 char *middle = &name[len / 2];
3448 // find the first blank
3449 char *first = strchr (name, (int) ' ');
3450 if (first == NULL) // no blanks
3451 return NULL;
3452 char *last = first;
3453 char *p = first;
3454 for (;;)
3456 p = strchr (p + 1, (int) ' ');
3457 if (p == NULL)
3458 break;
3459 if (p < middle)
3461 first = p;
3462 last = p;
3464 else
3466 last = p;
3467 break;
3470 // pick the better of the two
3471 char *ret;
3472 int f = (int) (middle - first);
3473 int l = (int) (last - middle);
3474 if ((first == last) || (f <= l))
3476 *first = '\0';
3477 ret = first + 1;
3479 else
3481 *last = '\0';
3482 ret = last + 1;
3484 return ret;