547
548
549 void CompactibleFreeListSpace::reportFreeListStatistics() const {
550 assert_lock_strong(&_freelistLock);
551 assert(PrintFLSStatistics != 0, "Reporting error");
552 _dictionary->report_statistics();
553 if (PrintFLSStatistics > 1) {
554 reportIndexedFreeListStatistics();
555 size_t total_size = totalSizeInIndexedFreeLists() +
556 _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock()));
557 gclog_or_tty->print(" free=" SIZE_FORMAT " frag=%1.4f\n", total_size, flsFrag());
558 }
559 }
560
561 void CompactibleFreeListSpace::reportIndexedFreeListStatistics() const {
562 assert_lock_strong(&_freelistLock);
563 gclog_or_tty->print("Statistics for IndexedFreeLists:\n"
564 "--------------------------------\n");
565 size_t total_size = totalSizeInIndexedFreeLists();
566 size_t free_blocks = numFreeBlocksInIndexedFreeLists();
567 gclog_or_tty->print("Total Free Space: %d\n", total_size);
568 gclog_or_tty->print("Max Chunk Size: %d\n", maxChunkSizeInIndexedFreeLists());
569 gclog_or_tty->print("Number of Blocks: %d\n", free_blocks);
570 if (free_blocks != 0) {
571 gclog_or_tty->print("Av. Block Size: %d\n", total_size/free_blocks);
572 }
573 }
574
575 size_t CompactibleFreeListSpace::numFreeBlocksInIndexedFreeLists() const {
576 size_t res = 0;
577 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
578 debug_only(
579 ssize_t recount = 0;
580 for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
581 fc = fc->next()) {
582 recount += 1;
583 }
584 assert(recount == _indexedFreeList[i].count(),
585 "Incorrect count in list");
586 )
587 res += _indexedFreeList[i].count();
588 }
589 return res;
590 }
591
2135 _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock()));
2136 if (totFree > 0) {
2137 frag = ((frag + _dictionary->sum_of_squared_block_sizes()) /
2138 (totFree * totFree));
2139 frag = (double)1.0 - frag;
2140 } else {
2141 assert(frag == 0.0, "Follows from totFree == 0");
2142 }
2143 return frag;
2144 }
2145
2146 void CompactibleFreeListSpace::beginSweepFLCensus(
2147 float inter_sweep_current,
2148 float inter_sweep_estimate,
2149 float intra_sweep_estimate) {
2150 assert_locked();
2151 size_t i;
2152 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
2153 AdaptiveFreeList<FreeChunk>* fl = &_indexedFreeList[i];
2154 if (PrintFLSStatistics > 1) {
2155 gclog_or_tty->print("size[%d] : ", i);
2156 }
2157 fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
2158 fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
2159 fl->set_before_sweep(fl->count());
2160 fl->set_bfr_surp(fl->surplus());
2161 }
2162 _dictionary->begin_sweep_dict_census(CMSLargeCoalSurplusPercent,
2163 inter_sweep_current,
2164 inter_sweep_estimate,
2165 intra_sweep_estimate);
2166 }
2167
2168 void CompactibleFreeListSpace::setFLSurplus() {
2169 assert_locked();
2170 size_t i;
2171 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
2172 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[i];
2173 fl->set_surplus(fl->count() -
2174 (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent));
2175 }
2666 }
2667
2668 void CFLS_LAB::compute_desired_plab_size() {
2669 for (size_t i = CompactibleFreeListSpace::IndexSetStart;
2670 i < CompactibleFreeListSpace::IndexSetSize;
2671 i += CompactibleFreeListSpace::IndexSetStride) {
2672 assert((_global_num_workers[i] == 0) == (_global_num_blocks[i] == 0),
2673 "Counter inconsistency");
2674 if (_global_num_workers[i] > 0) {
2675 // Need to smooth wrt historical average
2676 if (ResizeOldPLAB) {
2677 _blocks_to_claim[i].sample(
2678 MAX2((size_t)CMSOldPLABMin,
2679 MIN2((size_t)CMSOldPLABMax,
2680 _global_num_blocks[i]/(_global_num_workers[i]*CMSOldPLABNumRefills))));
2681 }
2682 // Reset counters for next round
2683 _global_num_workers[i] = 0;
2684 _global_num_blocks[i] = 0;
2685 if (PrintOldPLAB) {
2686 gclog_or_tty->print_cr("[%d]: %d", i, (size_t)_blocks_to_claim[i].average());
2687 }
2688 }
2689 }
2690 }
2691
2692 // If this is changed in the future to allow parallel
2693 // access, one would need to take the FL locks and,
2694 // depending on how it is used, stagger access from
2695 // parallel threads to reduce contention.
2696 void CFLS_LAB::retire(int tid) {
2697 // We run this single threaded with the world stopped;
2698 // so no need for locks and such.
2699 NOT_PRODUCT(Thread* t = Thread::current();)
2700 assert(Thread::current()->is_VM_thread(), "Error");
2701 for (size_t i = CompactibleFreeListSpace::IndexSetStart;
2702 i < CompactibleFreeListSpace::IndexSetSize;
2703 i += CompactibleFreeListSpace::IndexSetStride) {
2704 assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(),
2705 "Can't retire more than what we obtained");
2706 if (_num_blocks[i] > 0) {
2707 size_t num_retire = _indexedFreeList[i].count();
2708 assert(_num_blocks[i] > num_retire, "Should have used at least one");
2709 {
2710 // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
2711 // Mutex::_no_safepoint_check_flag);
2712
2713 // Update globals stats for num_blocks used
2714 _global_num_blocks[i] += (_num_blocks[i] - num_retire);
2715 _global_num_workers[i]++;
2716 assert(_global_num_workers[i] <= ParallelGCThreads, "Too big");
2717 if (num_retire > 0) {
2718 _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
2719 // Reset this list.
2720 _indexedFreeList[i] = AdaptiveFreeList<FreeChunk>();
2721 _indexedFreeList[i].set_size(i);
2722 }
2723 }
2724 if (PrintOldPLAB) {
2725 gclog_or_tty->print_cr("%d[%d]: %d/%d/%d",
2726 tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average());
2727 }
2728 // Reset stats for next round
2729 _num_blocks[i] = 0;
2730 }
2731 }
2732 }
2733
2734 void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList<FreeChunk>* fl) {
2735 assert(fl->count() == 0, "Precondition.");
2736 assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
2737 "Precondition");
2738
2739 // We'll try all multiples of word_sz in the indexed set, starting with
2740 // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples,
2741 // then try getting a big chunk and splitting it.
2742 {
2743 bool found;
2744 int k;
2745 size_t cur_sz;
|
547
548
549 void CompactibleFreeListSpace::reportFreeListStatistics() const {
550 assert_lock_strong(&_freelistLock);
551 assert(PrintFLSStatistics != 0, "Reporting error");
552 _dictionary->report_statistics();
553 if (PrintFLSStatistics > 1) {
554 reportIndexedFreeListStatistics();
555 size_t total_size = totalSizeInIndexedFreeLists() +
556 _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock()));
557 gclog_or_tty->print(" free=" SIZE_FORMAT " frag=%1.4f\n", total_size, flsFrag());
558 }
559 }
560
561 void CompactibleFreeListSpace::reportIndexedFreeListStatistics() const {
562 assert_lock_strong(&_freelistLock);
563 gclog_or_tty->print("Statistics for IndexedFreeLists:\n"
564 "--------------------------------\n");
565 size_t total_size = totalSizeInIndexedFreeLists();
566 size_t free_blocks = numFreeBlocksInIndexedFreeLists();
567 gclog_or_tty->print("Total Free Space: " SIZE_FORMAT "\n", total_size);
568 gclog_or_tty->print("Max Chunk Size: " SIZE_FORMAT "\n", maxChunkSizeInIndexedFreeLists());
569 gclog_or_tty->print("Number of Blocks: " SIZE_FORMAT "\n", free_blocks);
570 if (free_blocks != 0) {
571 gclog_or_tty->print("Av. Block Size: " SIZE_FORMAT "\n", total_size/free_blocks);
572 }
573 }
574
575 size_t CompactibleFreeListSpace::numFreeBlocksInIndexedFreeLists() const {
576 size_t res = 0;
577 for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
578 debug_only(
579 ssize_t recount = 0;
580 for (FreeChunk* fc = _indexedFreeList[i].head(); fc != NULL;
581 fc = fc->next()) {
582 recount += 1;
583 }
584 assert(recount == _indexedFreeList[i].count(),
585 "Incorrect count in list");
586 )
587 res += _indexedFreeList[i].count();
588 }
589 return res;
590 }
591
2135 _dictionary->total_chunk_size(DEBUG_ONLY(freelistLock()));
2136 if (totFree > 0) {
2137 frag = ((frag + _dictionary->sum_of_squared_block_sizes()) /
2138 (totFree * totFree));
2139 frag = (double)1.0 - frag;
2140 } else {
2141 assert(frag == 0.0, "Follows from totFree == 0");
2142 }
2143 return frag;
2144 }
2145
2146 void CompactibleFreeListSpace::beginSweepFLCensus(
2147 float inter_sweep_current,
2148 float inter_sweep_estimate,
2149 float intra_sweep_estimate) {
2150 assert_locked();
2151 size_t i;
2152 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
2153 AdaptiveFreeList<FreeChunk>* fl = &_indexedFreeList[i];
2154 if (PrintFLSStatistics > 1) {
2155 gclog_or_tty->print("size[" SIZE_FORMAT "] : ", i);
2156 }
2157 fl->compute_desired(inter_sweep_current, inter_sweep_estimate, intra_sweep_estimate);
2158 fl->set_coal_desired((ssize_t)((double)fl->desired() * CMSSmallCoalSurplusPercent));
2159 fl->set_before_sweep(fl->count());
2160 fl->set_bfr_surp(fl->surplus());
2161 }
2162 _dictionary->begin_sweep_dict_census(CMSLargeCoalSurplusPercent,
2163 inter_sweep_current,
2164 inter_sweep_estimate,
2165 intra_sweep_estimate);
2166 }
2167
2168 void CompactibleFreeListSpace::setFLSurplus() {
2169 assert_locked();
2170 size_t i;
2171 for (i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) {
2172 AdaptiveFreeList<FreeChunk> *fl = &_indexedFreeList[i];
2173 fl->set_surplus(fl->count() -
2174 (ssize_t)((double)fl->desired() * CMSSmallSplitSurplusPercent));
2175 }
2666 }
2667
2668 void CFLS_LAB::compute_desired_plab_size() {
2669 for (size_t i = CompactibleFreeListSpace::IndexSetStart;
2670 i < CompactibleFreeListSpace::IndexSetSize;
2671 i += CompactibleFreeListSpace::IndexSetStride) {
2672 assert((_global_num_workers[i] == 0) == (_global_num_blocks[i] == 0),
2673 "Counter inconsistency");
2674 if (_global_num_workers[i] > 0) {
2675 // Need to smooth wrt historical average
2676 if (ResizeOldPLAB) {
2677 _blocks_to_claim[i].sample(
2678 MAX2((size_t)CMSOldPLABMin,
2679 MIN2((size_t)CMSOldPLABMax,
2680 _global_num_blocks[i]/(_global_num_workers[i]*CMSOldPLABNumRefills))));
2681 }
2682 // Reset counters for next round
2683 _global_num_workers[i] = 0;
2684 _global_num_blocks[i] = 0;
2685 if (PrintOldPLAB) {
2686 gclog_or_tty->print_cr("[" SIZE_FORMAT "]: " SIZE_FORMAT,
2687 i, (size_t)_blocks_to_claim[i].average());
2688 }
2689 }
2690 }
2691 }
2692
2693 // If this is changed in the future to allow parallel
2694 // access, one would need to take the FL locks and,
2695 // depending on how it is used, stagger access from
2696 // parallel threads to reduce contention.
2697 void CFLS_LAB::retire(int tid) {
2698 // We run this single threaded with the world stopped;
2699 // so no need for locks and such.
2700 NOT_PRODUCT(Thread* t = Thread::current();)
2701 assert(Thread::current()->is_VM_thread(), "Error");
2702 for (size_t i = CompactibleFreeListSpace::IndexSetStart;
2703 i < CompactibleFreeListSpace::IndexSetSize;
2704 i += CompactibleFreeListSpace::IndexSetStride) {
2705 assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(),
2706 "Can't retire more than what we obtained");
2707 if (_num_blocks[i] > 0) {
2708 size_t num_retire = _indexedFreeList[i].count();
2709 assert(_num_blocks[i] > num_retire, "Should have used at least one");
2710 {
2711 // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i],
2712 // Mutex::_no_safepoint_check_flag);
2713
2714 // Update globals stats for num_blocks used
2715 _global_num_blocks[i] += (_num_blocks[i] - num_retire);
2716 _global_num_workers[i]++;
2717 assert(_global_num_workers[i] <= ParallelGCThreads, "Too big");
2718 if (num_retire > 0) {
2719 _cfls->_indexedFreeList[i].prepend(&_indexedFreeList[i]);
2720 // Reset this list.
2721 _indexedFreeList[i] = AdaptiveFreeList<FreeChunk>();
2722 _indexedFreeList[i].set_size(i);
2723 }
2724 }
2725 if (PrintOldPLAB) {
2726 gclog_or_tty->print_cr("%d[" SIZE_FORMAT "]: " SIZE_FORMAT "/" SIZE_FORMAT "/" SIZE_FORMAT,
2727 tid, i, num_retire, _num_blocks[i], (size_t)_blocks_to_claim[i].average());
2728 }
2729 // Reset stats for next round
2730 _num_blocks[i] = 0;
2731 }
2732 }
2733 }
2734
2735 void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList<FreeChunk>* fl) {
2736 assert(fl->count() == 0, "Precondition.");
2737 assert(word_sz < CompactibleFreeListSpace::IndexSetSize,
2738 "Precondition");
2739
2740 // We'll try all multiples of word_sz in the indexed set, starting with
2741 // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples,
2742 // then try getting a big chunk and splitting it.
2743 {
2744 bool found;
2745 int k;
2746 size_t cur_sz;
|