1/* 2 * Part of Scheme 48 1.9. See file COPYING for notices and license. 3 * 4 * Authors: David Frese, Christos Freris, Eric Knauel 5 */ 6 7/* This file needs to be included from generation_gc.c, because for 8 reasons of simplicity we use static variables from there directly 9 here. */ 10 11/* Not really sure if this is true: 12 13 MEASURE_GC was an old flag by Norbert, which activated writing out 14 several files with Sexps, containing the size of the heap, the 15 areas, and some timing information. Most (all?) of it is actually 16 stripped off here with "#if 0". 17 18 S48_MEASURE_GC_TIME is the newer flag by Christos, used to write 19 out gnuplot files with detailed timing informations and size 20 informations that are taking out of the same variables as 21 MEASURE_GC did. 22 23 DISPLAY_MEASURE_GC additionally prints out some infos to stdout 24 about what's going on with the measurement. 25 26 This should be made less confusing and working properly. 27 28 -- David 29*/ 30 31FILE* datafile; 32 33/* controlled by s48_collect: */ 34void start_measure() { 35 datafile = fopen("MEASURE-GC", "a"); 36 fprintf(datafile, " ( "); 37} 38 39void stop_measure() { 40 fprintf(datafile, " ) \n \n"); 41 fclose(datafile); 42} 43 44static unsigned long count_collection = 0; 45 46/* write-barrier and inter-generational-pointer */ 47static unsigned int count_wb = 0; 48static unsigned int count_gc_wb = 0; 49static unsigned int count_igp = 0; 50static unsigned int count_gc_igp = 0; 51 52 53/* visited and passed areas from trace_areas_roots */ 54 55static unsigned long count_areas_roots_visited = 0; 56static unsigned long count_areas_roots_passed = 0; 57 58/* the heap usage and size */ 59 60static unsigned long count_heap_size = 0; 61static unsigned long count_heap_usage = 0; 62 63 64static unsigned long old_heap_size = 0; 65 66unsigned long get_wbarrier() { 67 return count_wb; 68} 69 70unsigned long get_gc_wbarrier() { 71 return count_gc_wb; 72} 73 74unsigned long get_igen() { 75 return count_igp; 76} 77 78unsigned long get_gc_igen() { 79 return count_gc_igp; 80} 81 82 83int write_area_size(int size, int gens[]){ 84 int i; 85 86 fprintf(datafile, " (areasize "); 87 88 /* the creation space: */ 89 fprintf(datafile, " %d ", gens[size]); 90 91 for(i = 0; i < size; i++){ 92 93 /* the generations: */ 94 fprintf(datafile, " %d ", gens[i]); 95 } 96 fprintf(datafile, " ) "); 97 98 return 0; 99} 100 101 102 103/* mark_cons ratio */ 104int write_mc_ratio() { 105 double r = ((double) count_heap_usage) / 106 ((double) (count_heap_size - count_heap_usage)); 107 fprintf(datafile, " (mcratio "); 108 fprintf(datafile, " %f", r); 109 fprintf(datafile, " ) "); 110 111 return 0; 112} 113 114int write_heap_usage_size(){ 115 fprintf(datafile, " (heap "); 116 fprintf(datafile, " %d ", count_heap_size); 117 fprintf(datafile, " %d ", count_heap_usage); 118 fprintf(datafile, " ) "); 119 120 return 0; 121} 122 123/*sum of write-barrier calls and created inter-generational-pointer*/ 124int write_wb_igp(){ 125 fprintf(datafile, " (wb "); 126 fprintf(datafile, " %d", count_wb); 127 fprintf(datafile, " %d", count_igp); 128 fprintf(datafile, " ) "); 129 return 0; 130} 131 132/* which generation is collected */ 133int write_minor_major_gc(int n){ 134 fprintf(datafile, " (gens "); 135 fprintf(datafile, " %d ", n); /* collect the first n gens */ 136 fprintf(datafile, " %d ", count_collection); /* collection number */ 137 fprintf(datafile, " ) "); 138 139 return 0; 140} 141 142/* ratio of vistied/passed areas in trace_areas_roots */ 143int write_areas_roots_ratio(){ 144 double ratio = ((((double) count_areas_roots_passed) / 145 ((double) count_areas_roots_visited)) * 100); 146 fprintf(datafile, " (arearoots "); 147 fprintf(datafile, " %f ", ratio); 148 fprintf(datafile, " ) "); 149 return 0; 150} 151 152 153/* -- the "#ifdef" functions: -- */ 154 155 156/* writing some data just before the collection:*/ 157 158 159/************************************************************************ 160called in: <file>::<function> 161./c/bibop/generation_gc.c::s48_collect 162*************************************************************************/ 163void measure_gc_start(int c){ 164 count_collection++; 165 166 if (old_heap_size < count_heap_size){ 167 old_heap_size = count_heap_size; 168 } 169 170 start_measure(); /* opens fileport */ 171 write_minor_major_gc(c); 172 write_heap_usage_size(); 173 174 /* small and large area numbers are invoked in s48_collect*/ 175} 176 177/* next gc (in generation n) is triggerd and finished */ 178/************************************************************************ 179called in: <file>::<function> 180./c/bibop/generation_gc.c::s48_collect 181*************************************************************************/ 182void measure_gc_end() { 183 write_mc_ratio(); 184 write_heap_usage_size(); 185 write_wb_igp(); 186 write_areas_roots_ratio(); 187 stop_measure(); /* closes fileport */ 188} 189 190 191/************************************************************************ 192called in: ./c/bibop/area_roots.c::s48_write_barrier 193*************************************************************************/ 194void measure_write_barrier(char flag) { 195 if (flag){ 196 /* so we have a inter-gen-pointer..*/ 197 count_igp++; 198 } 199 count_wb++; 200} 201 202/************************************************************************ 203called in:./c/bibop/area_roots.c::s48_write_internal_barrier 204*************************************************************************/ 205void measure_gc_write_barrier() { 206 /* when we call this we have a new inter-gen-pointer..*/ 207 count_gc_igp++; 208 count_gc_wb++; 209} 210 211 212/* number of small/large areas per generation */ 213/************************************************************************ 214called in: <file>::<function> 215./c/bibop/generation_gc.c::get_area_objects 216*************************************************************************/ 217void measure_small_areas(int size, int small[]){ 218 219 write_area_size(size, small); 220} 221 222/************************************************************************ 223called in: <file>::<function> 224./c/bibop/generation_gc.c::get_area_objects 225*************************************************************************/ 226void measure_large_areas(int size, int large[]){ 227 228 write_area_size(size, large); 229} 230 231/* get the data from trace_areas_roots() */ 232/************************************************************************ 233called in: <file>::<function> 234./c/bibop/area_roots.c::s48_trace_areas_roots 235*************************************************************************/ 236void measure_areas_roots(unsigned long visited, unsigned long passed){ 237 count_areas_roots_visited += visited; 238 count_areas_roots_passed += passed; 239} 240 241/************************************************************************ 242called in: <file>::<function> 243./c/bibop/generation_gc.c::s48_collect 244*************************************************************************/ 245void measure_heap_size(unsigned long size){ 246 count_heap_size = size; 247} 248 249/************************************************************************ 250called in: ./c/bibop/generation_gc.c::s48_collect 251*************************************************************************/ 252void measure_heap_usage(unsigned long usage){ 253 count_heap_usage = usage; 254} 255 256/************************************************************************ 257called in: ./c/bibop/generation_gc.c::s48_collect 258*************************************************************************/ 259void clear_measurement(){ 260 261 count_wb = 0; 262 count_igp = 0; 263 count_areas_roots_passed = 0; 264 count_areas_roots_visited = 0; 265 266 count_gc_wb = 0; 267 count_gc_igp = 0; 268 269} 270 271unsigned long get_areas_size(Area* areas) { 272 unsigned long size = 0; 273 FOR_ALL_AREAS(areas, 274 size += (area->frontier - area->start)); 275 return size; 276} 277 278typedef struct { 279 unsigned long gen_small_current; /* generation small area current */ 280 unsigned long gen_small_other; /* generation small area other */ 281 unsigned long gen_large_current; /* generation large area current */ 282 unsigned long gen_large_other; /* generation large area other */ 283 unsigned long gen_weaks_current; /* generation weaks area current */ 284 unsigned long gen_weaks_other; /* generation weaks area other */ 285} GenImg; 286 287typedef struct { 288 unsigned long gc_nr; /* collection number */ 289 unsigned long cs_small_below; /* creation space small below area */ 290 unsigned long cs_small_above; /* creation space small above area */ 291 unsigned long cs_large; /* creation space large area */ 292 unsigned long cs_weaks; /* creation space weaks area */ 293 unsigned long wbarrier; /* write barrier calls */ 294 unsigned long igen; /* intergenerational pointers (old->young) */ 295 unsigned long gc_wbarrier; /* internal write barrier calls */ 296 unsigned long gc_igen; /* internal intergenerational pointers (old->young) */ 297 298 /* Generations */ 299 GenImg genImgs[S48_GENERATIONS_COUNT]; 300} HeapImg; 301 302void takeHeapImg(HeapImg* hi) { 303 int i; 304 305 hi->gc_nr = s48_gc_count(); 306 hi->cs_small_below = get_areas_size(creation_space.small_below); 307 hi->cs_small_above = get_areas_size(creation_space.small_above); 308 hi->cs_large = get_areas_size(creation_space.large); 309 hi->cs_weaks = get_areas_size(creation_space.weaks); 310 hi->wbarrier = get_wbarrier(); /* measure.h */ 311 hi->gc_wbarrier = get_gc_wbarrier(); /* measure.h */ 312 hi->igen = get_igen(); /* measure.h */ 313 hi->gc_igen = get_gc_igen(); /* measure.h */ 314 315 for (i = 0; i < S48_GENERATIONS_COUNT; i++) { 316 hi->genImgs[i].gen_small_current = 317 get_areas_size(generations[i].current_space->small_area); 318 hi->genImgs[i].gen_small_other = 319 get_areas_size(generations[i].other_space->small_area); 320 hi->genImgs[i].gen_large_current = 321 get_areas_size(generations[i].current_space->large_area); 322 hi->genImgs[i].gen_large_other = 323 get_areas_size(generations[i].other_space->large_area); 324 hi->genImgs[i].gen_weaks_current = 325 get_areas_size(generations[i].current_space->weaks_area); 326 hi->genImgs[i].gen_weaks_other = 327 get_areas_size(generations[i].other_space->weaks_area); 328 } 329} 330 331#if (DISPLAY_MEASURE_GC) 332 333void display_string(char* message) { 334 fprintf(stdout, message); 335} 336 337void display_string_x(char* message, int times) { 338 while (times > 0) { 339 display_string(message); 340 times--; 341 } 342} 343 344void display_number(int digits, long number) { 345 fprintf(stdout, " %0*d", digits, number); 346} 347 348void display_double(int digits, double n) { 349 fprintf(stdout, " %0*.*f", digits, 3, n); 350} 351 352void newline() { 353 fprintf(stdout, "\n"); 354} 355 356void space() { 357 fprintf(stdout, " "); 358} 359 360void dis_string(char* message) { 361 display_string(message); 362 newline(); 363} 364 365void dis_string_x(char* message, int times) { 366 display_string_x(message, times); 367 newline(); 368} 369 370void dis_number(int digits, long n) { 371 display_number(digits, n); 372 newline(); 373} 374 375void dis_double(int digits, double n) { 376 display_double(digits, n); 377 newline(); 378} 379 380void display_comparison(long new, long old) { 381 if (new == old) { 382 display_string(" "); 383 } 384 else if (new > old) { 385 display_string(" +"); 386 } 387 else display_string(" -"); 388} 389 390void write_vm_options(FILE* f) { 391 fprintf(f, 392 "VM (scheme48) Compiled with these Options\n" 393 "-----------------------------------------\n" 394 "S48_MEASURE_GC_TIME: %02d\n" 395 "MEASURE_GC: %02d\n" 396 "DISPLAY_MEASURE_GC: %02d\n" 397 "S48_GENERATIONS_COUNT: %03d\n" 398 "S48_CREATION_SPACE_SIZE: %03d\n" 399 "S48_DEFAULT_WATER_MARK: %03d\n" 400 "S48_ADJUST_WATER_MARK: %02d\n" 401 "S48_SMALL_OBJECT_LIMIT: %05d\n" 402 "S48_MINIMUM_SMALL_AREA_SIZE: %03d\n" 403 "S48_MAXIMUM_SMALL_AREA_SIZE: %03d\n" 404 "S48_MAXIMUM_LARGE_CREATION_SPACE_SIZE: %05d\n" 405 "S48_MINIMUM_WEAK_AREA_SIZE: %05d\n" 406 "S48_MAXIMUM_WEAK_AREA_SIZE: %05d\n" 407 "S48_COLLECTION_THRESHOLD: %05d\n" 408 "S48_LOG_CARD_SIZE: %03d\n" 409 "S48_DIRTY_VECTOR_METHOD: %02d\n" 410 "S48_WRITE_BARRIER_COMPLEXITY: %02d\n" 411 "S48_USE_CARD_GENERATION_INDEXING: %02d\n" 412 "S48_USE_GENERATION_INDEXING: %02d\n" 413 "S48_USE_REMEMBERED_SETS: %02d\n", 414 S48_MEASURE_GC_TIME, 415 MEASURE_GC, 416 DISPLAY_MEASURE_GC, 417 S48_GENERATIONS_COUNT, 418 S48_CREATION_SPACE_SIZE, 419 S48_DEFAULT_WATER_MARK, 420 S48_ADJUST_WATER_MARK, 421 S48_SMALL_OBJECT_LIMIT, 422 S48_MINIMUM_SMALL_AREA_SIZE, 423 S48_MAXIMUM_SMALL_AREA_SIZE, 424 S48_MAXIMUM_LARGE_CREATION_SPACE_SIZE, 425 S48_MINIMUM_WEAK_AREA_SIZE, 426 S48_MAXIMUM_WEAK_AREA_SIZE, 427 S48_COLLECTION_THRESHOLD, 428 S48_LOG_CARD_SIZE, 429 S48_DIRTY_VECTOR_METHOD, 430 S48_WRITE_BARRIER_COMPLEXITY, 431 S48_USE_CARD_GENERATION_INDEXING, 432 S48_USE_GENERATION_INDEXING, 433 S48_USE_REMEMBERED_SETS); 434 435#if (S48_USE_REMEMBERED_SETS) 436 fprintf(f, 437 "S48_REMEMBERED_SET_SIZE: %05d\n" 438 "S48_REMEMBERED_SET_TYPE: %02d\n" 439 "S48_UNIQUE_REMEMBERED_SET: %02d\n", 440 S48_REMEMBERED_SET_SIZE, 441 S48_REMEMBERED_SET_TYPE, 442 S48_UNIQUE_REMEMBERED_SET); 443 444#endif /* #if (S48_USE_REMEMBERED_SETS) */ 445 446 fprintf(f, 447 "S48_USE_RDM: %02d\n", 448 S48_USE_RDM); 449 450#if (S48_USE_RDM) 451 fprintf(f, 452 "S48_RDM_MAX_SIZE: %05d\n" 453 "S48_RDM_INITIAL_THRESHOLD: %05d\n" 454 "S48_RDM_MIN_THRESHOLD: %05d", 455 S48_RDM_MAX_SIZE, 456 S48_RDM_INITIAL_THRESHOLD, 457 S48_RDM_MIN_THRESHOLD); 458#endif /* #if (S48_USE_RDM) */ 459 460 fprintf(f, "\n\n"); 461} 462 463void display_vm_options() { 464 write_vm_options(stdout); 465} 466 467#endif 468 469 470FILE* file; 471 472static unsigned long gc_nr = 0; 473 474static double gc_time = 0; 475static double gc_runtime = 0; 476static unsigned long total_gc_time_in_usec = 0; 477static double gc_average_time = 0; 478 479static unsigned long heap_size_before = 0; 480static unsigned long heap_size_after = 0; 481static unsigned long max_heap = 0; 482 483static unsigned long s48_heap_size_before = 0; 484static unsigned long s48_heap_size_after = 0; 485 486static HeapImg heap_img_before; 487static HeapImg heap_img_after; 488 489static unsigned long all_surviving_obj = 0; 490static unsigned long first_time_flag = 0; 491 492void fprint_cs_data(FILE* f, HeapImg* img_before, HeapImg* img_after) { 493 fprintf(f, "%8i %8i %8i %8i %8i %8i %8i %8i ", 494 heap_img_before.cs_small_below, /* 9 */ 495 heap_img_after.cs_small_below, /* 10 */ 496 heap_img_before.cs_small_above, /* 11 */ 497 heap_img_after.cs_small_above, /* 12 */ 498 heap_img_before.cs_large, /* 13 */ 499 heap_img_after.cs_large, /* 14 */ 500 heap_img_before.cs_weaks, /* 15 */ 501 heap_img_after.cs_weaks /* 16 */ 502 ); 503} 504 505/* wi_data = write barrier & intergenerational pointers */ 506void fprint_wi_data(FILE* f, HeapImg* img_before, HeapImg* img_after) { 507 fprintf(f, "%8i %8i %8i %8i", 508 heap_img_before.wbarrier, /* 17 */ 509 heap_img_after.gc_wbarrier, /* 18 */ 510 heap_img_before.igen, /* 19 */ 511 heap_img_after.gc_igen /* 20 */ 512 ); 513} 514 515void fprint_gen_data(FILE* f, HeapImg* img_before, HeapImg* img_after) { 516 int i; 517 518 /* Line Order: 20 + ( X * i+1) 519 example: 520 Line Order of: img_after->genImgs[1].gen_large_current [ 6 ] 521 Is: 20 + ( 6 * 1+1) = 32 522 */ 523 524 for (i = 0; i < S48_GENERATIONS_COUNT; i++) { 525 fprintf(f, "%8i %8i %8i %8i %8i %8i %8i %8i %8i %8i %8i %8i ", /* X */ 526 img_before->genImgs[i].gen_small_current, /* 1 */ 527 img_after->genImgs[i].gen_small_current, /* 2 */ 528 img_before->genImgs[i].gen_small_other, /* 3 */ 529 img_after->genImgs[i].gen_small_other, /* 4 */ 530 img_before->genImgs[i].gen_large_current, /* 5 */ 531 img_after->genImgs[i].gen_large_current, /* 6 */ 532 img_before->genImgs[i].gen_large_other, /* 7 */ 533 img_after->genImgs[i].gen_large_other, /* 8 */ 534 img_before->genImgs[i].gen_weaks_current, /* 9 */ 535 img_after->genImgs[i].gen_weaks_current, /* 10 */ 536 img_before->genImgs[i].gen_weaks_other, /* 11 */ 537 img_after->genImgs[i].gen_weaks_other /* 12 */ 538 ); 539 } 540} 541 542void fprint_all_data (FILE* f, HeapImg* img_before, HeapImg* img_after){ 543 544 /* Creation Space */ 545 fprint_cs_data(f, img_before, img_after); 546 547 /* Write Barrier & InterGen Pointers */ 548 fprint_wi_data(f, img_before, img_after); 549 550 /* Generations */ 551 fprint_gen_data(f, img_before, img_after); 552} 553 554 555int get_small_objects(int gen){ 556 int number = 0; 557 /* little cheat to get to the creation_space*/ 558 if(gen == S48_GENERATIONS_COUNT){ 559 FOR_ALL_AREAS(creation_space.small_below, number += 1); 560 FOR_ALL_AREAS(creation_space.small_above, number += 1); 561 }else{ 562 FOR_ALL_AREAS(generations[gen].current_space->small_area, number += 1); 563 } 564 return number; 565} 566 567int get_large_objects(int gen){ 568 int number = 0; 569 if(gen == S48_GENERATIONS_COUNT){ 570 FOR_ALL_AREAS(creation_space.large, number += 1); 571 }else{ 572 FOR_ALL_AREAS(generations[gen].current_space->large_area, number +=1); 573 } 574 return number; 575} 576 577void get_area_objects(){ 578 int small[S48_GENERATIONS_COUNT+1]; 579 int large[S48_GENERATIONS_COUNT+1]; 580 int i; 581 for (i = 0; i <= S48_GENERATIONS_COUNT; i++){ 582 small[i] = get_small_objects(i); 583 large[i] = get_large_objects(i); 584 } 585 measure_small_areas(S48_GENERATIONS_COUNT, small); 586 measure_large_areas(S48_GENERATIONS_COUNT, large); 587} 588 589 590long time_swap; 591struct timeval t1; 592struct timeval t2; 593struct timeval t3; 594 595void measure_before_collection(int c) { 596#if 0 597 measure_gc_start(c); 598 all_surviving_obj = 0; 599 get_area_objects(); 600 measure_heap_size(s48_heap_size()); 601 measure_heap_usage(s48_heap_live_size()); 602#endif 603 604 /* catch the actual heap status */ 605 takeHeapImg(&heap_img_before); 606 heap_size_before = s48_heap_size(); 607 s48_heap_size_before = s48_heap_live_size(); 608 609 /* catch the time before ... */ 610 gettimeofday(&t1, 0); 611} 612 613void measure_after_collection(int c) { 614 gettimeofday(&t2, 0); 615 616 t3.tv_sec = (t2.tv_sec - t1.tv_sec); 617 time_swap = t2.tv_usec - t1.tv_usec; 618 if (time_swap < 0) { 619 time_swap = 1000000 + time_swap; 620 t3.tv_sec -= 1; 621 } 622 t3.tv_usec = time_swap; 623 624 /* save some values after collection */ 625 gc_nr = s48_gc_count(); 626 total_gc_time_in_usec += t3.tv_usec; 627 gc_time = t3.tv_usec / 1000000.0; 628 gc_runtime = total_gc_time_in_usec / 1000000.0; 629 gc_average_time = total_gc_time_in_usec / ( 1000000.0 * gc_nr) ; 630 631 takeHeapImg(&heap_img_after); 632 heap_size_after = s48_heap_size(); 633 s48_heap_size_after = s48_heap_live_size(); 634 635 max_heap = int_max(max_heap, int_max(heap_size_before, heap_size_after)); 636 637#if 0 638 measure_heap_size(s48_heap_size()); 639 measure_heap_usage(s48_heap_live_size()); 640 measure_gc_end(); /* This will null wb and igp counters */ 641#endif 642 643#if 0 644 file = fopen("MEASURE-GC-TIME", "a"); 645 fprintf(file, "( %d ", t3.tv_sec); 646 fprintf(file, " %d )", t3.tv_usec); 647 fclose(file); 648#endif 649 650 file = fopen("MEASURE_GC_RESULT_TEMP", "w"); /* w : to overwrite */ 651 fprintf(file, "%5i %5i %6.3f %6.3f %6.3f %8i %8i %8i ", 652 gc_nr, /* 1 */ 653 c, /* 2 up to collected gen */ 654 gc_time, /* 3 */ 655 gc_runtime, /* 4 */ 656 gc_average_time, /* 5 */ 657 heap_size_before, /* 6 */ 658 heap_size_after, /* 7 */ 659 max_heap /* 8 */ 660 ); 661 fprint_all_data(file, &heap_img_before, &heap_img_after); 662 fprintf(file, "\n"); /*newline */ 663 fclose(file); 664 665 /* Save all results in an extra file (not to overwrite) */ 666 system("cat MEASURE_GC_RESULT_TEMP >> MEASURE_ALL_GC_RESULT"); /* unistd.h */ 667 668#if (DISPLAY_MEASURE_GC) 669 /*Print config-options once */ 670 if (first_time_flag == 0) { 671 first_time_flag = 1; 672 display_vm_options(); 673 newline(); 674 dis_string("gc_nr gen_nr gc_time gc_runtime gc_average"); 675 dis_string_x("-", 40); 676 } 677 678 display_number(5, s48_gc_count() ); 679 display_double(5, gc_time ); 680 display_double(7, gc_runtime ); 681 display_double(5, gc_average_time ); 682 683 /* up to collected generations */ 684 display_number(2, c ); 685 686 /* the whole heap */ 687 display_number(8, heap_size_before); 688 display_number(8, heap_size_after); 689 display_comparison(heap_size_after, heap_size_before); 690 691 /* the used heap */ 692 display_number(8, s48_heap_size_before); 693 display_number(8, s48_heap_size_after); 694 display_comparison(s48_heap_size_after, s48_heap_size_before); 695 696 /* % relationship between the whole and the used heap */ 697 display_double(5, (s48_heap_size_after * 100.0 ) / heap_size_after); 698 699 newline(); 700 /*dis_string_x("-", 65); */ 701 /*newline(); */ 702 703 /* s48_check_heap(0);*/ 704 705 /* Initializes static variables: count_igp, count_wb, count_gc_igp, 706 count_gc_wb (measure.h) */ 707 clear_measurement(); 708#endif 709 710} 711