diff --git a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp index 5936c776a4782ee8f5040711fc32b4a21bf9d74c..315cfe1c63e7274773d32cdd7132b330a25c0b34 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp @@ -402,7 +402,7 @@ HeapWord* ParallelScavengeHeap::mem_allocate( return result; } if (!is_tlab && - size >= (young_gen()->eden_space()->capacity_in_words() / 2)) { + size >= (young_gen()->eden_space()->capacity_in_words(Thread::current()) / 2)) { result = old_gen()->allocate(size, is_tlab); if (result != NULL) { return result; diff --git a/src/share/vm/gc_implementation/shared/immutableSpace.hpp b/src/share/vm/gc_implementation/shared/immutableSpace.hpp index 3f28ec710e4f2b250c8ae5d39e4099887cf7f374..39166412d8b43667e95e0195753683ba63d1eee2 100644 --- a/src/share/vm/gc_implementation/shared/immutableSpace.hpp +++ b/src/share/vm/gc_implementation/shared/immutableSpace.hpp @@ -50,7 +50,8 @@ class ImmutableSpace: public CHeapObj { size_t capacity_in_bytes() const { return capacity_in_words() * HeapWordSize; } // Size computations. Sizes are in heapwords. - size_t capacity_in_words() const { return pointer_delta(end(), bottom()); } + size_t capacity_in_words() const { return pointer_delta(end(), bottom()); } + virtual size_t capacity_in_words(Thread*) const { return capacity_in_words(); } // Iteration. virtual void oop_iterate(OopClosure* cl); diff --git a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp index 344c6add09a02449025a90d3b090ec0a8e931010..4779daf69df3fc6a89c348bde352375da87f76b4 100644 --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp @@ -181,6 +181,25 @@ size_t MutableNUMASpace::unsafe_max_tlab_alloc(Thread *thr) const { return lgrp_spaces()->at(i)->space()->free_in_bytes(); } + +size_t MutableNUMASpace::capacity_in_words(Thread* thr) const { + guarantee(thr != NULL, "No thread"); + int lgrp_id = thr->lgrp_id(); + if (lgrp_id == -1) { + if (lgrp_spaces()->length() > 0) { + return capacity_in_words() / lgrp_spaces()->length(); + } else { + assert(false, "There should be at least one locality group"); + return 0; + } + } + int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); + if (i == -1) { + return 0; + } + return lgrp_spaces()->at(i)->space()->capacity_in_words(); +} + // Check if the NUMA topology has changed. Add and remove spaces if needed. // The update can be forced by setting the force parameter equal to true. bool MutableNUMASpace::update_layout(bool force) { @@ -722,7 +741,8 @@ HeapWord* MutableNUMASpace::allocate(size_t size) { i = os::random() % lgrp_spaces()->length(); } - MutableSpace *s = lgrp_spaces()->at(i)->space(); + LGRPSpace* ls = lgrp_spaces()->at(i); + MutableSpace *s = ls->space(); HeapWord *p = s->allocate(size); if (p != NULL) { @@ -743,6 +763,9 @@ HeapWord* MutableNUMASpace::allocate(size_t size) { *(int*)i = 0; } } + if (p == NULL) { + ls->set_allocation_failed(); + } return p; } @@ -761,7 +784,8 @@ HeapWord* MutableNUMASpace::cas_allocate(size_t size) { if (i == -1) { i = os::random() % lgrp_spaces()->length(); } - MutableSpace *s = lgrp_spaces()->at(i)->space(); + LGRPSpace *ls = lgrp_spaces()->at(i); + MutableSpace *s = ls->space(); HeapWord *p = s->cas_allocate(size); if (p != NULL) { size_t remainder = pointer_delta(s->end(), p + size); @@ -790,6 +814,9 @@ HeapWord* MutableNUMASpace::cas_allocate(size_t size) { *(int*)i = 0; } } + if (p == NULL) { + ls->set_allocation_failed(); + } return p; } diff --git a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp index e3d824481f41c1b600f7c8c0e3134649d75572f2..f7ca2462545e74e94435b78187d044528b4ac073 100644 --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp @@ -60,6 +60,7 @@ class MutableNUMASpace : public MutableSpace { MutableSpace* _space; MemRegion _invalid_region; AdaptiveWeightedAverage *_alloc_rate; + bool _allocation_failed; struct SpaceStats { size_t _local_space, _remote_space, _unbiased_space, _uncommited_space; @@ -81,7 +82,7 @@ class MutableNUMASpace : public MutableSpace { char* last_page_scanned() { return _last_page_scanned; } void set_last_page_scanned(char* p) { _last_page_scanned = p; } public: - LGRPSpace(int l) : _lgrp_id(l), _last_page_scanned(NULL) { + LGRPSpace(int l) : _lgrp_id(l), _last_page_scanned(NULL), _allocation_failed(false) { _space = new MutableSpace(); _alloc_rate = new AdaptiveWeightedAverage(NUMAChunkResizeWeight); } @@ -103,8 +104,21 @@ class MutableNUMASpace : public MutableSpace { return *(int*)lgrp_id_value == p->lgrp_id(); } + // Report a failed allocation. + void set_allocation_failed() { _allocation_failed = true; } + void sample() { - alloc_rate()->sample(space()->used_in_bytes()); + // If there was a failed allocation make allocation rate equal + // to the size of the whole chunk. This ensures the progress of + // the adaptation process. + size_t alloc_rate_sample; + if (_allocation_failed) { + alloc_rate_sample = space()->capacity_in_bytes(); + _allocation_failed = false; + } else { + alloc_rate_sample = space()->used_in_bytes(); + } + alloc_rate()->sample(alloc_rate_sample); } MemRegion invalid_region() const { return _invalid_region; } @@ -190,6 +204,9 @@ class MutableNUMASpace : public MutableSpace { virtual void ensure_parsability(); virtual size_t used_in_words() const; virtual size_t free_in_words() const; + + using MutableSpace::capacity_in_words; + virtual size_t capacity_in_words(Thread* thr) const; virtual size_t tlab_capacity(Thread* thr) const; virtual size_t unsafe_max_tlab_alloc(Thread* thr) const;