1 #ifndef lint 2 static char *sccsid = "@(#)printgprof.c 1.10 (Berkeley) 06/18/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 -> propself + np -> propchild ) / printtime , 115 np -> propself / HZ , 116 np -> propchild / 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 propself + propchild. 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 -> propself == 0 && 167 parentp -> propchild == 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 propagated time 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 -> propself + np1 -> propchild ) 208 - ( np2 -> propself + np2 -> propchild ); 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 if ( np1 -> ncall > np2 -> ncall ) 226 return -1; 227 if ( np1 -> ncall < np2 -> ncall ) 228 return 1; 229 return strcmp( np1 -> name , np2 -> name ); 230 } 231 232 printparents( childp ) 233 nltype *childp; 234 { 235 nltype *parentp; 236 arctype *arcp; 237 nltype *cycleheadp; 238 239 if ( childp -> cyclehead != 0 ) { 240 cycleheadp = childp -> cyclehead; 241 } else { 242 cycleheadp = childp; 243 } 244 if ( childp -> parents == 0 ) { 245 printf( "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n" , 246 "" , "" , "" , "" , "" , "" ); 247 return; 248 } 249 sortparents( childp ); 250 for ( arcp = childp -> parents ; arcp ; arcp = arcp -> arc_parentlist ) { 251 parentp = arcp -> arc_parentp; 252 if ( childp == parentp || 253 ( childp->cycleno != 0 && parentp->cycleno == childp->cycleno ) ) { 254 /* 255 * selfcall or call among siblings 256 */ 257 printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , 258 "" , "" , "" , "" , 259 arcp -> arc_count , "" ); 260 printname( parentp ); 261 printf( "\n" ); 262 } else { 263 /* 264 * regular parent of child 265 */ 266 printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , 267 "" , "" , 268 arcp -> arc_time / HZ , arcp -> arc_childtime / HZ , 269 arcp -> arc_count , cycleheadp -> ncall ); 270 printname( parentp ); 271 printf( "\n" ); 272 } 273 } 274 } 275 276 printchildren( parentp ) 277 nltype *parentp; 278 { 279 nltype *childp; 280 arctype *arcp; 281 282 sortchildren( parentp ); 283 arcp = parentp -> children; 284 for ( arcp = parentp -> children ; arcp ; arcp = arcp -> arc_childlist ) { 285 childp = arcp -> arc_childp; 286 if ( childp == parentp || 287 ( childp->cycleno != 0 && childp->cycleno == parentp->cycleno ) ) { 288 /* 289 * self call or call to sibling 290 */ 291 printf( "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " , 292 "" , "" , "" , "" , arcp -> arc_count , "" ); 293 printname( childp ); 294 printf( "\n" ); 295 } else { 296 /* 297 * regular child of parent 298 */ 299 printf( "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " , 300 "" , "" , 301 arcp -> arc_time / HZ , arcp -> arc_childtime / HZ , 302 arcp -> arc_count , childp -> cyclehead -> ncall ); 303 printname( childp ); 304 printf( "\n" ); 305 } 306 } 307 } 308 309 printname( selfp ) 310 nltype *selfp; 311 { 312 313 if ( selfp -> name != 0 ) { 314 printf( "%s" , selfp -> name ); 315 # ifdef DEBUG 316 if ( debug & DFNDEBUG ) { 317 printf( "{%d} " , selfp -> toporder ); 318 } 319 if ( debug & PROPDEBUG ) { 320 printf( "%5.2f%% " , selfp -> propfraction ); 321 } 322 # endif DEBUG 323 } 324 if ( selfp -> cycleno != 0 ) { 325 printf( "\t<cycle %d>" , selfp -> cycleno ); 326 } 327 if ( selfp -> index != 0 ) { 328 if ( selfp -> printflag ) { 329 printf( " [%d]" , selfp -> index ); 330 } else { 331 printf( " (%d)" , selfp -> index ); 332 } 333 } 334 } 335 336 sortchildren( parentp ) 337 nltype *parentp; 338 { 339 arctype *arcp; 340 arctype *detachedp; 341 arctype sorted; 342 arctype *prevp; 343 344 /* 345 * unlink children from parent, 346 * then insertion sort back on to sorted's children. 347 * *arcp the arc you have detached and are inserting. 348 * *detachedp the rest of the arcs to be sorted. 349 * sorted arc list onto which you insertion sort. 350 * *prevp arc before the arc you are comparing. 351 */ 352 sorted.arc_childlist = 0; 353 for ( arcp = parentp -> children , detachedp = arcp -> arc_childlist ; 354 arcp ; 355 arcp = detachedp , detachedp = detachedp -> arc_childlist ) { 356 /* 357 * consider *arcp as disconnected 358 * insert it into sorted 359 */ 360 for ( prevp = &sorted ; 361 prevp -> arc_childlist ; 362 prevp = prevp -> arc_childlist ) { 363 if ( arccmp( arcp , prevp -> arc_childlist ) != LESSTHAN ) { 364 break; 365 } 366 } 367 arcp -> arc_childlist = prevp -> arc_childlist; 368 prevp -> arc_childlist = arcp; 369 } 370 /* 371 * reattach sorted children to parent 372 */ 373 parentp -> children = sorted.arc_childlist; 374 } 375 376 sortparents( childp ) 377 nltype *childp; 378 { 379 arctype *arcp; 380 arctype *detachedp; 381 arctype sorted; 382 arctype *prevp; 383 384 /* 385 * unlink parents from child, 386 * then insertion sort back on to sorted's parents. 387 * *arcp the arc you have detached and are inserting. 388 * *detachedp the rest of the arcs to be sorted. 389 * sorted arc list onto which you insertion sort. 390 * *prevp arc before the arc you are comparing. 391 */ 392 sorted.arc_parentlist = 0; 393 for ( arcp = childp -> parents , detachedp = arcp -> arc_parentlist ; 394 arcp ; 395 arcp = detachedp , detachedp = detachedp -> arc_parentlist ) { 396 /* 397 * consider *arcp as disconnected 398 * insert it into sorted 399 */ 400 for ( prevp = &sorted ; 401 prevp -> arc_parentlist ; 402 prevp = prevp -> arc_parentlist ) { 403 if ( arccmp( arcp , prevp -> arc_parentlist ) != GREATERTHAN ) { 404 break; 405 } 406 } 407 arcp -> arc_parentlist = prevp -> arc_parentlist; 408 prevp -> arc_parentlist = arcp; 409 } 410 /* 411 * reattach sorted arcs to child 412 */ 413 childp -> parents = sorted.arc_parentlist; 414 } 415 416 /* 417 * print a cycle header 418 */ 419 printcycle( cyclep ) 420 nltype *cyclep; 421 { 422 char kirkbuffer[ BUFSIZ ]; 423 424 sprintf( kirkbuffer , "[%d]" , cyclep -> index ); 425 printf( "%-6.6s %5.1f %7.2f %11.2f %7d" , 426 kirkbuffer , 427 100 * ( cyclep -> propself + cyclep -> propchild ) / printtime , 428 cyclep -> propself / HZ , 429 cyclep -> propchild / HZ , 430 cyclep -> ncall ); 431 if ( cyclep -> selfcalls != 0 ) { 432 printf( "+%-7d" , cyclep -> selfcalls ); 433 } else { 434 printf( " %7.7s" , "" ); 435 } 436 printf( " <cycle %d as a whole>\t[%d]\n" , 437 cyclep -> cycleno , cyclep -> index ); 438 } 439 440 /* 441 * print the members of a cycle 442 */ 443 printmembers( cyclep ) 444 nltype *cyclep; 445 { 446 nltype *memberp; 447 448 sortmembers( cyclep ); 449 for ( memberp = cyclep -> cnext ; memberp ; memberp = memberp -> cnext ) { 450 printf( "%6.6s %5.5s %7.2f %11.2f %7d" , 451 "" , "" , memberp -> propself / HZ , memberp -> propchild / HZ , 452 memberp -> ncall ); 453 if ( memberp -> selfcalls != 0 ) { 454 printf( "+%-7d" , memberp -> selfcalls ); 455 } else { 456 printf( " %7.7s" , "" ); 457 } 458 printf( " " ); 459 printname( memberp ); 460 printf( "\n" ); 461 } 462 } 463 464 /* 465 * sort members of a cycle 466 */ 467 sortmembers( cyclep ) 468 nltype *cyclep; 469 { 470 nltype *todo; 471 nltype *doing; 472 nltype *prev; 473 474 /* 475 * detach cycle members from cyclehead, 476 * and insertion sort them back on. 477 */ 478 todo = cyclep -> cnext; 479 cyclep -> cnext = 0; 480 for ( doing = todo , todo = doing -> cnext ; 481 doing ; 482 doing = todo , todo = doing -> cnext ) { 483 for ( prev = cyclep ; prev -> cnext ; prev = prev -> cnext ) { 484 if ( membercmp( doing , prev -> cnext ) == GREATERTHAN ) { 485 break; 486 } 487 } 488 doing -> cnext = prev -> cnext; 489 prev -> cnext = doing; 490 } 491 } 492 493 /* 494 * major sort is on propself + propchild, 495 * next is sort on ncalls + selfcalls. 496 */ 497 int 498 membercmp( this , that ) 499 nltype *this; 500 nltype *that; 501 { 502 double thistime = this -> propself + this -> propchild; 503 double thattime = that -> propself + that -> propchild; 504 long thiscalls = this -> ncall + this -> selfcalls; 505 long thatcalls = that -> ncall + that -> selfcalls; 506 507 if ( thistime > thattime ) { 508 return GREATERTHAN; 509 } 510 if ( thistime < thattime ) { 511 return LESSTHAN; 512 } 513 if ( thiscalls > thatcalls ) { 514 return GREATERTHAN; 515 } 516 if ( thiscalls < thatcalls ) { 517 return LESSTHAN; 518 } 519 return EQUALTO; 520 } 521 /* 522 * compare two arcs to/from the same child/parent. 523 * - if one arc is a self arc, it's least. 524 * - if one arc is within a cycle, it's less than. 525 * - if both arcs are within a cycle, compare arc counts. 526 * - if neither arc is within a cycle, compare with 527 * arc_time + arc_childtime as major key 528 * arc count as minor key 529 */ 530 int 531 arccmp( thisp , thatp ) 532 arctype *thisp; 533 arctype *thatp; 534 { 535 nltype *thisparentp = thisp -> arc_parentp; 536 nltype *thischildp = thisp -> arc_childp; 537 nltype *thatparentp = thatp -> arc_parentp; 538 nltype *thatchildp = thatp -> arc_childp; 539 double thistime; 540 double thattime; 541 542 # ifdef DEBUG 543 if ( debug & TIMEDEBUG ) { 544 printf( "[arccmp] " ); 545 printname( thisparentp ); 546 printf( " calls " ); 547 printname ( thischildp ); 548 printf( " %f + %f %d/%d\n" , 549 thisp -> arc_time , thisp -> arc_childtime , 550 thisp -> arc_count , thischildp -> ncall ); 551 printf( "[arccmp] " ); 552 printname( thatparentp ); 553 printf( " calls " ); 554 printname( thatchildp ); 555 printf( " %f + %f %d/%d\n" , 556 thatp -> arc_time , thatp -> arc_childtime , 557 thatp -> arc_count , thatchildp -> ncall ); 558 printf( "\n" ); 559 } 560 # endif DEBUG 561 if ( thisparentp == thischildp ) { 562 /* this is a self call */ 563 return LESSTHAN; 564 } 565 if ( thatparentp == thatchildp ) { 566 /* that is a self call */ 567 return GREATERTHAN; 568 } 569 if ( thisparentp -> cycleno != 0 && thischildp -> cycleno != 0 && 570 thisparentp -> cycleno == thischildp -> cycleno ) { 571 /* this is a call within a cycle */ 572 if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 573 thatparentp -> cycleno == thatchildp -> cycleno ) { 574 /* that is a call within the cycle, too */ 575 if ( thisp -> arc_count < thatp -> arc_count ) { 576 return LESSTHAN; 577 } 578 if ( thisp -> arc_count > thatp -> arc_count ) { 579 return GREATERTHAN; 580 } 581 return EQUALTO; 582 } else { 583 /* that isn't a call within the cycle */ 584 return LESSTHAN; 585 } 586 } else { 587 /* this isn't a call within a cycle */ 588 if ( thatparentp -> cycleno != 0 && thatchildp -> cycleno != 0 && 589 thatparentp -> cycleno == thatchildp -> cycleno ) { 590 /* that is a call within a cycle */ 591 return GREATERTHAN; 592 } else { 593 /* neither is a call within a cycle */ 594 thistime = thisp -> arc_time + thisp -> arc_childtime; 595 thattime = thatp -> arc_time + thatp -> arc_childtime; 596 if ( thistime < thattime ) 597 return LESSTHAN; 598 if ( thistime > thattime ) 599 return GREATERTHAN; 600 if ( thisp -> arc_count < thatp -> arc_count ) 601 return LESSTHAN; 602 if ( thisp -> arc_count > thatp -> arc_count ) 603 return GREATERTHAN; 604 return EQUALTO; 605 } 606 } 607 } 608 609 printblurb( blurbname ) 610 char *blurbname; 611 { 612 char pathname[ BUFSIZ ]; 613 FILE *blurbfile; 614 int input; 615 616 sprintf( pathname , "%s%s" , BLURBLIB , blurbname ); 617 blurbfile = fopen( pathname , "r" ); 618 if ( blurbfile == NULL ) { 619 perror( pathname ); 620 return; 621 } 622 while ( ( input = getc( blurbfile ) ) != EOF ) { 623 putchar( input ); 624 } 625 fclose( blurbfile ); 626 } 627