Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 3914:20213c8a3c40
7050392: G1: Introduce flag to generate a log of the G1 ergonomic decisions
Summary: It introduces ergonomic decision logging in G1 for the following heuristics: heap sizing, collection set construction, concurrent cycle initiation, and partially-young GC start/end. The code has a bit of refactoring in a few places to make the decision logging possible. It also replaces alternative ad-hoc logging that we have under different parameters and switches (G1_DEBUG, G1PolicyVerbose).
Reviewed-by: johnc, ysr
author | tonyp |
---|---|
date | Wed, 07 Sep 2011 12:21:23 -0400 |
parents | eeae91c9baba |
children | 05550041d664 |
comparison
equal
deleted
inserted
replaced
3913:27702f012017 | 3914:20213c8a3c40 |
---|---|
29 #include "gc_implementation/g1/concurrentG1RefineThread.hpp" | 29 #include "gc_implementation/g1/concurrentG1RefineThread.hpp" |
30 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" | 30 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" |
31 #include "gc_implementation/g1/g1AllocRegion.inline.hpp" | 31 #include "gc_implementation/g1/g1AllocRegion.inline.hpp" |
32 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" | 32 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" |
33 #include "gc_implementation/g1/g1CollectorPolicy.hpp" | 33 #include "gc_implementation/g1/g1CollectorPolicy.hpp" |
34 #include "gc_implementation/g1/g1ErgoVerbose.hpp" | |
34 #include "gc_implementation/g1/g1MarkSweep.hpp" | 35 #include "gc_implementation/g1/g1MarkSweep.hpp" |
35 #include "gc_implementation/g1/g1OopClosures.inline.hpp" | 36 #include "gc_implementation/g1/g1OopClosures.inline.hpp" |
36 #include "gc_implementation/g1/g1RemSet.inline.hpp" | 37 #include "gc_implementation/g1/g1RemSet.inline.hpp" |
37 #include "gc_implementation/g1/heapRegionRemSet.hpp" | 38 #include "gc_implementation/g1/heapRegionRemSet.hpp" |
38 #include "gc_implementation/g1/heapRegionSeq.inline.hpp" | 39 #include "gc_implementation/g1/heapRegionSeq.inline.hpp" |
575 "res == NULL, trying the secondary_free_list"); | 576 "res == NULL, trying the secondary_free_list"); |
576 } | 577 } |
577 res = new_region_try_secondary_free_list(); | 578 res = new_region_try_secondary_free_list(); |
578 } | 579 } |
579 if (res == NULL && do_expand) { | 580 if (res == NULL && do_expand) { |
581 ergo_verbose1(ErgoHeapSizing, | |
582 "attempt heap expansion", | |
583 ergo_format_reason("region allocation request failed") | |
584 ergo_format_byte("allocation request"), | |
585 word_size * HeapWordSize); | |
580 if (expand(word_size * HeapWordSize)) { | 586 if (expand(word_size * HeapWordSize)) { |
581 // Even though the heap was expanded, it might not have reached | 587 // Even though the heap was expanded, it might not have reached |
582 // the desired size. So, we cannot assume that the allocation | 588 // the desired size. So, we cannot assume that the allocation |
583 // will succeed. | 589 // will succeed. |
584 res = _free_list.remove_head_or_null(); | 590 res = _free_list.remove_head_or_null(); |
788 // We should only be trying to expand when the free suffix is | 794 // We should only be trying to expand when the free suffix is |
789 // not sufficient for the object _and_ we have some expansion | 795 // not sufficient for the object _and_ we have some expansion |
790 // room available. | 796 // room available. |
791 assert(num_regions > fs, "earlier allocation should have succeeded"); | 797 assert(num_regions > fs, "earlier allocation should have succeeded"); |
792 | 798 |
799 ergo_verbose1(ErgoHeapSizing, | |
800 "attempt heap expansion", | |
801 ergo_format_reason("humongous allocation request failed") | |
802 ergo_format_byte("allocation request"), | |
803 word_size * HeapWordSize); | |
793 if (expand((num_regions - fs) * HeapRegion::GrainBytes)) { | 804 if (expand((num_regions - fs) * HeapRegion::GrainBytes)) { |
794 // Even though the heap was expanded, it might not have | 805 // Even though the heap was expanded, it might not have |
795 // reached the desired size. So, we cannot assume that the | 806 // reached the desired size. So, we cannot assume that the |
796 // allocation will succeed. | 807 // allocation will succeed. |
797 first = humongous_obj_allocate_find_first(num_regions, word_size); | 808 first = humongous_obj_allocate_find_first(num_regions, word_size); |
904 // allocate a new region. So the mutator alloc region should be NULL. | 915 // allocate a new region. So the mutator alloc region should be NULL. |
905 assert(_mutator_alloc_region.get() == NULL, "only way to get here"); | 916 assert(_mutator_alloc_region.get() == NULL, "only way to get here"); |
906 | 917 |
907 if (GC_locker::is_active_and_needs_gc()) { | 918 if (GC_locker::is_active_and_needs_gc()) { |
908 if (g1_policy()->can_expand_young_list()) { | 919 if (g1_policy()->can_expand_young_list()) { |
920 // No need for an ergo verbose message here, | |
921 // can_expand_young_list() does this when it returns true. | |
909 result = _mutator_alloc_region.attempt_allocation_force(word_size, | 922 result = _mutator_alloc_region.attempt_allocation_force(word_size, |
910 false /* bot_updates */); | 923 false /* bot_updates */); |
911 if (result != NULL) { | 924 if (result != NULL) { |
912 return result; | 925 return result; |
913 } | 926 } |
1475 // Should not be less than the heap min size. No need to adjust it | 1488 // Should not be less than the heap min size. No need to adjust it |
1476 // with respect to the heap max size as it's an upper bound (i.e., | 1489 // with respect to the heap max size as it's an upper bound (i.e., |
1477 // we'll try to make the capacity smaller than it, not greater). | 1490 // we'll try to make the capacity smaller than it, not greater). |
1478 maximum_desired_capacity = MAX2(maximum_desired_capacity, min_heap_size); | 1491 maximum_desired_capacity = MAX2(maximum_desired_capacity, min_heap_size); |
1479 | 1492 |
1480 if (PrintGC && Verbose) { | |
1481 const double free_percentage = | |
1482 (double) free_after_gc / (double) capacity_after_gc; | |
1483 gclog_or_tty->print_cr("Computing new size after full GC "); | |
1484 gclog_or_tty->print_cr(" " | |
1485 " minimum_free_percentage: %6.2f", | |
1486 minimum_free_percentage); | |
1487 gclog_or_tty->print_cr(" " | |
1488 " maximum_free_percentage: %6.2f", | |
1489 maximum_free_percentage); | |
1490 gclog_or_tty->print_cr(" " | |
1491 " capacity: %6.1fK" | |
1492 " minimum_desired_capacity: %6.1fK" | |
1493 " maximum_desired_capacity: %6.1fK", | |
1494 (double) capacity_after_gc / (double) K, | |
1495 (double) minimum_desired_capacity / (double) K, | |
1496 (double) maximum_desired_capacity / (double) K); | |
1497 gclog_or_tty->print_cr(" " | |
1498 " free_after_gc: %6.1fK" | |
1499 " used_after_gc: %6.1fK", | |
1500 (double) free_after_gc / (double) K, | |
1501 (double) used_after_gc / (double) K); | |
1502 gclog_or_tty->print_cr(" " | |
1503 " free_percentage: %6.2f", | |
1504 free_percentage); | |
1505 } | |
1506 if (capacity_after_gc < minimum_desired_capacity) { | 1493 if (capacity_after_gc < minimum_desired_capacity) { |
1507 // Don't expand unless it's significant | 1494 // Don't expand unless it's significant |
1508 size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; | 1495 size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; |
1509 if (expand(expand_bytes)) { | 1496 ergo_verbose4(ErgoHeapSizing, |
1510 if (PrintGC && Verbose) { | 1497 "attempt heap expansion", |
1511 gclog_or_tty->print_cr(" " | 1498 ergo_format_reason("capacity lower than " |
1512 " expanding:" | 1499 "min desired capacity after Full GC") |
1513 " max_heap_size: %6.1fK" | 1500 ergo_format_byte("capacity") |
1514 " minimum_desired_capacity: %6.1fK" | 1501 ergo_format_byte("occupancy") |
1515 " expand_bytes: %6.1fK", | 1502 ergo_format_byte_perc("min desired capacity"), |
1516 (double) max_heap_size / (double) K, | 1503 capacity_after_gc, used_after_gc, |
1517 (double) minimum_desired_capacity / (double) K, | 1504 minimum_desired_capacity, (double) MinHeapFreeRatio); |
1518 (double) expand_bytes / (double) K); | 1505 expand(expand_bytes); |
1519 } | |
1520 } | |
1521 | 1506 |
1522 // No expansion, now see if we want to shrink | 1507 // No expansion, now see if we want to shrink |
1523 } else if (capacity_after_gc > maximum_desired_capacity) { | 1508 } else if (capacity_after_gc > maximum_desired_capacity) { |
1524 // Capacity too large, compute shrinking size | 1509 // Capacity too large, compute shrinking size |
1525 size_t shrink_bytes = capacity_after_gc - maximum_desired_capacity; | 1510 size_t shrink_bytes = capacity_after_gc - maximum_desired_capacity; |
1511 ergo_verbose4(ErgoHeapSizing, | |
1512 "attempt heap shrinking", | |
1513 ergo_format_reason("capacity higher than " | |
1514 "max desired capacity after Full GC") | |
1515 ergo_format_byte("capacity") | |
1516 ergo_format_byte("occupancy") | |
1517 ergo_format_byte_perc("max desired capacity"), | |
1518 capacity_after_gc, used_after_gc, | |
1519 maximum_desired_capacity, (double) MaxHeapFreeRatio); | |
1526 shrink(shrink_bytes); | 1520 shrink(shrink_bytes); |
1527 if (PrintGC && Verbose) { | |
1528 gclog_or_tty->print_cr(" " | |
1529 " shrinking:" | |
1530 " min_heap_size: %6.1fK" | |
1531 " maximum_desired_capacity: %6.1fK" | |
1532 " shrink_bytes: %6.1fK", | |
1533 (double) min_heap_size / (double) K, | |
1534 (double) maximum_desired_capacity / (double) K, | |
1535 (double) shrink_bytes / (double) K); | |
1536 } | |
1537 } | 1521 } |
1538 } | 1522 } |
1539 | 1523 |
1540 | 1524 |
1541 HeapWord* | 1525 HeapWord* |
1617 assert_at_safepoint(true /* should_be_vm_thread */); | 1601 assert_at_safepoint(true /* should_be_vm_thread */); |
1618 | 1602 |
1619 verify_region_sets_optional(); | 1603 verify_region_sets_optional(); |
1620 | 1604 |
1621 size_t expand_bytes = MAX2(word_size * HeapWordSize, MinHeapDeltaBytes); | 1605 size_t expand_bytes = MAX2(word_size * HeapWordSize, MinHeapDeltaBytes); |
1606 ergo_verbose1(ErgoHeapSizing, | |
1607 "attempt heap expansion", | |
1608 ergo_format_reason("allocation request failed") | |
1609 ergo_format_byte("allocation request"), | |
1610 word_size * HeapWordSize); | |
1622 if (expand(expand_bytes)) { | 1611 if (expand(expand_bytes)) { |
1623 _hrs.verify_optional(); | 1612 _hrs.verify_optional(); |
1624 verify_region_sets_optional(); | 1613 verify_region_sets_optional(); |
1625 return attempt_allocation_at_safepoint(word_size, | 1614 return attempt_allocation_at_safepoint(word_size, |
1626 false /* expect_null_mutator_alloc_region */); | 1615 false /* expect_null_mutator_alloc_region */); |
1644 bool G1CollectedHeap::expand(size_t expand_bytes) { | 1633 bool G1CollectedHeap::expand(size_t expand_bytes) { |
1645 size_t old_mem_size = _g1_storage.committed_size(); | 1634 size_t old_mem_size = _g1_storage.committed_size(); |
1646 size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); | 1635 size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); |
1647 aligned_expand_bytes = align_size_up(aligned_expand_bytes, | 1636 aligned_expand_bytes = align_size_up(aligned_expand_bytes, |
1648 HeapRegion::GrainBytes); | 1637 HeapRegion::GrainBytes); |
1649 | 1638 ergo_verbose2(ErgoHeapSizing, |
1650 if (Verbose && PrintGC) { | 1639 "expand the heap", |
1651 gclog_or_tty->print("Expanding garbage-first heap from %ldK by %ldK", | 1640 ergo_format_byte("requested expansion amount") |
1652 old_mem_size/K, aligned_expand_bytes/K); | 1641 ergo_format_byte("attempted expansion amount"), |
1653 } | 1642 expand_bytes, aligned_expand_bytes); |
1654 | 1643 |
1655 // First commit the memory. | 1644 // First commit the memory. |
1656 HeapWord* old_end = (HeapWord*) _g1_storage.high(); | 1645 HeapWord* old_end = (HeapWord*) _g1_storage.high(); |
1657 bool successful = _g1_storage.expand_by(aligned_expand_bytes); | 1646 bool successful = _g1_storage.expand_by(aligned_expand_bytes); |
1658 if (successful) { | 1647 if (successful) { |
1692 curr = curr_end; | 1681 curr = curr_end; |
1693 } | 1682 } |
1694 assert(curr == mr.end(), "post-condition"); | 1683 assert(curr == mr.end(), "post-condition"); |
1695 } | 1684 } |
1696 } else { | 1685 } else { |
1686 ergo_verbose0(ErgoHeapSizing, | |
1687 "did not expand the heap", | |
1688 ergo_format_reason("heap expansion operation failed")); | |
1697 // The expansion of the virtual storage space was unsuccessful. | 1689 // The expansion of the virtual storage space was unsuccessful. |
1698 // Let's see if it was because we ran out of swap. | 1690 // Let's see if it was because we ran out of swap. |
1699 if (G1ExitOnExpansionFailure && | 1691 if (G1ExitOnExpansionFailure && |
1700 _g1_storage.uncommitted_size() >= aligned_expand_bytes) { | 1692 _g1_storage.uncommitted_size() >= aligned_expand_bytes) { |
1701 // We had head room... | 1693 // We had head room... |
1702 vm_exit_out_of_memory(aligned_expand_bytes, "G1 heap expansion"); | 1694 vm_exit_out_of_memory(aligned_expand_bytes, "G1 heap expansion"); |
1703 } | 1695 } |
1704 } | |
1705 | |
1706 if (Verbose && PrintGC) { | |
1707 size_t new_mem_size = _g1_storage.committed_size(); | |
1708 gclog_or_tty->print_cr("...%s, expanded to %ldK", | |
1709 (successful ? "Successful" : "Failed"), | |
1710 new_mem_size/K); | |
1711 } | 1696 } |
1712 return successful; | 1697 return successful; |
1713 } | 1698 } |
1714 | 1699 |
1715 void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { | 1700 void G1CollectedHeap::shrink_helper(size_t shrink_bytes) { |
1720 HeapRegion::GrainBytes); | 1705 HeapRegion::GrainBytes); |
1721 size_t num_regions_deleted = 0; | 1706 size_t num_regions_deleted = 0; |
1722 MemRegion mr = _hrs.shrink_by(aligned_shrink_bytes, &num_regions_deleted); | 1707 MemRegion mr = _hrs.shrink_by(aligned_shrink_bytes, &num_regions_deleted); |
1723 HeapWord* old_end = (HeapWord*) _g1_storage.high(); | 1708 HeapWord* old_end = (HeapWord*) _g1_storage.high(); |
1724 assert(mr.end() == old_end, "post-condition"); | 1709 assert(mr.end() == old_end, "post-condition"); |
1710 | |
1711 ergo_verbose3(ErgoHeapSizing, | |
1712 "shrink the heap", | |
1713 ergo_format_byte("requested shrinking amount") | |
1714 ergo_format_byte("aligned shrinking amount") | |
1715 ergo_format_byte("attempted shrinking amount"), | |
1716 shrink_bytes, aligned_shrink_bytes, mr.byte_size()); | |
1725 if (mr.byte_size() > 0) { | 1717 if (mr.byte_size() > 0) { |
1726 if (_hr_printer.is_active()) { | 1718 if (_hr_printer.is_active()) { |
1727 HeapWord* curr = mr.end(); | 1719 HeapWord* curr = mr.end(); |
1728 while (curr > mr.start()) { | 1720 while (curr > mr.start()) { |
1729 HeapWord* curr_end = curr; | 1721 HeapWord* curr_end = curr; |
1738 assert(mr.start() == new_end, "post-condition"); | 1730 assert(mr.start() == new_end, "post-condition"); |
1739 | 1731 |
1740 _expansion_regions += num_regions_deleted; | 1732 _expansion_regions += num_regions_deleted; |
1741 update_committed_space(old_end, new_end); | 1733 update_committed_space(old_end, new_end); |
1742 HeapRegionRemSet::shrink_heap(n_regions()); | 1734 HeapRegionRemSet::shrink_heap(n_regions()); |
1743 | 1735 } else { |
1744 if (Verbose && PrintGC) { | 1736 ergo_verbose0(ErgoHeapSizing, |
1745 size_t new_mem_size = _g1_storage.committed_size(); | 1737 "did not shrink the heap", |
1746 gclog_or_tty->print_cr("Shrinking garbage-first heap from %ldK by %ldK to %ldK", | 1738 ergo_format_reason("heap shrinking operation failed")); |
1747 old_mem_size/K, aligned_shrink_bytes/K, | |
1748 new_mem_size/K); | |
1749 } | |
1750 } | 1739 } |
1751 } | 1740 } |
1752 | 1741 |
1753 void G1CollectedHeap::shrink(size_t shrink_bytes) { | 1742 void G1CollectedHeap::shrink(size_t shrink_bytes) { |
1754 verify_region_sets_optional(); | 1743 verify_region_sets_optional(); |
3577 | 3566 |
3578 { | 3567 { |
3579 size_t expand_bytes = g1_policy()->expansion_amount(); | 3568 size_t expand_bytes = g1_policy()->expansion_amount(); |
3580 if (expand_bytes > 0) { | 3569 if (expand_bytes > 0) { |
3581 size_t bytes_before = capacity(); | 3570 size_t bytes_before = capacity(); |
3571 // No need for an ergo verbose message here, | |
3572 // expansion_amount() does this when it returns a value > 0. | |
3582 if (!expand(expand_bytes)) { | 3573 if (!expand(expand_bytes)) { |
3583 // We failed to expand the heap so let's verify that | 3574 // We failed to expand the heap so let's verify that |
3584 // committed/uncommitted amount match the backing store | 3575 // committed/uncommitted amount match the backing store |
3585 assert(capacity() == _g1_storage.committed_size(), "committed size mismatch"); | 3576 assert(capacity() == _g1_storage.committed_size(), "committed size mismatch"); |
3586 assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch"); | 3577 assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch"); |
3730 G1IsAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} | 3721 G1IsAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} |
3731 void do_object(oop p) { assert(false, "Do not call."); } | 3722 void do_object(oop p) { assert(false, "Do not call."); } |
3732 bool do_object_b(oop p) { | 3723 bool do_object_b(oop p) { |
3733 // It is reachable if it is outside the collection set, or is inside | 3724 // It is reachable if it is outside the collection set, or is inside |
3734 // and forwarded. | 3725 // and forwarded. |
3735 | |
3736 #ifdef G1_DEBUG | |
3737 gclog_or_tty->print_cr("is alive "PTR_FORMAT" in CS %d forwarded %d overall %d", | |
3738 (void*) p, _g1->obj_in_cs(p), p->is_forwarded(), | |
3739 !_g1->obj_in_cs(p) || p->is_forwarded()); | |
3740 #endif // G1_DEBUG | |
3741 | |
3742 return !_g1->obj_in_cs(p) || p->is_forwarded(); | 3726 return !_g1->obj_in_cs(p) || p->is_forwarded(); |
3743 } | 3727 } |
3744 }; | 3728 }; |
3745 | 3729 |
3746 class G1KeepAliveClosure: public OopClosure { | 3730 class G1KeepAliveClosure: public OopClosure { |
3748 public: | 3732 public: |
3749 G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} | 3733 G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {} |
3750 void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } | 3734 void do_oop(narrowOop* p) { guarantee(false, "Not needed"); } |
3751 void do_oop( oop* p) { | 3735 void do_oop( oop* p) { |
3752 oop obj = *p; | 3736 oop obj = *p; |
3753 #ifdef G1_DEBUG | |
3754 if (PrintGC && Verbose) { | |
3755 gclog_or_tty->print_cr("keep alive *"PTR_FORMAT" = "PTR_FORMAT" "PTR_FORMAT, | |
3756 p, (void*) obj, (void*) *p); | |
3757 } | |
3758 #endif // G1_DEBUG | |
3759 | |
3760 if (_g1->obj_in_cs(obj)) { | 3737 if (_g1->obj_in_cs(obj)) { |
3761 assert( obj->is_forwarded(), "invariant" ); | 3738 assert( obj->is_forwarded(), "invariant" ); |
3762 *p = obj->forwardee(); | 3739 *p = obj->forwardee(); |
3763 #ifdef G1_DEBUG | |
3764 gclog_or_tty->print_cr(" in CSet: moved "PTR_FORMAT" -> "PTR_FORMAT, | |
3765 (void*) obj, (void*) *p); | |
3766 #endif // G1_DEBUG | |
3767 } | 3740 } |
3768 } | 3741 } |
3769 }; | 3742 }; |
3770 | 3743 |
3771 class UpdateRSetDeferred : public OopsInHeapRegionClosure { | 3744 class UpdateRSetDeferred : public OopsInHeapRegionClosure { |