Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @ 1145:e018e6884bd8
6631166: CMS: better heuristics when combatting fragmentation
Summary: Autonomic per-worker free block cache sizing, tunable coalition policies, fixes to per-size block statistics, retuned gain and bandwidth of some feedback loop filters to allow quicker reactivity to abrupt changes in ambient demand, and other heuristics to reduce fragmentation of the CMS old gen. Also tightened some assertions, including those related to locking.
Reviewed-by: jmasa
author | ysr |
---|---|
date | Wed, 23 Dec 2009 09:23:54 -0800 |
parents | 0fbdb4381b99 |
children | a8127dc669ba |
comparison
equal
deleted
inserted
replaced
1111:44f61c24ddab | 1145:e018e6884bd8 |
---|---|
23 */ | 23 */ |
24 | 24 |
25 // Classes in support of keeping track of promotions into a non-Contiguous | 25 // Classes in support of keeping track of promotions into a non-Contiguous |
26 // space, in this case a CompactibleFreeListSpace. | 26 // space, in this case a CompactibleFreeListSpace. |
27 | 27 |
28 #define CFLS_LAB_REFILL_STATS 0 | |
29 | |
30 // Forward declarations | 28 // Forward declarations |
31 class CompactibleFreeListSpace; | 29 class CompactibleFreeListSpace; |
32 class BlkClosure; | 30 class BlkClosure; |
33 class BlkClosureCareful; | 31 class BlkClosureCareful; |
34 class UpwardsObjectClosure; | 32 class UpwardsObjectClosure; |
87 void init() { | 85 void init() { |
88 bufferSize = computeBufferSize(); | 86 bufferSize = computeBufferSize(); |
89 displacedHdr = (markOop*)&displacedHdr; | 87 displacedHdr = (markOop*)&displacedHdr; |
90 nextSpoolBlock = NULL; | 88 nextSpoolBlock = NULL; |
91 } | 89 } |
90 | |
91 void print_on(outputStream* st) const; | |
92 void print() const { print_on(gclog_or_tty); } | |
92 }; | 93 }; |
93 | 94 |
94 class PromotionInfo VALUE_OBJ_CLASS_SPEC { | 95 class PromotionInfo VALUE_OBJ_CLASS_SPEC { |
95 bool _tracking; // set if tracking | 96 bool _tracking; // set if tracking |
96 CompactibleFreeListSpace* _space; // the space to which this belongs | 97 CompactibleFreeListSpace* _space; // the space to which this belongs |
119 bool noPromotions() const { | 120 bool noPromotions() const { |
120 assert(_promoHead != NULL || _promoTail == NULL, "list inconsistency"); | 121 assert(_promoHead != NULL || _promoTail == NULL, "list inconsistency"); |
121 return _promoHead == NULL; | 122 return _promoHead == NULL; |
122 } | 123 } |
123 void startTrackingPromotions(); | 124 void startTrackingPromotions(); |
124 void stopTrackingPromotions(); | 125 void stopTrackingPromotions(uint worker_id = 0); |
125 bool tracking() const { return _tracking; } | 126 bool tracking() const { return _tracking; } |
126 void track(PromotedObject* trackOop); // keep track of a promoted oop | 127 void track(PromotedObject* trackOop); // keep track of a promoted oop |
127 // The following variant must be used when trackOop is not fully | 128 // The following variant must be used when trackOop is not fully |
128 // initialized and has a NULL klass: | 129 // initialized and has a NULL klass: |
129 void track(PromotedObject* trackOop, klassOop klassOfOop); // keep track of a promoted oop | 130 void track(PromotedObject* trackOop, klassOop klassOfOop); // keep track of a promoted oop |
159 _spareSpool = NULL; | 160 _spareSpool = NULL; |
160 _firstIndex = 0; | 161 _firstIndex = 0; |
161 _nextIndex = 0; | 162 _nextIndex = 0; |
162 | 163 |
163 } | 164 } |
165 | |
166 void print_on(outputStream* st) const; | |
167 void print_statistics(uint worker_id) const; | |
164 }; | 168 }; |
165 | 169 |
166 class LinearAllocBlock VALUE_OBJ_CLASS_SPEC { | 170 class LinearAllocBlock VALUE_OBJ_CLASS_SPEC { |
167 public: | 171 public: |
168 LinearAllocBlock() : _ptr(0), _word_size(0), _refillSize(0), | 172 LinearAllocBlock() : _ptr(0), _word_size(0), _refillSize(0), |
241 // a lock protecting the free lists and free blocks; | 245 // a lock protecting the free lists and free blocks; |
242 // mutable because of ubiquity of locking even for otherwise const methods | 246 // mutable because of ubiquity of locking even for otherwise const methods |
243 mutable Mutex _freelistLock; | 247 mutable Mutex _freelistLock; |
244 // locking verifier convenience function | 248 // locking verifier convenience function |
245 void assert_locked() const PRODUCT_RETURN; | 249 void assert_locked() const PRODUCT_RETURN; |
250 void assert_locked(const Mutex* lock) const PRODUCT_RETURN; | |
246 | 251 |
247 // Linear allocation blocks | 252 // Linear allocation blocks |
248 LinearAllocBlock _smallLinearAllocBlock; | 253 LinearAllocBlock _smallLinearAllocBlock; |
249 | 254 |
250 FreeBlockDictionary::DictionaryChoice _dictionaryChoice; | 255 FreeBlockDictionary::DictionaryChoice _dictionaryChoice; |
278 mutable Mutex _parDictionaryAllocLock; | 283 mutable Mutex _parDictionaryAllocLock; |
279 Mutex* parDictionaryAllocLock() const { return &_parDictionaryAllocLock; } | 284 Mutex* parDictionaryAllocLock() const { return &_parDictionaryAllocLock; } |
280 | 285 |
281 // Locks protecting the exact lists during par promotion allocation. | 286 // Locks protecting the exact lists during par promotion allocation. |
282 Mutex* _indexedFreeListParLocks[IndexSetSize]; | 287 Mutex* _indexedFreeListParLocks[IndexSetSize]; |
283 | |
284 #if CFLS_LAB_REFILL_STATS | |
285 // Some statistics. | |
286 jint _par_get_chunk_from_small; | |
287 jint _par_get_chunk_from_large; | |
288 #endif | |
289 | |
290 | 288 |
291 // Attempt to obtain up to "n" blocks of the size "word_sz" (which is | 289 // Attempt to obtain up to "n" blocks of the size "word_sz" (which is |
292 // required to be smaller than "IndexSetSize".) If successful, | 290 // required to be smaller than "IndexSetSize".) If successful, |
293 // adds them to "fl", which is required to be an empty free list. | 291 // adds them to "fl", which is required to be an empty free list. |
294 // If the count of "fl" is negative, it's absolute value indicates a | 292 // If the count of "fl" is negative, it's absolute value indicates a |
318 inline HeapWord* getChunkFromSmallLinearAllocBlockRemainder(size_t size); | 316 inline HeapWord* getChunkFromSmallLinearAllocBlockRemainder(size_t size); |
319 | 317 |
320 // Helper function for getChunkFromIndexedFreeList. | 318 // Helper function for getChunkFromIndexedFreeList. |
321 // Replenish the indexed free list for this "size". Do not take from an | 319 // Replenish the indexed free list for this "size". Do not take from an |
322 // underpopulated size. | 320 // underpopulated size. |
323 FreeChunk* getChunkFromIndexedFreeListHelper(size_t size); | 321 FreeChunk* getChunkFromIndexedFreeListHelper(size_t size, bool replenish = true); |
324 | 322 |
325 // Get a chunk from the indexed free list. If the indexed free list | 323 // Get a chunk from the indexed free list. If the indexed free list |
326 // does not have a free chunk, try to replenish the indexed free list | 324 // does not have a free chunk, try to replenish the indexed free list |
327 // then get the free chunk from the replenished indexed free list. | 325 // then get the free chunk from the replenished indexed free list. |
328 inline FreeChunk* getChunkFromIndexedFreeList(size_t size); | 326 inline FreeChunk* getChunkFromIndexedFreeList(size_t size); |
428 SequentialSubTasksDone* conc_par_seq_tasks() {return &_conc_par_seq_tasks; } | 426 SequentialSubTasksDone* conc_par_seq_tasks() {return &_conc_par_seq_tasks; } |
429 void initialize_sequential_subtasks_for_rescan(int n_threads); | 427 void initialize_sequential_subtasks_for_rescan(int n_threads); |
430 void initialize_sequential_subtasks_for_marking(int n_threads, | 428 void initialize_sequential_subtasks_for_marking(int n_threads, |
431 HeapWord* low = NULL); | 429 HeapWord* low = NULL); |
432 | 430 |
433 #if CFLS_LAB_REFILL_STATS | |
434 void print_par_alloc_stats(); | |
435 #endif | |
436 | |
437 // Space enquiries | 431 // Space enquiries |
438 size_t used() const; | 432 size_t used() const; |
439 size_t free() const; | 433 size_t free() const; |
440 size_t max_alloc_in_words() const; | 434 size_t max_alloc_in_words() const; |
441 // XXX: should have a less conservative used_region() than that of | 435 // XXX: should have a less conservative used_region() than that of |
615 // verify that the given chunk is in the free lists. | 609 // verify that the given chunk is in the free lists. |
616 bool verifyChunkInFreeLists(FreeChunk* fc) const; | 610 bool verifyChunkInFreeLists(FreeChunk* fc) const; |
617 // Do some basic checks on the the free lists. | 611 // Do some basic checks on the the free lists. |
618 void checkFreeListConsistency() const PRODUCT_RETURN; | 612 void checkFreeListConsistency() const PRODUCT_RETURN; |
619 | 613 |
614 // Printing support | |
615 void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st); | |
616 void print_indexed_free_lists(outputStream* st) const; | |
617 void print_dictionary_free_lists(outputStream* st) const; | |
618 void print_promo_info_blocks(outputStream* st) const; | |
619 | |
620 NOT_PRODUCT ( | 620 NOT_PRODUCT ( |
621 void initializeIndexedFreeListArrayReturnedBytes(); | 621 void initializeIndexedFreeListArrayReturnedBytes(); |
622 size_t sumIndexedFreeListArrayReturnedBytes(); | 622 size_t sumIndexedFreeListArrayReturnedBytes(); |
623 // Return the total number of chunks in the indexed free lists. | 623 // Return the total number of chunks in the indexed free lists. |
624 size_t totalCountInIndexedFreeLists() const; | 624 size_t totalCountInIndexedFreeLists() const; |
636 // Print the statistics for the free lists. | 636 // Print the statistics for the free lists. |
637 void printFLCensus(size_t sweep_count) const; | 637 void printFLCensus(size_t sweep_count) const; |
638 | 638 |
639 // Statistics functions | 639 // Statistics functions |
640 // Initialize census for lists before the sweep. | 640 // Initialize census for lists before the sweep. |
641 void beginSweepFLCensus(float sweep_current, | 641 void beginSweepFLCensus(float inter_sweep_current, |
642 float sweep_estimate); | 642 float inter_sweep_estimate, |
643 float intra_sweep_estimate); | |
643 // Set the surplus for each of the free lists. | 644 // Set the surplus for each of the free lists. |
644 void setFLSurplus(); | 645 void setFLSurplus(); |
645 // Set the hint for each of the free lists. | 646 // Set the hint for each of the free lists. |
646 void setFLHints(); | 647 void setFLHints(); |
647 // Clear the census for each of the free lists. | 648 // Clear the census for each of the free lists. |
728 | 729 |
729 // Our local free lists. | 730 // Our local free lists. |
730 FreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize]; | 731 FreeList _indexedFreeList[CompactibleFreeListSpace::IndexSetSize]; |
731 | 732 |
732 // Initialized from a command-line arg. | 733 // Initialized from a command-line arg. |
733 size_t _blocks_to_claim; | 734 |
734 | 735 // Allocation statistics in support of dynamic adjustment of |
735 #if CFLS_LAB_REFILL_STATS | 736 // #blocks to claim per get_from_global_pool() call below. |
736 // Some statistics. | 737 static AdaptiveWeightedAverage |
737 int _refills; | 738 _blocks_to_claim [CompactibleFreeListSpace::IndexSetSize]; |
738 int _blocksTaken; | 739 static size_t _global_num_blocks [CompactibleFreeListSpace::IndexSetSize]; |
739 static int _tot_refills; | 740 static int _global_num_workers[CompactibleFreeListSpace::IndexSetSize]; |
740 static int _tot_blocksTaken; | 741 size_t _num_blocks [CompactibleFreeListSpace::IndexSetSize]; |
741 static int _next_threshold; | 742 |
742 #endif | 743 // Internal work method |
744 void get_from_global_pool(size_t word_sz, FreeList* fl); | |
743 | 745 |
744 public: | 746 public: |
745 CFLS_LAB(CompactibleFreeListSpace* cfls); | 747 CFLS_LAB(CompactibleFreeListSpace* cfls); |
746 | 748 |
747 // Allocate and return a block of the given size, or else return NULL. | 749 // Allocate and return a block of the given size, or else return NULL. |
748 HeapWord* alloc(size_t word_sz); | 750 HeapWord* alloc(size_t word_sz); |
749 | 751 |
750 // Return any unused portions of the buffer to the global pool. | 752 // Return any unused portions of the buffer to the global pool. |
751 void retire(); | 753 void retire(int tid); |
754 | |
755 // Dynamic OldPLABSize sizing | |
756 static void compute_desired_plab_size(); | |
757 // When the settings are modified from default static initialization | |
758 static void modify_initialization(size_t n, unsigned wt); | |
752 }; | 759 }; |
753 | 760 |
754 size_t PromotionInfo::refillSize() const { | 761 size_t PromotionInfo::refillSize() const { |
755 const size_t CMSSpoolBlockSize = 256; | 762 const size_t CMSSpoolBlockSize = 256; |
756 const size_t sz = heap_word_size(sizeof(SpoolBlock) + sizeof(markOop) | 763 const size_t sz = heap_word_size(sizeof(SpoolBlock) + sizeof(markOop) |