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