6783381: NUMA allocator: don't pretouch eden space with UseNUMA

Tue, 27 Jan 2009 18:13:59 -0800

author
iveresov
date
Tue, 27 Jan 2009 18:13:59 -0800
changeset 970
4e400c36026f
parent 969
5cfd8d19e546
child 971
5b39c489c39d

6783381: NUMA allocator: don't pretouch eden space with UseNUMA
Summary: Moved pretouching to MutableSpace. Also MutableSpace now turns on page interleaving for the region it covers.
Reviewed-by: jmasa, jcoomes

src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/shared/mutableSpace.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/shared/mutableSpace.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp	Mon Jan 26 12:47:21 2009 -0800
     1.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psOldGen.cpp	Tue Jan 27 18:13:59 2009 -0800
     1.3 @@ -116,7 +116,7 @@
     1.4    // ObjectSpace stuff
     1.5    //
     1.6  
     1.7 -  _object_space = new MutableSpace();
     1.8 +  _object_space = new MutableSpace(virtual_space()->alignment());
     1.9  
    1.10    if (_object_space == NULL)
    1.11      vm_exit_during_initialization("Could not allocate an old gen space");
    1.12 @@ -385,10 +385,10 @@
    1.13    start_array()->set_covered_region(new_memregion);
    1.14    Universe::heap()->barrier_set()->resize_covered_region(new_memregion);
    1.15  
    1.16 -  HeapWord* const virtual_space_high = (HeapWord*) virtual_space()->high();
    1.17 -
    1.18    // ALWAYS do this last!!
    1.19 -  object_space()->set_end(virtual_space_high);
    1.20 +  object_space()->initialize(new_memregion,
    1.21 +                             SpaceDecorator::DontClear,
    1.22 +                             SpaceDecorator::DontMangle);
    1.23  
    1.24    assert(new_word_size == heap_word_size(object_space()->capacity_in_bytes()),
    1.25      "Sanity");
     2.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp	Mon Jan 26 12:47:21 2009 -0800
     2.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.cpp	Tue Jan 27 18:13:59 2009 -0800
     2.3 @@ -78,7 +78,7 @@
     2.4    _special = false;
     2.5  }
     2.6  
     2.7 -bool PSVirtualSpace::expand_by(size_t bytes, bool pre_touch) {
     2.8 +bool PSVirtualSpace::expand_by(size_t bytes) {
     2.9    assert(is_aligned(bytes), "arg not aligned");
    2.10    DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
    2.11  
    2.12 @@ -92,15 +92,6 @@
    2.13      _committed_high_addr += bytes;
    2.14    }
    2.15  
    2.16 -  if (pre_touch || AlwaysPreTouch) {
    2.17 -    for (char* curr = base_addr;
    2.18 -         curr < _committed_high_addr;
    2.19 -         curr += os::vm_page_size()) {
    2.20 -      char tmp = *curr;
    2.21 -      *curr = 0;
    2.22 -    }
    2.23 -  }
    2.24 -
    2.25    return result;
    2.26  }
    2.27  
    2.28 @@ -255,7 +246,7 @@
    2.29    DEBUG_ONLY(verify());
    2.30  }
    2.31  
    2.32 -bool PSVirtualSpaceHighToLow::expand_by(size_t bytes, bool pre_touch) {
    2.33 +bool PSVirtualSpaceHighToLow::expand_by(size_t bytes) {
    2.34    assert(is_aligned(bytes), "arg not aligned");
    2.35    DEBUG_ONLY(PSVirtualSpaceVerifier this_verifier(this));
    2.36  
    2.37 @@ -269,15 +260,6 @@
    2.38      _committed_low_addr -= bytes;
    2.39    }
    2.40  
    2.41 -  if (pre_touch || AlwaysPreTouch) {
    2.42 -    for (char* curr = base_addr;
    2.43 -         curr < _committed_high_addr;
    2.44 -         curr += os::vm_page_size()) {
    2.45 -      char tmp = *curr;
    2.46 -      *curr = 0;
    2.47 -    }
    2.48 -  }
    2.49 -
    2.50    return result;
    2.51  }
    2.52  
     3.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp	Mon Jan 26 12:47:21 2009 -0800
     3.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp	Tue Jan 27 18:13:59 2009 -0800
     3.3 @@ -80,7 +80,7 @@
     3.4    inline  void   set_reserved(char* low_addr, char* high_addr, bool special);
     3.5    inline  void   set_reserved(ReservedSpace rs);
     3.6    inline  void   set_committed(char* low_addr, char* high_addr);
     3.7 -  virtual bool   expand_by(size_t bytes, bool pre_touch = false);
     3.8 +  virtual bool   expand_by(size_t bytes);
     3.9    virtual bool   shrink_by(size_t bytes);
    3.10    virtual size_t expand_into(PSVirtualSpace* space, size_t bytes);
    3.11    void           release();
    3.12 @@ -127,7 +127,7 @@
    3.13    PSVirtualSpaceHighToLow(ReservedSpace rs, size_t alignment);
    3.14    PSVirtualSpaceHighToLow(ReservedSpace rs);
    3.15  
    3.16 -  virtual bool   expand_by(size_t bytes, bool pre_touch = false);
    3.17 +  virtual bool   expand_by(size_t bytes);
    3.18    virtual bool   shrink_by(size_t bytes);
    3.19    virtual size_t expand_into(PSVirtualSpace* space, size_t bytes);
    3.20  
     4.1 --- a/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp	Mon Jan 26 12:47:21 2009 -0800
     4.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.cpp	Tue Jan 27 18:13:59 2009 -0800
     4.3 @@ -64,12 +64,12 @@
     4.4    }
     4.5  
     4.6    if (UseNUMA) {
     4.7 -    _eden_space = new MutableNUMASpace();
     4.8 +    _eden_space = new MutableNUMASpace(virtual_space()->alignment());
     4.9    } else {
    4.10 -    _eden_space = new MutableSpace();
    4.11 +    _eden_space = new MutableSpace(virtual_space()->alignment());
    4.12    }
    4.13 -  _from_space = new MutableSpace();
    4.14 -  _to_space   = new MutableSpace();
    4.15 +  _from_space = new MutableSpace(virtual_space()->alignment());
    4.16 +  _to_space   = new MutableSpace(virtual_space()->alignment());
    4.17  
    4.18    if (_eden_space == NULL || _from_space == NULL || _to_space == NULL) {
    4.19      vm_exit_during_initialization("Could not allocate a young gen space");
     5.1 --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Mon Jan 26 12:47:21 2009 -0800
     5.2 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp	Tue Jan 27 18:13:59 2009 -0800
     5.3 @@ -27,7 +27,7 @@
     5.4  # include "incls/_mutableNUMASpace.cpp.incl"
     5.5  
     5.6  
     5.7 -MutableNUMASpace::MutableNUMASpace() {
     5.8 +MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment) {
     5.9    _lgrp_spaces = new (ResourceObj::C_HEAP) GrowableArray<LGRPSpace*>(0, true);
    5.10    _page_size = os::vm_page_size();
    5.11    _adaptation_cycles = 0;
    5.12 @@ -221,7 +221,7 @@
    5.13          }
    5.14        }
    5.15        if (!found) {
    5.16 -        lgrp_spaces()->append(new LGRPSpace(lgrp_ids[i]));
    5.17 +        lgrp_spaces()->append(new LGRPSpace(lgrp_ids[i], alignment()));
    5.18        }
    5.19      }
    5.20  
    5.21 @@ -443,10 +443,10 @@
    5.22    // Is there bottom?
    5.23    if (new_region.start() < intersection.start()) { // Yes
    5.24      // Try to coalesce small pages into a large one.
    5.25 -    if (UseLargePages && page_size() >= os::large_page_size()) {
    5.26 -      HeapWord* p = (HeapWord*)round_to((intptr_t) intersection.start(), os::large_page_size());
    5.27 +    if (UseLargePages && page_size() >= alignment()) {
    5.28 +      HeapWord* p = (HeapWord*)round_to((intptr_t) intersection.start(), alignment());
    5.29        if (new_region.contains(p)
    5.30 -          && pointer_delta(p, new_region.start(), sizeof(char)) >= os::large_page_size()) {
    5.31 +          && pointer_delta(p, new_region.start(), sizeof(char)) >= alignment()) {
    5.32          if (intersection.contains(p)) {
    5.33            intersection = MemRegion(p, intersection.end());
    5.34          } else {
    5.35 @@ -462,10 +462,10 @@
    5.36    // Is there top?
    5.37    if (intersection.end() < new_region.end()) { // Yes
    5.38      // Try to coalesce small pages into a large one.
    5.39 -    if (UseLargePages && page_size() >= os::large_page_size()) {
    5.40 -      HeapWord* p = (HeapWord*)round_down((intptr_t) intersection.end(), os::large_page_size());
    5.41 +    if (UseLargePages && page_size() >= alignment()) {
    5.42 +      HeapWord* p = (HeapWord*)round_down((intptr_t) intersection.end(), alignment());
    5.43        if (new_region.contains(p)
    5.44 -          && pointer_delta(new_region.end(), p, sizeof(char)) >= os::large_page_size()) {
    5.45 +          && pointer_delta(new_region.end(), p, sizeof(char)) >= alignment()) {
    5.46          if (intersection.contains(p)) {
    5.47            intersection = MemRegion(intersection.start(), p);
    5.48          } else {
    5.49 @@ -504,12 +504,12 @@
    5.50              // That's the only case we have to make an additional bias_region() call.
    5.51              HeapWord* start = invalid_region->start();
    5.52              HeapWord* end = invalid_region->end();
    5.53 -            if (UseLargePages && page_size() >= os::large_page_size()) {
    5.54 -              HeapWord *p = (HeapWord*)round_down((intptr_t) start, os::large_page_size());
    5.55 +            if (UseLargePages && page_size() >= alignment()) {
    5.56 +              HeapWord *p = (HeapWord*)round_down((intptr_t) start, alignment());
    5.57                if (new_region.contains(p)) {
    5.58                  start = p;
    5.59                }
    5.60 -              p = (HeapWord*)round_to((intptr_t) end, os::large_page_size());
    5.61 +              p = (HeapWord*)round_to((intptr_t) end, alignment());
    5.62                if (new_region.contains(end)) {
    5.63                  end = p;
    5.64                }
    5.65 @@ -526,7 +526,8 @@
    5.66  
    5.67  void MutableNUMASpace::initialize(MemRegion mr,
    5.68                                    bool clear_space,
    5.69 -                                  bool mangle_space) {
    5.70 +                                  bool mangle_space,
    5.71 +                                  bool setup_pages) {
    5.72    assert(clear_space, "Reallocation will destory data!");
    5.73    assert(lgrp_spaces()->length() > 0, "There should be at least one space");
    5.74  
    5.75 @@ -538,7 +539,7 @@
    5.76  
    5.77    // Compute chunk sizes
    5.78    size_t prev_page_size = page_size();
    5.79 -  set_page_size(UseLargePages ? os::large_page_size() : os::vm_page_size());
    5.80 +  set_page_size(UseLargePages ? alignment() : os::vm_page_size());
    5.81    HeapWord* rounded_bottom = (HeapWord*)round_to((intptr_t) bottom(), page_size());
    5.82    HeapWord* rounded_end = (HeapWord*)round_down((intptr_t) end(), page_size());
    5.83    size_t base_space_size_pages = pointer_delta(rounded_end, rounded_bottom, sizeof(char)) / page_size();
    5.84 @@ -666,7 +667,7 @@
    5.85      }
    5.86  
    5.87      // Clear space (set top = bottom) but never mangle.
    5.88 -    s->initialize(new_region, SpaceDecorator::Clear, SpaceDecorator::DontMangle);
    5.89 +    s->initialize(new_region, SpaceDecorator::Clear, SpaceDecorator::DontMangle, MutableSpace::DontSetupPages);
    5.90  
    5.91      set_adaptation_cycles(samples_count());
    5.92    }
     6.1 --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp	Mon Jan 26 12:47:21 2009 -0800
     6.2 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp	Tue Jan 27 18:13:59 2009 -0800
     6.3 @@ -82,8 +82,8 @@
     6.4      char* last_page_scanned()            { return _last_page_scanned; }
     6.5      void set_last_page_scanned(char* p)  { _last_page_scanned = p;    }
     6.6     public:
     6.7 -    LGRPSpace(int l) : _lgrp_id(l), _last_page_scanned(NULL), _allocation_failed(false) {
     6.8 -      _space = new MutableSpace();
     6.9 +    LGRPSpace(int l, size_t alignment) : _lgrp_id(l), _last_page_scanned(NULL), _allocation_failed(false) {
    6.10 +      _space = new MutableSpace(alignment);
    6.11        _alloc_rate = new AdaptiveWeightedAverage(NUMAChunkResizeWeight);
    6.12      }
    6.13      ~LGRPSpace() {
    6.14 @@ -183,10 +183,10 @@
    6.15  
    6.16   public:
    6.17    GrowableArray<LGRPSpace*>* lgrp_spaces() const     { return _lgrp_spaces;       }
    6.18 -  MutableNUMASpace();
    6.19 +  MutableNUMASpace(size_t alignment);
    6.20    virtual ~MutableNUMASpace();
    6.21    // Space initialization.
    6.22 -  virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space);
    6.23 +  virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space, bool setup_pages = SetupPages);
    6.24    // Update space layout if necessary. Do all adaptive resizing job.
    6.25    virtual void update();
    6.26    // Update allocation rate averages.
     7.1 --- a/src/share/vm/gc_implementation/shared/mutableSpace.cpp	Mon Jan 26 12:47:21 2009 -0800
     7.2 +++ b/src/share/vm/gc_implementation/shared/mutableSpace.cpp	Tue Jan 27 18:13:59 2009 -0800
     7.3 @@ -25,7 +25,10 @@
     7.4  # include "incls/_precompiled.incl"
     7.5  # include "incls/_mutableSpace.cpp.incl"
     7.6  
     7.7 -MutableSpace::MutableSpace(): ImmutableSpace(), _top(NULL) {
     7.8 +MutableSpace::MutableSpace(size_t alignment): ImmutableSpace(), _top(NULL), _alignment(alignment) {
     7.9 +  assert(MutableSpace::alignment() >= 0 &&
    7.10 +         MutableSpace::alignment() % os::vm_page_size() == 0,
    7.11 +         "Space should be aligned");
    7.12    _mangler = new MutableSpaceMangler(this);
    7.13  }
    7.14  
    7.15 @@ -33,16 +36,88 @@
    7.16    delete _mangler;
    7.17  }
    7.18  
    7.19 +void MutableSpace::numa_setup_pages(MemRegion mr, bool clear_space) {
    7.20 +  if (!mr.is_empty()) {
    7.21 +    size_t page_size = UseLargePages ? alignment() : os::vm_page_size();
    7.22 +    HeapWord *start = (HeapWord*)round_to((intptr_t) mr.start(), page_size);
    7.23 +    HeapWord *end =  (HeapWord*)round_down((intptr_t) mr.end(), page_size);
    7.24 +    if (end > start) {
    7.25 +      size_t size = pointer_delta(end, start, sizeof(char));
    7.26 +      if (clear_space) {
    7.27 +        // Prefer page reallocation to migration.
    7.28 +        os::free_memory((char*)start, size);
    7.29 +      }
    7.30 +      os::numa_make_global((char*)start, size);
    7.31 +    }
    7.32 +  }
    7.33 +}
    7.34 +
    7.35 +void MutableSpace::pretouch_pages(MemRegion mr) {
    7.36 +  for (volatile char *p = (char*)mr.start(); p < (char*)mr.end(); p += os::vm_page_size()) {
    7.37 +    char t = *p; *p = t;
    7.38 +  }
    7.39 +}
    7.40 +
    7.41  void MutableSpace::initialize(MemRegion mr,
    7.42                                bool clear_space,
    7.43 -                              bool mangle_space) {
    7.44 -  HeapWord* bottom = mr.start();
    7.45 -  HeapWord* end    = mr.end();
    7.46 +                              bool mangle_space,
    7.47 +                              bool setup_pages) {
    7.48  
    7.49 -  assert(Universe::on_page_boundary(bottom) && Universe::on_page_boundary(end),
    7.50 +  assert(Universe::on_page_boundary(mr.start()) && Universe::on_page_boundary(mr.end()),
    7.51           "invalid space boundaries");
    7.52 -  set_bottom(bottom);
    7.53 -  set_end(end);
    7.54 +
    7.55 +  if (setup_pages && (UseNUMA || AlwaysPreTouch)) {
    7.56 +    // The space may move left and right or expand/shrink.
    7.57 +    // We'd like to enforce the desired page placement.
    7.58 +    MemRegion head, tail;
    7.59 +    if (last_setup_region().is_empty()) {
    7.60 +      // If it's the first initialization don't limit the amount of work.
    7.61 +      head = mr;
    7.62 +      tail = MemRegion(mr.end(), mr.end());
    7.63 +    } else {
    7.64 +      // Is there an intersection with the address space?
    7.65 +      MemRegion intersection = last_setup_region().intersection(mr);
    7.66 +      if (intersection.is_empty()) {
    7.67 +        intersection = MemRegion(mr.end(), mr.end());
    7.68 +      }
    7.69 +      // All the sizes below are in words.
    7.70 +      size_t head_size = 0, tail_size = 0;
    7.71 +      if (mr.start() <= intersection.start()) {
    7.72 +        head_size = pointer_delta(intersection.start(), mr.start());
    7.73 +      }
    7.74 +      if(intersection.end() <= mr.end()) {
    7.75 +        tail_size = pointer_delta(mr.end(), intersection.end());
    7.76 +      }
    7.77 +      // Limit the amount of page manipulation if necessary.
    7.78 +      if (NUMASpaceResizeRate > 0 && !AlwaysPreTouch) {
    7.79 +        const size_t change_size = head_size + tail_size;
    7.80 +        const float setup_rate_words = NUMASpaceResizeRate >> LogBytesPerWord;
    7.81 +        head_size = MIN2((size_t)(setup_rate_words * head_size / change_size),
    7.82 +                         head_size);
    7.83 +        tail_size = MIN2((size_t)(setup_rate_words * tail_size / change_size),
    7.84 +                         tail_size);
    7.85 +      }
    7.86 +      head = MemRegion(intersection.start() - head_size, intersection.start());
    7.87 +      tail = MemRegion(intersection.end(), intersection.end() + tail_size);
    7.88 +    }
    7.89 +    assert(mr.contains(head) && mr.contains(tail), "Sanity");
    7.90 +
    7.91 +    if (UseNUMA) {
    7.92 +      numa_setup_pages(head, clear_space);
    7.93 +      numa_setup_pages(tail, clear_space);
    7.94 +    }
    7.95 +
    7.96 +    if (AlwaysPreTouch) {
    7.97 +      pretouch_pages(head);
    7.98 +      pretouch_pages(tail);
    7.99 +    }
   7.100 +
   7.101 +    // Remember where we stopped so that we can continue later.
   7.102 +    set_last_setup_region(MemRegion(head.start(), tail.end()));
   7.103 +  }
   7.104 +
   7.105 +  set_bottom(mr.start());
   7.106 +  set_end(mr.end());
   7.107  
   7.108    if (clear_space) {
   7.109      clear(mangle_space);
     8.1 --- a/src/share/vm/gc_implementation/shared/mutableSpace.hpp	Mon Jan 26 12:47:21 2009 -0800
     8.2 +++ b/src/share/vm/gc_implementation/shared/mutableSpace.hpp	Tue Jan 27 18:13:59 2009 -0800
     8.3 @@ -25,7 +25,10 @@
     8.4  // A MutableSpace is a subtype of ImmutableSpace that supports the
     8.5  // concept of allocation. This includes the concepts that a space may
     8.6  // be only partially full, and the querry methods that go with such
     8.7 -// an assumption.
     8.8 +// an assumption. MutableSpace is also responsible for minimizing the
     8.9 +// page allocation time by having the memory pretouched (with
    8.10 +// AlwaysPretouch) and for optimizing page placement on NUMA systems
    8.11 +// by make the underlying region interleaved (with UseNUMA).
    8.12  //
    8.13  // Invariant: (ImmutableSpace +) bottom() <= top() <= end()
    8.14  // top() is inclusive and end() is exclusive.
    8.15 @@ -37,15 +40,23 @@
    8.16  
    8.17    // Helper for mangling unused space in debug builds
    8.18    MutableSpaceMangler* _mangler;
    8.19 -
    8.20 +  // The last region which page had been setup to be interleaved.
    8.21 +  MemRegion _last_setup_region;
    8.22 +  size_t _alignment;
    8.23   protected:
    8.24    HeapWord* _top;
    8.25  
    8.26    MutableSpaceMangler* mangler() { return _mangler; }
    8.27  
    8.28 +  void numa_setup_pages(MemRegion mr, bool clear_space);
    8.29 +  void pretouch_pages(MemRegion mr);
    8.30 +
    8.31 +  void set_last_setup_region(MemRegion mr) { _last_setup_region = mr;   }
    8.32 +  MemRegion last_setup_region() const      { return _last_setup_region; }
    8.33 +
    8.34   public:
    8.35    virtual ~MutableSpace();
    8.36 -  MutableSpace();
    8.37 +  MutableSpace(size_t page_size);
    8.38  
    8.39    // Accessors
    8.40    HeapWord* top() const                    { return _top;    }
    8.41 @@ -57,13 +68,20 @@
    8.42    virtual void set_bottom(HeapWord* value) { _bottom = value; }
    8.43    virtual void set_end(HeapWord* value)    { _end = value; }
    8.44  
    8.45 +  size_t alignment()                       { return _alignment; }
    8.46 +
    8.47    // Returns a subregion containing all objects in this space.
    8.48    MemRegion used_region() { return MemRegion(bottom(), top()); }
    8.49  
    8.50 +  static const bool SetupPages = true;
    8.51 +  static const bool DontSetupPages = false;
    8.52 +
    8.53    // Initialization
    8.54    virtual void initialize(MemRegion mr,
    8.55                            bool clear_space,
    8.56 -                          bool mangle_space);
    8.57 +                          bool mangle_space,
    8.58 +                          bool setup_pages = SetupPages);
    8.59 +
    8.60    virtual void clear(bool mangle_space);
    8.61    // Does the usual initialization but optionally resets top to bottom.
    8.62  #if 0  // MANGLE_SPACE

mercurial