< prev index next >

src/share/vm/gc_implementation/shared/parGCAllocBuffer.cpp

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 22,92 **** * */ #include "precompiled.hpp" #include "gc_implementation/shared/parGCAllocBuffer.hpp" ! #include "memory/sharedHeap.hpp" #include "oops/arrayOop.hpp" #include "oops/oop.inline.hpp" - #include "utilities/globalDefinitions.hpp" ! PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC ParGCAllocBuffer::ParGCAllocBuffer(size_t desired_plab_sz_) : _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL), ! _end(NULL), _hard_end(NULL), ! _retained(false), _retained_filler(), ! _allocated(0), _wasted(0) { assert (min_size() > AlignmentReserve, "Inconsistency!"); ! // arrayOopDesc::header_size depends on command line initialization. ! FillerHeaderSize = align_object_size(arrayOopDesc::header_size(T_INT)); ! AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? FillerHeaderSize : 0; } - size_t ParGCAllocBuffer::FillerHeaderSize; - // If the minimum object size is greater than MinObjAlignment, we can // end up with a shard at the end of the buffer that's smaller than // the smallest object. We can't allow that because the buffer must // look like it's full of objects when we retire it, so we make // sure we have enough space for a filler int array object. size_t ParGCAllocBuffer::AlignmentReserve; ! void ParGCAllocBuffer::retire(bool end_of_gc, bool retain) { ! assert(!retain || end_of_gc, "Can only retain at GC end."); ! if (_retained) { ! // If the buffer had been retained shorten the previous filler object. ! assert(_retained_filler.end() <= _top, "INVARIANT"); ! CollectedHeap::fill_with_object(_retained_filler); ! // Wasted space book-keeping, otherwise (normally) done in invalidate() ! _wasted += _retained_filler.word_size(); ! _retained = false; ! } ! assert(!end_of_gc || !_retained, "At this point, end_of_gc ==> !_retained."); if (_top < _hard_end) { CollectedHeap::fill_with_object(_top, _hard_end); - if (!retain) { - invalidate(); - } else { - // Is there wasted space we'd like to retain for the next GC? - if (pointer_delta(_end, _top) > FillerHeaderSize) { - _retained = true; - _retained_filler = MemRegion(_top, FillerHeaderSize); - _top = _top + FillerHeaderSize; - } else { invalidate(); } - } - } - } - - void ParGCAllocBuffer::flush_stats(PLABStats* stats) { - assert(ResizePLAB, "Wasted work"); - stats->add_allocated(_allocated); - stats->add_wasted(_wasted); - stats->add_unused(pointer_delta(_end, _top)); } // Compute desired plab size and latch result for later // use. This should be called once at the end of parallel // scavenge; it clears the sensor accumulators. --- 22,87 ---- * */ #include "precompiled.hpp" #include "gc_implementation/shared/parGCAllocBuffer.hpp" ! #include "memory/threadLocalAllocBuffer.hpp" #include "oops/arrayOop.hpp" #include "oops/oop.inline.hpp" ! const size_t ParGCAllocBuffer::min_size() { ! // Make sure that we return something that is larger than AlignmentReserve ! return align_object_size(MAX2(MinTLABSize / HeapWordSize, (uintx)oopDesc::header_size())) + AlignmentReserve; ! } ! ! const size_t ParGCAllocBuffer::max_size() { ! return ThreadLocalAllocBuffer::max_size(); ! } ParGCAllocBuffer::ParGCAllocBuffer(size_t desired_plab_sz_) : _word_sz(desired_plab_sz_), _bottom(NULL), _top(NULL), ! _end(NULL), _hard_end(NULL), _allocated(0), _wasted(0) { assert (min_size() > AlignmentReserve, "Inconsistency!"); ! // ArrayOopDesc::header_size depends on command line initialization. ! AlignmentReserve = oopDesc::header_size() > MinObjAlignment ? align_object_size(arrayOopDesc::header_size(T_INT)) : 0; } // If the minimum object size is greater than MinObjAlignment, we can // end up with a shard at the end of the buffer that's smaller than // the smallest object. We can't allow that because the buffer must // look like it's full of objects when we retire it, so we make // sure we have enough space for a filler int array object. size_t ParGCAllocBuffer::AlignmentReserve; ! void ParGCAllocBuffer::flush_and_retire_stats(PLABStats* stats) { ! // We want to distinguish between unused space in the last buffer and waste ! // created otherwise. Save the amount of unused space because retire() will ! // update the pointers we use. ! size_t unused = pointer_delta(_end, _top); ! ! // Retire the last allocation buffer. ! retire(); ! ! stats->add_allocated(_allocated); ! // Retire() counts the unused space as wasted. So we need to remove it again ! // before updating the statistics. ! stats->add_wasted(_wasted - unused); ! stats->add_unused(unused); ! ! // Since we have flushed the stats we need to clear the _allocated and _wasted ! // fields in case somebody retains an instance of this over GCs. Not doing so ! // will artifically inflate the values in the statistics. ! _allocated = 0; ! _wasted = 0; ! } ! ! void ParGCAllocBuffer::retire() { if (_top < _hard_end) { CollectedHeap::fill_with_object(_top, _hard_end); invalidate(); } } // Compute desired plab size and latch result for later // use. This should be called once at the end of parallel // scavenge; it clears the sensor accumulators.
*** 99,144 **** if (_allocated == 0) { assert(_unused == 0, err_msg("Inconsistency in PLAB stats: " "_allocated: "SIZE_FORMAT", " "_wasted: "SIZE_FORMAT", " ! "_unused: "SIZE_FORMAT", " ! "_used : "SIZE_FORMAT, ! _allocated, _wasted, _unused, _used)); _allocated = 1; } ! double wasted_frac = (double)_unused/(double)_allocated; ! size_t target_refills = (size_t)((wasted_frac*TargetSurvivorRatio)/ ! TargetPLABWastePct); if (target_refills == 0) { target_refills = 1; } ! _used = _allocated - _wasted - _unused; ! size_t plab_sz = _used/(target_refills*no_of_gc_workers); ! if (PrintPLAB) gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT " ", plab_sz); // Take historical weighted average ! _filter.sample(plab_sz); // Clip from above and below, and align to object boundary ! plab_sz = MAX2(min_size(), (size_t)_filter.average()); ! plab_sz = MIN2(max_size(), plab_sz); ! plab_sz = align_object_size(plab_sz); // Latch the result ! if (PrintPLAB) gclog_or_tty->print(" desired_plab_sz = " SIZE_FORMAT ") ", plab_sz); ! _desired_plab_sz = plab_sz; ! // Now clear the accumulators for next round: ! // note this needs to be fixed in the case where we ! // are retaining across scavenges. FIX ME !!! XXX ! _allocated = 0; ! _wasted = 0; ! _unused = 0; } #ifndef PRODUCT void ParGCAllocBuffer::print() { ! gclog_or_tty->print("parGCAllocBuffer: _bottom: " PTR_FORMAT " _top: " PTR_FORMAT ! " _end: " PTR_FORMAT " _hard_end: " PTR_FORMAT " _retained: %c" ! " _retained_filler: [" PTR_FORMAT "," PTR_FORMAT ")\n", ! _bottom, _top, _end, _hard_end, ! "FT"[_retained], _retained_filler.start(), _retained_filler.end()); } #endif // !PRODUCT --- 94,132 ---- if (_allocated == 0) { assert(_unused == 0, err_msg("Inconsistency in PLAB stats: " "_allocated: "SIZE_FORMAT", " "_wasted: "SIZE_FORMAT", " ! "_unused: "SIZE_FORMAT, ! _allocated, _wasted, _unused)); _allocated = 1; } ! double wasted_frac = (double)_unused / (double)_allocated; ! size_t target_refills = (size_t)((wasted_frac * TargetSurvivorRatio) / TargetPLABWastePct); if (target_refills == 0) { target_refills = 1; } ! size_t used = _allocated - _wasted - _unused; ! size_t recent_plab_sz = used / (target_refills * no_of_gc_workers); // Take historical weighted average ! _filter.sample(recent_plab_sz); // Clip from above and below, and align to object boundary ! size_t new_plab_sz = MAX2(min_size(), (size_t)_filter.average()); ! new_plab_sz = MIN2(max_size(), new_plab_sz); ! new_plab_sz = align_object_size(new_plab_sz); // Latch the result ! if (PrintPLAB) { ! gclog_or_tty->print(" (plab_sz = " SIZE_FORMAT" desired_plab_sz = " SIZE_FORMAT") ", recent_plab_sz, new_plab_sz); ! } ! _desired_plab_sz = new_plab_sz; ! ! reset(); } #ifndef PRODUCT void ParGCAllocBuffer::print() { ! gclog_or_tty->print_cr("parGCAllocBuffer: _bottom: " PTR_FORMAT " _top: " PTR_FORMAT ! " _end: " PTR_FORMAT " _hard_end: " PTR_FORMAT ")", ! p2i(_bottom), p2i(_top), p2i(_end), p2i(_hard_end)); } #endif // !PRODUCT
< prev index next >