1 #ifndef lint 2 static char *sccsid = "@(#)printgprof.c 1.9 (Berkeley) 06/14/82"; 3 #endif lint 4 5 #include "gprof.h" 6 7 printprof() 8 { 9 register nltype *np; 10 nltype **sortednlp; 11 int index; 12 13 printf( "\ngranularity: each sample hit covers %d byte(s)" , 14 (long) scale * sizeof(UNIT) ); 15 printf( " for %.2f%% of %.2f seconds\n\n" , 100.0/totime , totime / HZ ); 16 actime = 0.0; 17 flatprofheader(); 18 /* 19 * Sort the symbol table in by time 20 */ 21 sortednlp = (nltype **) calloc( nname , sizeof(nltype *) ); 22 if ( sortednlp == (nltype **) 0 ) { 23 fprintf( stderr , "[printprof] ran out of memory for time sorting\n" ); 24 } 25 for ( index = 0 ; index < nname ; index += 1 ) { 26 sortednlp[ index ] = &nl[ index ]; 27 } 28 qsort( sortednlp , nname , sizeof(nltype *) , timecmp ); 29 for ( index = 0 ; index < nname ; index += 1 ) { 30 np = sortednlp[ index ]; 31 flatprofline( np ); 32 } 33 actime = 0.0; 34 } 35 36 timecmp( npp1 , npp2 ) 37 nltype **npp1, **npp2; 38 { 39 double timediff; 40 long calldiff; 41 42 timediff = (*npp2) -> time - (*npp1) -> time; 43 if ( timediff > 0.0 ) 44 return 1 ; 45 if ( timediff < 0.0 ) 46 return -1; 47 calldiff = (*npp2) -> ncall - (*npp1) -> ncall; 48 if ( calldiff > 0 ) 49 return 1; 50 if ( calldiff < 0 ) 51 return -1; 52 return( strcmp( (*npp1) -> name , (*npp2) -> name ) ); 53 } 54 55 /* 56 * header for flatprofline 57 */ 58 flatprofheader() 59 { 60 61 if ( bflag ) { 62 printblurb( "flat.blurb" ); 63 } 64 printf( "%5.5s %7.7s %7.7s %7.7s %-8.8s\n" , 65 "%time" , "cumsecs" , "seconds" , "calls" , "name" ); 66 } 67 68 flatprofline( np ) 69 register nltype *np; 70 { 71 72 if ( zflag == 0 && np -> ncall == 0 && np -> time == 0 ) { 73 return; 74 } 75 actime += np -> time; 76 printf( "%5.1f %7.2f %7.2f" , 77 100 * np -> time / totime , actime / HZ , np -> time / HZ ); 78 if ( np -> ncall != 0 ) { 79 printf( " %7d" , np -> ncall ); 80 } else { 81 printf( " %7.7s" , "" ); 82 } 83 printf( " %s\n" , np -> name ); 84 } 85 86 gprofheader() 87 { 88 89 if ( bflag ) { 90 printblurb( "callg.blurb" ); 91 } 92 printf( "\ngranularity: each sample hit covers %d byte(s)" , 93 (long) scale * sizeof(UNIT) ); 94 printf( " for %.2f%% of %.2f seconds\n\n" , 95 100.0/printtime , printtime / HZ ); 96 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , 97 "" , "" , "" , "" , "called" , "total" , "parents" , "" ); 98 printf( "%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n" , 99 "index" , "%time" , "self" , "descendents" , 100 "called" , "self" , "name" , "index" ); 101 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n" , 102 "" , "" , "" , "" , "called" , "total" , "children" , "" ); 103 printf( "\n" ); 104 } 105 106 gprofline( np ) 107 register nltype *np; 108 { 109 char kirkbuffer[ BUFSIZ ]; 110 111 sprintf( kirkbuffer , "[%d]" , np -> index ); 112 printf( "%-6.6s %5.1f %7.2f %11.2f" , 113 kirkbuffer , 114 100 * ( np -> time + np -> childtime ) / printtime , 115 np -> time / HZ , 116 np -> childtime / HZ ); 117 if ( ( np -> ncall + np -> selfcalls ) != 0 ) { 118 printf( " %7d" , np -> ncall ); 119 if ( np -> selfcalls != 0 ) { 120 printf( "+%-7d " , np -> selfcalls ); 121 } else { 122 printf( " %7.7s " , "" ); 123 } 124 } else { 125 printf( " %7.7s %7.7s " , "" , "" ); 126 } 127 printname( np ); 128 printf( "\n" ); 129 } 130 131 printgprof() 132 { 133 nltype **timesortnlp; 134 int index; 135 nltype *parentp; 136 137 /* 138 * Now, sort by time + childtime. 139 * sorting both the regular function names 140 * and cycle headers. 141 */ 142 timesortnlp = (nltype **) calloc( nname + ncycle , sizeof(nltype *) ); 143 if ( timesortnlp == (nltype **) 0 ) { 144 fprintf( stderr , "%s: ran out of memory for sorting\n" , whoami ); 145 } 146 for ( index = 0 ; index < nname ; index++ ) { 147 timesortnlp[index] = &nl[index]; 148 } 149 for ( index = 1 ; index <= ncycle ; index++ ) { 150 timesortnlp[nname+index-1] = &cyclenl[index]; 151 } 152 qsort( timesortnlp , nname + ncycle , sizeof(nltype *) , totalcmp ); 153 for ( index = 0 ; index < nname + ncycle ; index++ ) { 154 timesortnlp[ index ] -> index = index + 1; 155 } 156 /* 157 * Now, print out the structured profiling list 158 */ 159 printf( "\f\n" ); 160 gprofheader(); 161 for ( index = 0 ; index < nname + ncycle ; index ++ ) { 162 parentp = timesortnlp[ index ]; 163 if ( zflag == 0 && 164 parentp -> ncall == 0 && 165 parentp -> selfcalls == 0 && 166 parentp -> time == 0 && 167 parentp -> childtime == 0 ) { 168 continue; 169 } 170 if ( ! parentp -> printflag ) { 171 continue; 172 } 173 if ( parentp -> name == 0 && parentp -> cycleno != 0 ) { 174 /* 175 * cycle header 176 */ 177 printcycle( parentp ); 178 printmembers( parentp ); 179 } else { 180 printparents( parentp ); 181 gprofline( parentp ); 182 printchildren( parentp ); 183 } 184 printf( "\n" ); 185 printf( "-----------------------------------------------\n" ); 186 printf( "\n" ); 187 } 188 } 189 190 /* 191 * sort by decreasing total time (time+childtime) 192 * if times are equal, but one is a cycle header, 193 * say that's first (e.g. less, i.e. -1). 194 * if one's name doesn't have an underscore and the other does, 195 * say the one is first. 196 * all else being equal, sort by names. 197 */ 198 int 199 totalcmp( npp1 , npp2 ) 200 nltype **npp1; 201 nltype **npp2; 202 { 203 register nltype *np1 = *npp1; 204 register nltype *np2 = *npp2; 205 double diff; 206 207 diff = ( np1 -> time + np1 -> childtime ) 208 - ( np2 -> time + np2 -> childtime ); 209 if ( diff < 0.0 ) 210 return 1; 211 if ( diff > 0.0 ) 212 return -1; 213 if ( np1 -> name == 0 && np1 -> cycleno != 0 ) 214 return -1; 215 if ( np2 -> name == 0 && np2 -> cycleno != 0 ) 216 return 1; 217 if ( np1 -> name == 0 ) 218 return -1; 219 if ( np2 -> name == 0 ) 220 return 1; 221 if ( *(np1 -> name) != '_' && *(np2 -> name) == '_' ) 222 return -1; 223 if ( *(np1 -> name) == '_' && *(np2 -> name) != '_' ) 224 return 1; 225 return strcmp( np1 -> name , np2 -> name ); 226 } 227 228 printparents( childp ) 229 nltype *childp; 230 { 231 nltype *parentp; 232 arctype *arcp; 233 nltype *cycleheadp; 234 235 if ( childp -> cyclehead != 0 ) { 236 cycleheadp = childp -> cyclehead; 237 } else { 238 cycleheadp = childp; 239 } 240 if ( childp -> parents == 0 ) { 241 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" , 242 "" , "" , "" , "" , "" , "" ); 243 return; 244 } 245 sortparents( childp ); 246 for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { 247 parentp = arcp -> arc_parentp; 248 if ( childp == parentp || 249 ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { 250 /* 251 * selfcall or call among siblings 252 */ 253 printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , 254 "" , "" , "" , "" , 255 arcp -> arc_count , "" ); 256 printname( parentp ); 257 printf( "\n" ); 258 } else { 259 /* 260 * regular parent of child 261 */ 262 printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , 263 "" , "" , 264 arcp -> arc_time / HZ , arcp -> arc_childtime / HZ , 265 arcp -> arc_count , cycleheadp -> ncall ); 266 printname( parentp ); 267 printf( "\n" ); 268 } 269 } 270 } 271 272 printchildren( parentp ) 273 nltype *parentp; 274 { 275 nltype *childp; 276 arctype *arcp; 277 278 sortchildren( parentp ); 279 arcp = parentp -> children; 280 for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 281 childp = arcp -> arc_childp; 282 if ( childp == parentp || 283 ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { 284 /* 285 * self call or call to sibling 286 */ 287 printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , 288 "" , "" , "" , "" , arcp -> arc_count , "" ); 289 printname( childp ); 290 printf( "\n" ); 291 } else { 292 /* 293 * regular child of parent 294 */ 295 printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , 296 "" , "" , 297 arcp -> arc_time / HZ , arcp -> arc_childtime / HZ , 298 arcp -> arc_count , childp -> cyclehead -> ncall ); 299 printname( childp ); 300 printf( "\n" ); 301 } 302 } 303 } 304 305 printname( selfp ) 306 nltype *selfp; 307 { 308 309 if ( selfp -> name != 0 ) { 310 printf( "%s" , selfp -> name ); 311 # ifdef DEBUG 312 if ( debug & DFNDEBUG ) { 313 printf( "{%d} " , selfp -> toporder ); 314 } 315 # endif DEBUG 316 } 317 if ( selfp -> cycleno != 0 ) { 318 printf( "\t<cycle %d>" , selfp -> cycleno ); 319 } 320 if ( selfp -> index != 0 ) { 321 if ( selfp -> printflag ) { 322 printf( " [%d]" , selfp -> index ); 323 } else { 324 printf( " (%d)" , selfp -> index ); 325 } 326 } 327 } 328 329 sortchildren( parentp ) 330 nltype *parentp; 331 { 332 arctype *arcp; 333 arctype *detachedp; 334 arctype sorted; 335 arctype *prevp; 336 337 /* 338 * unlink children from parent, 339 * then insertion sort back on to sorted's children. 340 * *arcp the arc you have detached and are inserting. 341 * *detachedp the rest of the arcs to be sorted. 342 * sorted arc list onto which you insertion sort. 343 * *prevp arc before the arc you are comparing. 344 */ 345 sorted.arc_childlist = 0; 346 for ( arcp = parentp -> children , detachedp = arcp -> arc_childlist ; 347 arcp ; 348 arcp = detachedp , detachedp = detachedp -> arc_childlist ) { 349 /* 350 * consider *arcp as disconnected 351 * insert it into sorted 352 */ 353 for ( prevp = &sorted ; 354 prevp -> arc_childlist ; 355 prevp = prevp -> arc_childlist ) { 356 if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) { 357 break; 358 } 359 } 360 arcp -> arc_childlist = prevp -> arc_childlist; 361 prevp -> arc_childlist = arcp; 362 } 363 /* 364 * reattach sorted children to parent 365 */ 366 parentp -> children = sorted.arc_childlist; 367 } 368 369 sortparents( childp ) 370 nltype *childp; 371 { 372 arctype *arcp; 373 arctype *detachedp; 374 arctype sorted; 375 arctype *prevp; 376 377 /* 378 * unlink parents from child, 379 * then insertion sort back on to sorted's parents. 380 * *arcp the arc you have detached and are inserting. 381 * *detachedp the rest of the arcs to be sorted. 382 * sorted arc list onto which you insertion sort. 383 * *prevp arc before the arc you are comparing. 384 */ 385 sorted.arc_parentlist = 0; 386 for ( arcp = childp -> parents , detachedp = arcp -> arc_parentlist ; 387 arcp ; 388 arcp = detachedp , detachedp = detachedp -> arc_parentlist ) { 389 /* 390 * consider *arcp as disconnected 391 * insert it into sorted 392 */ 393 for ( prevp = &sorted ; 394 prevp -> arc_parentlist ; 395 prevp = prevp -> arc_parentlist ) { 396 if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) { 397 break; 398 } 399 } 400 arcp -> arc_parentlist = prevp -> arc_parentlist; 401 prevp -> arc_parentlist = arcp; 402 } 403 /* 404 * reattach sorted arcs to child 405 */ 406 childp -> parents = sorted.arc_parentlist; 407 } 408 409 /* 410 * print a cycle header 411 */ 412 printcycle( cyclep ) 413 nltype *cyclep; 414 { 415 char kirkbuffer[ BUFSIZ ]; 416 417 sprintf( kirkbuffer , "[%d]" , cyclep -> index ); 418 printf( "%-6.6s %5.1f %7.2f %11.2f %7d" , 419 kirkbuffer , 420 100 * ( cyclep -> time + cyclep -> childtime ) / printtime , 421 cyclep -> time / HZ , 422 cyclep -> childtime / HZ , 423 cyclep -> ncall ); 424 if ( cyclep -> selfcalls != 0 ) { 425 printf( "+%-7d" , cyclep -> selfcalls ); 426 } else { 427 printf( " %7.7s" , "" ); 428 } 429 printf( " <cycle %d as a whole>\t[%d]\n" , 430 cyclep -> cycleno , cyclep -> index ); 431 } 432 433 /* 434 * print the members of a cycle 435 */ 436 printmembers( cyclep ) 437 nltype *cyclep; 438 { 439 nltype *memberp; 440 441 sortmembers( cyclep ); 442 for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { 443 printf( "%6.6s %5.5s %7.2f %11.2f %7d" , 444 "" , "" , memberp -> time / HZ , memberp -> childtime / HZ , 445 memberp -> ncall ); 446 if ( memberp -> selfcalls != 0 ) { 447 printf( "+%-7d" , memberp -> selfcalls ); 448 } else { 449 printf( " %7.7s" , "" ); 450 } 451 printf( " " ); 452 printname( memberp ); 453 printf( "\n" ); 454 } 455 } 456 457 /* 458 * sort members of a cycle 459 */ 460 sortmembers( cyclep ) 461 nltype *cyclep; 462 { 463 nltype *todo; 464 nltype *doing; 465 nltype *prev; 466 467 /* 468 * detach cycle members from cyclehead, 469 * and insertion sort them back on. 470 */ 471 todo = cyclep -> cnext; 472 cyclep -> cnext = 0; 473 for ( doing = todo , todo = doing -> cnext ; 474 doing ; 475 doing = todo , todo = doing -> cnext ) { 476 for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) { 477 if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) { 478 break; 479 } 480 } 481 doing -> cnext = prev -> cnext; 482 prev -> cnext = doing; 483 } 484 } 485 486 /* 487 * major sort is on time + childtime, 488 * next is sort on ncalls + selfcalls. 489 */ 490 int 491 membercmp( this , that ) 492 nltype *this; 493 nltype *that; 494 { 495 double thistime = this -> time + this -> childtime; 496 double thattime = that -> time + that -> childtime; 497 long thiscalls = this -> ncall + this -> selfcalls; 498 long thatcalls = that -> ncall + that -> selfcalls; 499 500 if ( thistime > thattime ) { 501 return GREATERTHAN; 502 } 503 if ( thistime < thattime ) { 504 return LESSTHAN; 505 } 506 if ( thiscalls > thatcalls ) { 507 return GREATERTHAN; 508 } 509 if ( thiscalls < thatcalls ) { 510 return LESSTHAN; 511 } 512 return EQUALTO; 513 } 514 /* 515 * compare two arcs to/from the same child/parent. 516 * - if one arc is a self arc, it's least. 517 * - if one arc is within a cycle, it's less than. 518 * - if both arcs are within a cycle, compare arc counts. 519 * - if neither arc is within a cycle, compare with 520 * time + childtime as major key 521 * arc count as minor key 522 */ 523 int 524 arccmp( thisp , thatp ) 525 arctype *thisp; 526 arctype *thatp; 527 { 528 nltype *thisparentp = thisp -> arc_parentp; 529 nltype *thischildp = thisp -> arc_childp; 530 nltype *thatparentp = thatp -> arc_parentp; 531 nltype *thatchildp = thatp -> arc_childp; 532 double thistime; 533 double thattime; 534 535 # ifdef DEBUG 536 if ( debug & TIMEDEBUG ) { 537 printf( "[arccmp] " ); 538 printname( thisparentp ); 539 printf( " calls " ); 540 printname ( thischildp ); 541 printf( " %f + %f %d/%d\n" , 542 thisp -> arc_time , thisp -> arc_childtime , 543 thisp -> arc_count , thischildp -> ncall ); 544 printf( "[arccmp] " ); 545 printname( thatparentp ); 546 printf( " calls " ); 547 printname( thatchildp ); 548 printf( " %f + %f %d/%d\n" , 549 thatp -> arc_time , thatp -> arc_childtime , 550 thatp -> arc_count , thatchildp -> ncall ); 551 printf( "\n" ); 552 } 553 # endif DEBUG 554 if ( thisparentp == thischildp ) { 555 /* this is a self call */ 556 return LESSTHAN; 557 } 558 if ( thatparentp == thatchildp ) { 559 /* that is a self call */ 560 return GREATERTHAN; 561 } 562 if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 && 563 thisparentp -> cycleno == thischildp -> cycleno ) { 564 /* this is a call within a cycle */ 565 if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 566 thatparentp -> cycleno == thatchildp -> cycleno ) { 567 /* that is a call within the cycle, too */ 568 if ( thisp -> arc_count < thatp -> arc_count ) { 569 return LESSTHAN; 570 } 571 if ( thisp -> arc_count > thatp -> arc_count ) { 572 return GREATERTHAN; 573 } 574 return EQUALTO; 575 } else { 576 /* that isn't a call within the cycle */ 577 return LESSTHAN; 578 } 579 } else { 580 /* this isn't a call within a cycle */ 581 if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 582 thatparentp -> cycleno == thatchildp -> cycleno ) { 583 /* that is a call within a cycle */ 584 return GREATERTHAN; 585 } else { 586 /* neither is a call within a cycle */ 587 thistime = thisp -> arc_time + thisp -> arc_childtime; 588 thattime = thatp -> arc_time + thatp -> arc_childtime; 589 if ( thistime < thattime ) 590 return LESSTHAN; 591 if ( thistime > thattime ) 592 return GREATERTHAN; 593 if ( thisp -> arc_count < thatp -> arc_count ) 594 return LESSTHAN; 595 if ( thisp -> arc_count > thatp -> arc_count ) 596 return GREATERTHAN; 597 return EQUALTO; 598 } 599 } 600 } 601 602 printblurb( blurbname ) 603 char *blurbname; 604 { 605 char pathname[ BUFSIZ ]; 606 FILE *blurbfile; 607 int input; 608 609 sprintf( pathname , "%s%s" , BLURBLIB , blurbname ); 610 blurbfile = fopen( pathname , "r" ); 611 if ( blurbfile == NULL ) { 612 perror( pathname ); 613 return; 614 } 615 while ( ( input = getc( blurbfile ) ) != EOF ) { 616 putchar( input ); 617 } 618 fclose( blurbfile ); 619 } 620