1 /* ------------------------------------------------------------------------
2 * $Id: cgprof.c,v 1.1 2000/04/05 10:06:36 simonmar Exp $
4 * Copyright (C) 1995-2000 University of Oxford
6 * Permission to use, copy, modify, and distribute this software,
7 * and to incorporate it, in whole or in part, into other software,
8 * is hereby granted without fee, provided that
9 * (1) the above copyright notice and this permission notice appear in
10 * all copies of the source code, and the above copyright notice
11 * appear in clearly visible form on all supporting documentation
12 * and distribution media;
13 * (2) modified versions of this software be accompanied by a complete
14 * change history describing author, date, and modifications made;
16 * (3) any redistribution of the software, in original or modified
17 * form, be without fee and subject to these same conditions.
18 * --------------------------------------------------------------------- */
30 /* -----------------------------------------------------------------------------
32 * -------------------------------------------------------------------------- */
34 int raw_profile_next=0;
35 int raw_profile_size=0;
36 parsed_cost_object *raw_profile=NULL;
38 /* -----------------------------------------------------------------------------
39 * Create/grow data sequence of raw profile data
40 * -------------------------------------------------------------------------- */
42 void enlargeRawProfile() {
44 if (raw_profile_size==0) {
46 raw_profile_size = RAW_PROFILE_INIT_SIZE;
47 raw_profile = calloc(raw_profile_size,sizeof(parsed_cost_object));
49 raw_profile_size += RAW_PROFILE_INIT_SIZE;
50 raw_profile = realloc(raw_profile,
51 raw_profile_size*sizeof(parsed_cost_object));
53 if (raw_profile==NULL) {
54 fprintf(stderr,"{enlargeRawProfile} unable to allocate %d elements",
60 /* -----------------------------------------------------------------------------
61 * Function that adds two cost centers together
63 * This will be used to generate the inheretance profile.
64 * -------------------------------------------------------------------------- */
66 void add_costs(object_cost *left, object_cost right) {
69 left->syncs += right.syncs;
70 left->comp_max += right.comp_max;
71 left->comp_avg += right.comp_avg;
72 left->comp_min += right.comp_min;
73 left->comm_max += right.comm_max;
74 left->comm_avg += right.comm_avg;
75 left->comm_min += right.comm_min;
76 left->comp_idle_max += right.comp_idle_max;
77 left->comp_idle_avg += right.comp_idle_avg;
78 left->comp_idle_min += right.comp_idle_min;
79 left->hrel_max += right.hrel_max;
80 left->hrel_avg += right.hrel_avg;
81 left->hrel_min += right.hrel_min;
82 if ((left->proc==NULL) || (right.proc==NULL)) {
83 fprintf(stderr,"Cost is null");
89 int ignore_function(char *fname) {
93 /* -----------------------------------------------------------------------------
94 * GHC specific data structures
95 * -------------------------------------------------------------------------- */
98 /* You will need to update these when you increase the number of */
99 /* cost centres, cost centre stacks, heap objects */
101 #define MAX_IDENTIFIERS 2000 /* maximum number of identifiers */
102 /* or size of matrix structure */
104 /* make this dynamic */
106 #define MAX_TIME 100 /* Maximum serial time for heap profile */
107 #define MAX_SAMPLES 50 /* Maximum heap samples */
109 /* To do: modify this to be dynamic */
111 #define MAX_STRING_SIZE 70
112 #define MAX_LINE_LENGTH 80
115 /* Cost centre data structure */
117 struct cost_centre { char *name;
122 typedef struct cost_centre cc_matrix[MAX_IDENTIFIERS];
124 //typedef struct cost_centre *cc_matrix;
126 typedef cc_matrix* p_cc_matrix;
127 typedef char* MY_STRING;
129 /* Heap sample structure */
132 int count; /* heap_sample */
135 typedef struct heap_sample heap_sample_matrix[MAX_IDENTIFIERS];
136 typedef heap_sample_matrix* p_heap_sample_matrix;
138 /* Cost centre stack data structure */
140 struct cost_centre_stack {
143 int scc; /* scc_sample */
144 int ticks; /* scc_sample */
145 int bytes; /* scc_sample */
146 p_heap_sample_matrix hsm; /* heap_sample */
149 typedef struct cost_centre_stack ccs_matrix[MAX_IDENTIFIERS];
150 typedef ccs_matrix* p_ccs_matrix;
152 /* Heap object data structure */
154 struct heap_object { int type; /* type of heap object */
156 int type_constr_ref; /* if present */
159 typedef struct heap_object heap_object_matrix[MAX_IDENTIFIERS];
160 typedef heap_object_matrix* p_heap_object_matrix;
162 /* Type constructor structure */
164 struct type_constr { char* module;
168 typedef struct type_constr type_constr_matrix[MAX_IDENTIFIERS];
169 typedef type_constr_matrix* p_type_constr_matrix;
171 /* Heap update structure */
173 struct heap_update_sample { int ccs; /* associated cost centre stack */
174 int ho; /* associated heap object */
178 typedef struct heap_update_sample heap_update_list[MAX_SAMPLES];
179 typedef heap_update_list* p_heap_update_list;
181 struct heap_update_record { int no_samples; /* Number of samples */
182 p_heap_update_list acc_samples;
185 typedef struct heap_update_record TheHeap[MAX_TIME];
186 typedef TheHeap* p_TheHeap;
189 /* -----------------------------------------------------------------------------
190 * GHC specific functions
191 * -------------------------------------------------------------------------- */
193 // Initialisation routines
195 void initialise_heap_update_list(heap_update_list *m)
198 for (i=0; i<MAX_SAMPLES;i++)
206 void add_to_heap_update_list(heap_update_list *m, int ccs, int ho, int count, int pos)
210 (*m)[pos].count = count;
213 void initialise_TheHeap(TheHeap *h)
216 for (i=0; i<MAX_TIME;i++)
218 heap_update_list *h_u_l;
219 h_u_l = (p_heap_update_list) malloc (sizeof(heap_update_list));
220 initialise_heap_update_list(h_u_l);
221 (*h)[i].acc_samples = h_u_l;
222 (*h)[i].no_samples = 0;
226 void add_to_TheHeap(TheHeap *h, int time, int ccs, int ho, int count)
228 add_to_heap_update_list((*h)[time].acc_samples,ccs,ho,count,(*h)[time].no_samples);
229 (*h)[time].no_samples++;
232 void initialise_cc_matrix(cc_matrix *m)
235 char *blank="blank"; /* To do: Modify this terminator string */
236 for (i=0; i<MAX_IDENTIFIERS; i++)
238 (*m)[i].name = (MY_STRING) malloc ((MAX_STRING_SIZE));
239 (*m)[i].module = (MY_STRING) malloc ((MAX_STRING_SIZE));
240 (*m)[i].group = (MY_STRING) malloc ((MAX_STRING_SIZE));
242 strcpy((*m)[i].name,blank);
243 strcpy((*m)[i].module,blank);
244 strcpy((*m)[i].group,blank);
248 void free_cc_matrix(cc_matrix *m)
251 for (i=0; i<MAX_IDENTIFIERS; i++)
254 free((*m)[i].module);
260 void initialise_heap_object_matrix(heap_object_matrix *m)
263 char *blank="blank"; /* To do: ditto */
264 for (i=0; i<MAX_IDENTIFIERS; i++)
267 (*m)[i].descriptor = (MY_STRING) malloc ((MAX_STRING_SIZE));
268 strcpy((*m)[i].descriptor,blank);
269 (*m)[i].type_constr_ref = -1;
273 void initialise_type_constr_matrix(type_constr_matrix *m)
277 for (i=0; i<MAX_IDENTIFIERS; i++)
279 (*m)[i].module = (MY_STRING) malloc ((MAX_STRING_SIZE));
280 (*m)[i].name = (MY_STRING) malloc ((MAX_STRING_SIZE));
281 strcpy((*m)[i].module,blank);
282 strcpy((*m)[i].name,blank);
286 void initialise_heap_sample_matrix(heap_sample_matrix *m)
289 for (i=0; i<MAX_IDENTIFIERS; i++)
290 { (*m)[i].count = -1; }
293 void initialise_ccs_matrix(ccs_matrix *m)
296 for (i=0; i<MAX_IDENTIFIERS; i++)
298 /* Stack heap samples */
299 heap_sample_matrix *hs_m;
300 hs_m = (p_heap_sample_matrix) malloc (sizeof(heap_sample_matrix));
301 initialise_heap_sample_matrix(hs_m);
303 /* Stack scc samples */
313 // Filling matrix routines
315 char* StripDoubleQuotes(char* s) /* For fussy daVinci! */
320 char *tempstring = (MY_STRING) malloc ((MAX_STRING_SIZE));
321 strcpy(tempstring,empty);
324 { tempchar = p; strncat(tempstring,p,1);
331 void fill_cc_matrix(cc_matrix *m,char* name,char* module,char* group,int i)
333 if (i>MAX_IDENTIFIERS)
334 { fprintf(log,"Cost centre MAX_IDENTIFIERS exceeded: %i \n",i); exit(1); }
335 name = StripDoubleQuotes(name);
336 strcpy((*m)[i].name,name);
337 module = StripDoubleQuotes(module);
338 strcpy((*m)[i].module,module);
339 group = StripDoubleQuotes(group);
340 strcpy((*m)[i].group,group);
343 void fill_ccs_matrix(ccs_matrix *m,int cc, int ccs, int scc, int ticks, int bytes, int h_o, int count, int i)
345 heap_sample_matrix *hsm;
347 if ((*m)[i].cc == 0) /* added for type 2 stack semantics, but should not */
348 /* change behaviour of type 1 (apart from CAF:REP. */
350 if (i>MAX_IDENTIFIERS)
351 { fprintf(log,"Cost centre stack MAX_IDENTIFIERS exceeded: %i \n",i); exit(1); }
353 (*m)[i].cc = cc; (*m)[i].ccs = ccs;
354 (*m)[i].ticks = ticks; (*m)[i].bytes = bytes; (*m)[i].scc = scc;
355 (*hsm)[h_o].count = count;
357 else fprintf(log,"Ignoring redeclaration of stack %i\n",i);
360 void add_ccs_costs(ccs_matrix *m, int b,int c,int d,int x,int y,int h_o, int co)
362 (*m)[c].scc = (*m)[c].scc + d;
363 (*m)[c].ticks = (*m)[c].ticks + x;
364 (*m)[c].bytes = (*m)[c].bytes + y;
367 void add_heap_sample_costs(ccs_matrix *m, int b,int c,int d,int x,int y,int h_o, int co)
369 heap_sample_matrix *hsm = (*m)[c].hsm;
370 if (((*hsm)[h_o].count)==-1)
371 (*hsm)[h_o].count = (*hsm)[h_o].count + co + 1; /* as init is -1 */
373 (*hsm)[h_o].count = (*hsm)[h_o].count + co;
376 void add_heap_object(heap_object_matrix *m, int pos, int t, char* des, int tr)
378 if (pos>MAX_IDENTIFIERS)
379 { fprintf(log,"Heap object MAX_IDENTIFIERS exceeded: %i \n",pos); exit(1); }
381 strcpy((*m)[pos].descriptor,des);
382 (*m)[pos].type_constr_ref = tr;
385 void add_type_constr_object(type_constr_matrix *m, int pos, char* mod, char* n)
387 if (pos>MAX_IDENTIFIERS)
388 { fprintf(log,"Type constructor MAX_IDENTIFIERS exceeded: %i \n",pos); exit(1); }
389 strcpy((*m)[pos].module,mod);
390 strcpy((*m)[pos].name,n);
396 void print_heap_update_list(heap_update_list *m, int number)
400 for (i=0; i<number;i++)
402 fprintf(log," (%i,%i,%i) ",(*m)[i].ccs,(*m)[i].ho,(*m)[i].count);
407 void print_TheHeap(TheHeap *h)
410 fprintf(log,"The Heap\n========\n");
411 for (i=0; i<MAX_TIME;i++)
413 if ((*h)[i].no_samples>0)
415 fprintf(log,"Sample time %i, number of samples %i actual samples "
416 ,i,(*h)[i].no_samples);
417 print_heap_update_list((*h)[i].acc_samples,(*h)[i].no_samples);
422 void PrintXaxis(FILE *HEAP_PROFILE, TheHeap *h)
425 fprintf(HEAP_PROFILE," ");
426 for (i=0; i<MAX_TIME;i++)
428 if ((*h)[i].no_samples>0)
429 fprintf(HEAP_PROFILE,"%i ",i);
433 int FindSample(heap_update_list *m, int number, int element)
436 for (i=0; i<number;i++)
438 if ((*m)[i].ho==element)
439 return ((*m)[i].count);
444 void PrintSampleCosts(FILE *hfp, TheHeap *h, int element)
448 for (i=0; i<MAX_TIME;i++)
450 if ((*h)[i].no_samples>0)
452 total = total + FindSample((*h)[i].acc_samples,(*h)[i].no_samples,element);
453 fprintf(hfp," %i ",total);
458 void print_cc_matrix(cc_matrix *m)
462 fprintf(log,"Cost centre matrix\n");
463 fprintf(log,"==================\n");
464 for (i=0; i<MAX_IDENTIFIERS; i++)
465 { if (strcmp((*m)[i].name,blank)!=0)
466 fprintf(log,"%s %s %s\n",(*m)[i].name,(*m)[i].module,(*m)[i].group); }
470 void print_heap_object_matrix(FILE* hfp, TheHeap *h, heap_object_matrix *m)
473 for (i=0; i<MAX_IDENTIFIERS; i++)
475 if (((*m)[i].type)!=-1)
477 fprintf(hfp,"Y%i set {",i);
478 /* if ((*m)[i].type==1) fprintf(hfp,"data_contr ");
479 if ((*m)[i].type==2) fprintf(hfp,"PAP ");
480 if ((*m)[i].type==3) fprintf(hfp,"thunk ");
481 if ((*m)[i].type==4) fprintf(hfp,"function ");
482 if ((*m)[i].type==5) fprintf(hfp,"dictionary ");
484 fprintf(hfp,"%s %i ",(*m)[i].descriptor,(*m)[i].type_constr_ref);
486 fprintf(hfp,"%s ",(*m)[i].descriptor); */
487 PrintSampleCosts(hfp,h,i);
493 int number_of_heap_objects(heap_object_matrix *m)
497 for (i=0; i<MAX_IDENTIFIERS; i++)
499 if (((*m)[i].type)!=-1) count++;
504 void names_of_heap_objects(FILE *hfp, heap_object_matrix *m)
507 for (i=0; i<MAX_IDENTIFIERS; i++)
509 if (((*m)[i].type)!=-1)
510 fprintf(hfp,"Y%i ",i);
515 void names_and_colour_assignment(FILE *hfp, heap_object_matrix *m)
519 for (i=0; i<MAX_IDENTIFIERS; i++)
521 if (((*m)[i].type)!=-1)
525 case 0 : fprintf(hfp,"%s \t Y%i \t red \t fdiagonal1\n",(*m)[i].descriptor,i);
527 case 1 : fprintf(hfp,"%s \t Y%i \t blue \t fdiagonal1\n",(*m)[i].descriptor,i);
529 case 2 : fprintf(hfp,"%s \t Y%i \t green \t fdiagonal1\n",(*m)[i].descriptor,i);
531 case 3 : fprintf(hfp,"%s \t Y%i \t yellow \t fdiagonal1\n",(*m)[i].descriptor,i);
533 case 4 : fprintf(hfp,"%s \t Y%i \t pink \t fdiagonal1\n",(*m)[i].descriptor,i);
535 case 5 : fprintf(hfp,"%s \t Y%i \t goldenrod \t fdiagonal1\n",(*m)[i].descriptor,i);
537 case 6 : fprintf(hfp,"%s \t Y%i \t orange \t fdiagonal1\n",(*m)[i].descriptor,i);
539 default: fprintf(hfp,"%s \t Y%i \t purple \t fdiagonal1\n",(*m)[i].descriptor,i);
546 void print_type_constr_matrix(type_constr_matrix *m)
550 fprintf(log,"Type constructor matrix\n");
551 fprintf(log,"=======================\n");
552 for (i=0; i<MAX_IDENTIFIERS; i++)
554 if (strcmp((*m)[i].name,blank)!=0)
555 fprintf(log,"%i %s %s\n",i,(*m)[i].module,(*m)[i].name);
559 void print_heap_sample_matrix(heap_sample_matrix *m)
562 fprintf(log,"HeapSamples[");
563 for (i=0; i<MAX_IDENTIFIERS; i++)
565 if ((*m)[i].count!=-1) fprintf(log,"(%i,%i),",i,(*m)[i].count);
570 void print_ccs_matrix(ccs_matrix *m)
573 fprintf(log,"Cost centre stack matrix\n");
574 fprintf(log,"========================\n");
575 for (i=0; i<MAX_IDENTIFIERS; i++)
578 fprintf(log,"%i %i %i %i %i \n",(*m)[i].cc,(*m)[i].ccs,(*m)[i].scc,
579 (*m)[i].ticks,(*m)[i].bytes);
588 void FormStack(ccs_matrix *m, cc_matrix *n, int i, char s[])
593 strcat(s,(*n)[(*m)[j].cc].name);
595 while ((*m)[j].ccs != (-1))
597 strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].name);
602 else fprintf(log,"ERROR: Form Stack %i\n",i);
605 /* This version, which is used, adds the module and group name to the cost centre name*/
606 /* This means the cost centre name remains unique when it is textualised and fed into */
607 /* daVinci. It also allows the module and group name to be extracted at the display */
610 void FormStack2(ccs_matrix *m, cc_matrix *n, int i, char s[])
615 strcat(s,(*n)[(*m)[j].cc].name);
617 strcat(s,(*n)[(*m)[j].cc].module);
619 strcat(s,(*n)[(*m)[j].cc].group);
621 while ((*m)[j].ccs != (-1))
623 strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].name);
625 strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].module);
627 strcat(s,(*n)[(*m)[(*m)[j].ccs].cc].group);
632 else fprintf(log,"ERROR: Form Stack %i\n",i);
635 void PrintStack(ccs_matrix *m, cc_matrix *n, int i)
637 char stack[MAX_PROFILE_LINE_LENGTH];
642 fprintf(log,"%s,",(*n)[(*m)[j].cc].name);
643 while ((*m)[j].ccs != (-1))
645 fprintf(log,"%s,",(*n)[(*m)[(*m)[j].ccs].cc].name);
649 fprintf(log,"%i scc %i ticks %i bytes ",
650 (*m)[i].scc,(*m)[i].ticks,(*m)[i].bytes);
651 print_heap_sample_matrix((*m)[i].hsm);
654 { /* fprintf(log,"empty stack\n"); */ }
657 int CountStacks(ccs_matrix *m)
661 for (j=0; j<MAX_IDENTIFIERS;j++) if ((*m)[j].cc != 0) count++;
665 void PrintAllStacks(ccs_matrix *m, cc_matrix *n)
668 fprintf(log,"Stacks\n======\n");
669 for (i=0;i<MAX_IDENTIFIERS;i++) { PrintStack(m,n,i); }
673 /* -----------------------------------------------------------------------------
674 * TCL Heap profile generator
675 * -------------------------------------------------------------------------- */
677 void produce_HEAP_PROFILE(FILE *HEAP_PROFILE, TheHeap *th, heap_object_matrix *ho_m)
679 // First the header information
680 fprintf(HEAP_PROFILE,"#!/home/sj/blt2.4o/src/bltwish\n");
681 fprintf(HEAP_PROFILE,"package require BLT\n");
682 fprintf(HEAP_PROFILE,"if { $tcl_version >= 8.0 } {\n");
683 fprintf(HEAP_PROFILE,"\t \t namespace import blt::*\n");
684 fprintf(HEAP_PROFILE,"namespace import -force blt::tile::*\n");
685 fprintf(HEAP_PROFILE,"}\n");
686 fprintf(HEAP_PROFILE,"source scripts/demo.tcl\n");
687 fprintf(HEAP_PROFILE,"proc FormatXTicks { w value } {\n");
688 fprintf(HEAP_PROFILE,"\t \t set index [expr round($value)]\n");
689 fprintf(HEAP_PROFILE,"\t \t if { $index != $value } {\n");
690 fprintf(HEAP_PROFILE,"\t \t \t return $value\n");
691 fprintf(HEAP_PROFILE,"\t \t}\n");
692 fprintf(HEAP_PROFILE,"incr index -1\n");
694 // Now the code to generate the units in the X axis
696 fprintf(HEAP_PROFILE,"set name [lindex { ");
697 PrintXaxis(HEAP_PROFILE,th);
698 fprintf(HEAP_PROFILE," } $index]\n");
700 fprintf(HEAP_PROFILE,"return $name\n");
701 fprintf(HEAP_PROFILE,"}\n");
703 // more general graph stuff
705 fprintf(HEAP_PROFILE,"source scripts/stipples.tcl\n");
706 fprintf(HEAP_PROFILE,"image create photo bgTexture -file ./images/chalk.gif\n");
707 fprintf(HEAP_PROFILE,"option add *Button.padX 5\n");
708 fprintf(HEAP_PROFILE,"option add *tile bgTexture\n");
709 fprintf(HEAP_PROFILE,"option add *Radiobutton.font -*-courier*-medium-r-*-*-14-*-*\n");
710 fprintf(HEAP_PROFILE,"option add *Radiobutton.relief flat\n");
711 fprintf(HEAP_PROFILE,"option add *Radiobutton.borderWidth 2\n");
712 fprintf(HEAP_PROFILE,"option add *Radiobutton.highlightThickness 0\n");
713 fprintf(HEAP_PROFILE,"option add *Htext.font -*-times*-bold-r-*-*-14-*-*\n");
714 fprintf(HEAP_PROFILE,"option add *Htext.tileOffset no\n");
715 fprintf(HEAP_PROFILE,"option add *header.font -*-times*-medium-r-*-*-14-*-*\n");
716 fprintf(HEAP_PROFILE,"option add *Barchart.font -*-helvetica-bold-r-*-*-14-*-*\n");
718 fprintf(HEAP_PROFILE,"option add *Barchart.title \"Heap profile of program ");
719 // TO DO: Add program name in here
720 fprintf(HEAP_PROFILE,"\"\n");
722 fprintf(HEAP_PROFILE,"option add *Axis.tickFont -*-helvetica-medium-r-*-*-12-*-*\n");
723 fprintf(HEAP_PROFILE,"option add *Axis.titleFont -*-helvetica-bold-r-*-*-12-*-*\n");
724 fprintf(HEAP_PROFILE,"option add *x.Command FormatXTicks\n");
725 fprintf(HEAP_PROFILE,"option add *x.Title \"Time (seconds)\"\n");
726 fprintf(HEAP_PROFILE,"option add *y.Title \"Heap usage (000 bytes)\"\n");
727 fprintf(HEAP_PROFILE,"option add *activeBar.Foreground pink\noption add *activeBar.stipple dot3\noption add *Element.Background red\noption add *Element.Relief raised\n");
728 fprintf(HEAP_PROFILE,"option add *Grid.dashes { 2 4 }\noption add *Grid.hide no\noption add *Grid.mapX \"\"\n");
729 fprintf(HEAP_PROFILE,"option add *Legend.Font \"-*-helvetica*-bold-r-*-*-12-*-*\"\noption add *Legend.activeBorderWidth 2\noption add *Legend.activeRelief raised \noption add *Legend.anchor ne \noption add *Legend.borderWidth 0\noption add *Legend.position right\n");
730 fprintf(HEAP_PROFILE,"option add *TextMarker.Font *Helvetica-Bold-R*14*\n");
731 fprintf(HEAP_PROFILE,"set visual [winfo screenvisual .] \nif { $visual != \"staticgray\" && $visual != \"grayscale\" } {\n option add *print.background yellow\n option add *quit.background red\n option add *quit.activeBackground red2\n}\n");
732 fprintf(HEAP_PROFILE,"htext .title -text {\n Heap profile\n}\n");
733 fprintf(HEAP_PROFILE,"htext .header -text {\n \%%\% \n");
734 fprintf(HEAP_PROFILE," radiobutton .header.stacked -text stacked -variable barMode \\\n -anchor w -value \"stacked\" -selectcolor red -command {\n .graph configure -barmode $barMode\n } \n .header append .header.stacked -width 1.5i -anchor w\n");
735 fprintf(HEAP_PROFILE," \%%\% Heap usage stacked: overall height is the sum of the heap used. \n \%%\% \n");
736 fprintf(HEAP_PROFILE," radiobutton .header.aligned -text aligned -variable barMode \\\n -anchor w -value \"aligned\" -selectcolor yellow -command {\n .graph configure -barmode $barMode }\n .header append .header.aligned -width 1.5i -fill x\n");
737 fprintf(HEAP_PROFILE," \%%\% Heap usage components displayed side-by-side.\n \%%\%\n");
738 fprintf(HEAP_PROFILE," radiobutton .header.overlap -text \"overlap\" -variable barMode \\\n -anchor w -value \"overlap\" -selectcolor green -command {\n .graph configure -barmode $barMode\n }\n .header append .header.overlap -width 1.5i -fill x\n");
739 fprintf(HEAP_PROFILE," \%%\% Heap usage shown as an overlapped histogram.\n \%%\%\n");
740 fprintf(HEAP_PROFILE," radiobutton .header.normal -text \"normal\" -variable barMode \\\n -anchor w -value \"normal\" -selectcolor blue -command {\n .graph configure -barmode $barMode\n }\n .header append .header.normal -width 1.5i -fill x\n");
741 fprintf(HEAP_PROFILE," \%%\% Heap components overlayed one on top of the next. \n}\n");
742 fprintf(HEAP_PROFILE,"htext .footer -text { To create a postscript file \"heap_profile.ps\", press the \%%\%\n button $htext(widget).print -text print -command {\n puts stderr [time {.graph postscript output heap_profile.ps}]\n }\n $htext(widget) append $htext(widget).print\n\%%\% button.}\n");
743 fprintf(HEAP_PROFILE,"barchart .graph -tile bgTexture\n");
745 // This is where the actual data comes in
747 fprintf(HEAP_PROFILE,"vector X ");
748 names_of_heap_objects(HEAP_PROFILE,ho_m);
749 fprintf(HEAP_PROFILE,"\nX set { ");
750 PrintXaxis(HEAP_PROFILE,th);
751 fprintf(HEAP_PROFILE," }\n");
753 print_heap_object_matrix(HEAP_PROFILE,th, ho_m);
755 // NAMES FOR THE ATTRIBUTES
756 fprintf(HEAP_PROFILE,"set attributes {\n");
757 names_and_colour_assignment(HEAP_PROFILE,ho_m);
758 fprintf(HEAP_PROFILE,"}\n");
760 fprintf(HEAP_PROFILE,"foreach {label yData color stipple} $attributes {\n .graph element create $yData -label $label -bd 1 \\\n -ydata $yData -xdata X -fg ${color}3 -bg ${color}1 -stipple $stipple\n}\n");
761 fprintf(HEAP_PROFILE,".header.stacked invoke\n");
762 fprintf(HEAP_PROFILE,"scrollbar .xbar -command { .graph axis view x } -orient horizontal\nscrollbar .ybar -command { .graph axis view y } -orient vertical\n.graph axis configure x -scrollcommand { .xbar set } -logscale no -loose no\n.graph axis configure y -scrollcommand { .ybar set } -logscale no -loose no\n");
763 fprintf(HEAP_PROFILE,"table . \\\n 0,0 .title -fill x \\\n 1,0 .header -fill x \\\n 2,0 .graph -fill both \\\n 3,0 .xbar -fill x \\\n 5,0 .footer -fill x\n");
764 fprintf(HEAP_PROFILE,"table configure . r0 r1 r3 r4 r5 -resize none\n");
765 fprintf(HEAP_PROFILE,"Blt_ZoomStack .graph\nBlt_Crosshairs .graph\nBlt_ActiveLegend .graph\nBlt_ClosestPoint .graph\n");
766 fprintf(HEAP_PROFILE,".graph marker bind all <B2-Motion> {\n set coords [\%W invtransform \%%x \%y]\n catch { \%W marker configure [\%W marker get current] -coords $coords }\n}\n.graph marker bind all <Enter> {\n set marker [\%W marker get current]\n catch { %W marker configure $marker -bg green}\n}\n.graph marker bind all <Leave> {\n set marker [\%W marker get current]\n catch { %W marker configure $marker -bg \"\"}\n}\n");
771 /* -----------------------------------------------------------------------------
772 * Read and create the raw profile data structure
773 * -------------------------------------------------------------------------- */
775 /* void readRawProfile(FILE *fptr,int *nonodes) { */
777 void readRawProfile(FILE *fp,int *nonodes, int MaxNoNodes) {
778 char line[MAX_PROFILE_LINE_LENGTH];
779 char stack[MAX_PROFILE_LINE_LENGTH];
780 char rest[MAX_PROFILE_LINE_LENGTH];
781 int i,nolines,sstepline,syncs;
784 float comp_max, comp_avg, comp_min, /* SYNCS */
785 comm_max, comm_avg, comm_min, /* COMP */
786 comp_idle_max, comp_idle_avg, comp_idle_min; /* COMM */
788 /* Cost relationships are comp=scc, comm=ticks, comp_idle=bytes */
790 long int hmax,havg,hmin; /* COMPIDLE */
792 /* set to zero for now. Might use these later for heap costs. */
794 int *result; /* Something to do with daVinci? */
796 /* GHC specific variables */
798 int a,b,c,d,x,y,z,count, next, throw;
801 char e[MAX_STRING_SIZE];
802 char f[MAX_STRING_SIZE];
803 char g[MAX_STRING_SIZE];
804 char lline[MAX_PROFILE_LINE_LENGTH];
806 /* identifiers generated by the XML handler */
807 char *ccentre=">>cost_centre";
808 char *ccstack=">>cost_centre_stack";
809 char *sccsample=">>scc_sample";
810 char *heapsample=">>heap_sample";
811 char *heapupdate=">>heap_update";
812 char *heapobject=">>heap_object";
813 char *typeconstr=">>type_constr";
821 heap_object_matrix *ho_m;
822 type_constr_matrix *tc_m;
827 HEAP_PROFILE = fopen("GHCbarchart.tcl", "w");
828 if (HEAP_PROFILE == NULL){
829 fprintf(stderr,"tcl script generator: ERROR- GHCbarchart.tcl cannot be created\a\n");
833 th = (p_TheHeap) malloc (sizeof(TheHeap));
834 cc_m = (p_cc_matrix) malloc (sizeof(cc_matrix));
835 //cc_m = (p_cc_matrix) calloc(MAX_IDENTIFIERS,sizeof(_cc_));
836 ccs_m = (p_ccs_matrix) malloc (sizeof(ccs_matrix));
837 ho_m = (p_heap_object_matrix) malloc (sizeof(heap_object_matrix));
838 tc_m = (p_type_constr_matrix) malloc (sizeof(type_constr_matrix));
840 /* End of GHC specific variables */
842 //fprintf(log,"Number 1 %i \n",MAX_IDENTIFIERS*sizeof(_cc_));
843 //fprintf(log,"Number 2 %i \n",sizeof(cc_matrix));
845 nolines=0; /* Number of lines read in from profile log file */
851 initialise_cc_matrix(cc_m);
852 initialise_ccs_matrix(ccs_m);
853 initialise_heap_object_matrix(ho_m);
854 initialise_type_constr_matrix(tc_m);
855 initialise_TheHeap(th);
857 fprintf(log,"MAX_IDENTIFIERS = %i \n",MAX_IDENTIFIERS);
859 /* end GHC specific */
862 fill_cc_matrix(cc_m,"CAF:REPOSITORY","PROFILER","PROFILER",MAX_IDENTIFIERS-1);
863 fill_ccs_matrix(ccs_m,MAX_IDENTIFIERS-1,1,0.0,0.0,0.0,0,-1,MAX_IDENTIFIERS-1);
867 This builds a node in the graph called CAF:REPOSITORY, which can be
868 found off the root node. All CAFs are subsequently hung from this node
869 which means the node node can be hidden using the abstraction
870 mechanisms provided by daVinci.
875 /* This is the GHC file handler which reads the lines from the profile log file and */
876 /* puts the stack and cost information in the raw profile data structure */
878 while (fscanf(fp,"%s",lline))
880 /* Kill the end of the logfile with the ">>" string */
881 if (strcmp(lline,ending)==0) break;
883 /* Deal with the cost centres */
884 if (strcmp(ccentre,lline)==0)
887 //while (fscanf(fp," %i %[^ ] %[^ ] %s", &z, e, f, g)!=0)
888 while (fscanf(fp," %i %[^ ] %s", &z, e, f)!=0)
890 fprintf(log,"Declaring cost centre `%i %s %s %s' \n",z,e,f,f);
892 fill_cc_matrix(cc_m,e,f,f,z);
899 /* Deal with the cost centre stacks */
900 if (strcmp(ccstack,lline)==0)
903 while (fscanf(fp,"%i %i %i",&a,&d,&b)!=0)
905 if (d==1) /* of size one */
907 fprintf(log,"Declaring cost centre stack `%i %i %i'\n",a,d,b);
908 fill_ccs_matrix(ccs_m,b,-1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
910 if (d==2) /* of size > 1 */
915 fprintf(log,"Declaring cost centre stack `%i %i %i %i'\n",a,d,b,c);
916 if ((c==1)&&!(strncmp((*cc_m)[b].name,"CAF",2)))
917 // fill_ccs_matrix(ccs_m,b,MAX_IDENTIFIERS-1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
918 /* The line above hangs all CAFs off the CAF:REPOSITORY node
919 in the daVinci graph. For programs which have a small
920 number of CAFs this works nicely. However, when the
921 number of CAFs become very large (eg +200) then the
922 daVinci graph begins to look horid and, after (say)
923 +500 CAF nodes, becomes very slow to load. So to
924 fix this we replace the code with the line below.
926 if (!(strncmp((*cc_m)[b].name,"CAF:main",7)))
927 /* Treat CAF:main as a normal node */
928 fill_ccs_matrix(ccs_m,b,c,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
931 //add_ccs_costs(ccs_m,0,MAX_IDENTIFIERS-1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,0);
932 fill_ccs_matrix(ccs_m,MAX_IDENTIFIERS-1,1,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
933 /* This does not even bother registering the new CAFs
934 as daVinci nodes, but instead just merges the CAF
935 with the CAF:REPOSITORY node. This greatly reduces
936 the number of CAFs daVinci has to deal with, though
937 may make the graph look a little different!
939 Also note that now Simon has changed the semantics,
940 you will want to treat adding CAF nodes in a
941 different way to adding normal program nodes
945 fill_ccs_matrix(ccs_m,b,c,(*ccs_m)[a].scc,(*ccs_m)[a].ticks,(*ccs_m)[a].bytes,0,-1,a);
953 /* Deal with the scc_samples */
954 if (strcmp(sccsample,lline)==0)
957 while (fscanf(fp,"%i %i %i %i",&a,&d,&b,&c))
959 fprintf(log,"Loading scc_samples `%i %i %i %i'\n",a,d,b,c);
960 add_ccs_costs(ccs_m,0,a,d,b,c,0,0);
963 } /* end sccsample if */
967 /* Deal with the heap samples */
968 if (strcmp(heapsample,lline)==0)
971 while (fscanf(fp,"%i %i %i",&a,&d,&b))
973 fprintf(log,"Loading heap_samples `%i %i %i'\n",a,d,b);
974 add_heap_sample_costs(ccs_m,0,a,0,0,0,d,b);
977 } /* end heapsample if */
981 /* Deal with the heap objects */
982 if (strcmp(heapobject,lline)==0)
985 while (fscanf(fp,"%i %i",&a,&d))
989 fscanf(fp," %s %i",e,&b);
990 add_heap_object(ho_m,a,d,e,b);
995 add_heap_object(ho_m,a,d,e,-1);
999 } /* end heapobject if */
1003 /* Deal with the type constructors */
1004 if (strcmp(typeconstr,lline)==0)
1007 while (fscanf(fp,"%i %s %s",&a,e,f))
1009 add_type_constr_object(tc_m,a,e,f);
1012 } /* end type constructor if */
1016 /* Deal with the heap_updates */
1017 if (strcmp(heapupdate,lline)==0)
1020 while (fscanf(fp,"%i %i %i %i %i %i",&a,&d,&b,&c,&z,&x))
1022 add_to_TheHeap(th,a,b,c,z);
1023 fprintf(log,"Adding heap sample %i %i %i %i\n",a,b,c,z);
1024 while (x) /* more than one sample */
1026 fscanf(fp," %i %i %i %i",&b,&c,&z,&x);
1027 add_to_TheHeap(th,a,b,c,z);
1028 fprintf(log,"Adding heap sample %i %i %i %i\n",a,b,c,z);
1033 } /* end heap update if */
1035 } /* end type constructor else */
1037 } /* end heapobject else */
1039 } /* end heapsample else */
1040 } /* end sccsample else */
1041 } /* end ccstack else */
1042 } /* end ccstack if */
1045 print_cc_matrix(cc_m);
1046 print_ccs_matrix(ccs_m);
1047 fprintf(log,"There are %i stacks\n",CountStacks(ccs_m));
1048 print_type_constr_matrix(tc_m);
1050 /* Functions for heap profile */
1052 fprintf(log,"The units for the x axis are \n");
1055 fprintf(log,"There are %i distinct heap objects\n",number_of_heap_objects(ho_m));
1056 names_of_heap_objects(log,ho_m);
1057 names_and_colour_assignment(log,ho_m);
1058 print_heap_object_matrix(log,th,ho_m);
1060 PrintAllStacks(ccs_m,cc_m);
1061 /* comment out line below to remove the heap profile generator */
1062 produce_HEAP_PROFILE(HEAP_PROFILE,th,ho_m);
1063 fclose(HEAP_PROFILE);
1065 /* End of GHC file handler */
1068 /* Now process the stack matrix */
1070 for (newloop=0;newloop<MAX_IDENTIFIERS;newloop++)
1071 { if ((*ccs_m)[newloop].cc != 0)
1075 FormStack2(ccs_m,cc_m,newloop,stack);
1078 comp_max = (float)(*ccs_m)[newloop].scc;
1079 comp_avg = (float)(*ccs_m)[newloop].scc;
1080 comp_min = (float)(*ccs_m)[newloop].scc;
1081 comm_max = (float)(*ccs_m)[newloop].ticks;
1082 comm_avg = (float)(*ccs_m)[newloop].ticks;
1083 comm_min = (float)(*ccs_m)[newloop].ticks;
1084 comp_idle_max = (float)(*ccs_m)[newloop].bytes;
1085 comp_idle_avg = (float)(*ccs_m)[newloop].bytes;
1086 comp_idle_min = (float)(*ccs_m)[newloop].bytes;
1087 hmax = 0.0; havg = 0.0; hmin = 0.0;
1089 /* Dynamic memory allocation for raw_profile data structure */
1091 if (raw_profile_next==raw_profile_size) enlargeRawProfile();
1093 /* Assign data from single logfile entry to raw_profile data structure */
1094 /* this deals with the cost metrics */
1096 raw_profile[raw_profile_next].active = 1;
1097 raw_profile[raw_profile_next].cost.syncs = syncs;
1098 raw_profile[raw_profile_next].cost.comp_max = comp_max;
1099 raw_profile[raw_profile_next].cost.comp_avg = comp_avg;
1100 raw_profile[raw_profile_next].cost.comp_min = comp_min;
1101 raw_profile[raw_profile_next].cost.comm_max = comm_max;
1102 raw_profile[raw_profile_next].cost.comm_avg = comm_avg;
1103 raw_profile[raw_profile_next].cost.comm_min = comm_min;
1104 raw_profile[raw_profile_next].cost.comp_idle_max= comp_idle_max;
1105 raw_profile[raw_profile_next].cost.comp_idle_avg= comp_idle_avg;
1106 raw_profile[raw_profile_next].cost.comp_idle_min= comp_idle_min;
1107 raw_profile[raw_profile_next].cost.hrel_max = hmax;
1108 raw_profile[raw_profile_next].cost.hrel_avg = havg;
1109 raw_profile[raw_profile_next].cost.hrel_min = hmin;
1111 /* this deals with the stack itself */
1113 raw_profile[raw_profile_next].stack=calloc(MAX_STACK_DEPTH,
1115 if (raw_profile[raw_profile_next].stack==NULL) {
1116 fprintf(stderr,"{readRawProfile} unable to allocate stack entry");
1120 fprintf(log,"STACK=\"%s\"\n",stack);
1121 raw_profile[raw_profile_next].stack_size=1;
1122 /* move the stack read frame to the first space (or comma) in the stack string */
1123 for(ptr=stack; ((*ptr)!=' ') && (*ptr!=',');ptr++) {}
1124 fprintf(log,"TOS=%d at line %d\n",*ptr,sstepline);
1126 /* to distinguish the head of the stack from the rest */
1127 /* if read frame points to space you are at the head of the stack */
1129 /* raw_profile[raw_profile_next].stack[0]
1130 =lookupSymbolTable(CG_SSTEP,sstepline,(*ptr='\0',stack)); */
1131 /* This line has changed as GHC treats its cost-centres in a different */
1132 /* way to BSP. There is no distinction between 'a cost centre at line x' */
1133 /* and a normal cost centre. The fix is easy, just treat all cost centres, */
1134 /* even those at the head of the stack in the same way. */
1135 raw_profile[raw_profile_next].stack[0]
1136 =lookupSymbolTable(CG_STACK,sstepline,(*ptr='\0',stack));
1138 /* otherwise you are looking at just another stack element */
1139 raw_profile[raw_profile_next].stack[0]
1140 =lookupSymbolTable(CG_STACK,sstepline,(*ptr='\0',stack));
1142 ptr++; /* move the read frame on one */
1144 for(;*ptr;ptr++) { /* find the next element in the stack */
1147 if (Verbose) fprintf(log,"NAME=\"%s\"\n",drag); /* name of the next element */
1148 if (!ignore_function(drag)) {
1149 raw_profile[raw_profile_next].stack[
1150 raw_profile[raw_profile_next].stack_size++]
1151 = lookupSymbolTable(CG_STACK,0,drag); /* add element to the raw_profile */
1157 /* create cost object */
1159 raw_profile[raw_profile_next].cost.proc
1160 =calloc(bsp_p,sizeof(object_cost_proc));
1161 if (raw_profile[raw_profile_next].cost.proc==NULL) {
1162 fprintf(stderr,"Unable to allocate storage");
1166 /* process the HREL information - one set for every BSP process */
1168 for(i=0;i<bsp_p;i++) {
1170 raw_profile[raw_profile_next].cost.proc[i].proc_comp = 0.0;
1171 raw_profile[raw_profile_next].cost.proc[i].proc_comm = 0.0;
1172 raw_profile[raw_profile_next].cost.proc[i].proc_comp_idle= 0.0;
1173 raw_profile[raw_profile_next].cost.proc[i].proc_hrel_in = 0;
1174 raw_profile[raw_profile_next].cost.proc[i].proc_hrel_out = 0;
1178 raw_profile_next++; /* Increase the raw profile data structure counter */
1179 nolines++; /* Increase the number of lines read */
1181 strcpy(stack,""); /* reset the stack */
1182 } /* end of new if statement */
1183 } /* end of new for loop */
1185 *nonodes = symbol_table_next;
1186 fprintf(log,"%s: read %d lines from profile.Graph contains %i nodes.
1187 \n",Pgm,nolines,symbol_table_next);
1189 free_cc_matrix(cc_m); /* be nice and clean up the cost centre matrix */
1192 /* -----------------------------------------------------------------------------
1193 * Pretty print the raw profile data
1194 * -------------------------------------------------------------------------- */
1196 void printRawProfile() {
1201 fprintf(log,"\n\nRAW DATA:\n");
1202 for(i=0;i<raw_profile_next;i++) {
1203 cost = &raw_profile[i].cost;
1204 stack = raw_profile[i].stack;
1205 fprintf(log,"Stack=[");
1206 for(j=0;j<raw_profile[i].stack_size;j++)
1207 printSymbolTable_entry(stack[j]);
1208 fprintf(log,"] %d Syncs %f Comp %f Comm %f Wait\n\n",
1209 cost->syncs,cost->comp_max,cost->comm_max,cost->comp_idle_max);
1213 /* -----------------------------------------------------------------------------
1214 * Create connectivity matrix
1215 * -------------------------------------------------------------------------- */
1217 void createConnectivityMatrix(int NoNodes,Matrix *graph,
1218 Matrix *costs,int *root, int inherit) {
1219 object_cost zero_cost,*update;
1223 zero_cost.comp_max =0.0;
1224 zero_cost.comp_avg =0.0;
1225 zero_cost.comp_min =0.0;
1226 zero_cost.comm_max =0.0;
1227 zero_cost.comm_avg =0.0;
1228 zero_cost.comm_min =0.0;
1229 zero_cost.comp_idle_max=0.0;
1230 zero_cost.comp_idle_avg=0.0;
1231 zero_cost.comp_idle_min=0.0;
1232 zero_cost.hrel_max =0;
1233 zero_cost.hrel_avg =0;
1234 zero_cost.hrel_min =0;
1236 zero_cost.proc = NULL;
1237 *graph = newMat(NoNodes,NoNodes,sizeof(int),(i=0,&i));
1238 *costs = newMat(NoNodes,1,sizeof(object_cost),&zero_cost);
1239 for(i=0;i<NoNodes;i++) {
1240 update=&Mat(object_cost,*costs,i,0);
1241 update->proc=calloc(bsp_p,sizeof(object_cost_proc));
1242 if (update->proc==NULL){
1243 fprintf(stderr,"Unable to allocate storage");
1246 for(j=0;j<bsp_p;j++) {
1247 update->proc[j].proc_comp =0.0;
1248 update->proc[j].proc_comm =0.0;
1249 update->proc[j].proc_comp_idle =0.0;
1250 update->proc[j].proc_hrel_in =0;
1251 update->proc[j].proc_hrel_out =0;
1255 for(i=0;i<raw_profile_next;i++) {
1256 if (raw_profile[i].active) {
1257 this = raw_profile[i].stack[0];
1259 Mat(int,*graph,this,next) = 1;
1260 update = &Mat(object_cost,*costs,next,0);
1261 add_costs(update,raw_profile[i].cost);
1262 for(j=1;j<raw_profile[i].stack_size;j++) {
1264 next = raw_profile[i].stack[j];
1265 Mat(int,*graph,next,this)=1;
1266 update = &Mat(object_cost,*costs,next,0);
1267 /* include this line for INHERITANCE; remove it for not! */
1268 if (inherit) add_costs(update,raw_profile[i].cost);
1272 *root = raw_profile[0].stack[raw_profile[0].stack_size-1];
1274 /* Check graph isn't empty */
1275 if (!Mat_dense(*costs,*root,0)) *root=-1;
1278 void printConnectivityMatrix(Matrix graph,Matrix costs,int root) {
1282 fprintf(log,"Root node is %d\n",root);
1283 for(i=0;i<graph.rows;i++) {
1284 fprintf(log,"%4d)",i);
1285 printSymbolTable_entry(i);
1286 cost = Mat(object_cost,costs,i,0);
1287 fprintf(log,"%d %f %f %f\n\tBranch=[",
1288 cost.syncs,cost.comp_max,cost.comm_max,cost.comp_idle_max);
1289 for(j=0;j<graph.cols;j++)
1290 if (Mat_dense(graph,i,j)) fprintf(log,"%d ",j);
1291 fprintf(log,"]\n\n");