src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp

Print this page
rev 7147 : 8059758: Startup benchmark performance and footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zeroes out) virtual memory used for auxiliary data structures. This causes a footprint and performance regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: tbd


  52 class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper {
  53  private:
  54   size_t _pages_per_region;
  55 
  56  public:
  57   G1RegionsLargerThanCommitSizeMapper(ReservedSpace rs,
  58                                       size_t os_commit_granularity,
  59                                       size_t alloc_granularity,
  60                                       size_t commit_factor,
  61                                       MemoryType type) :
  62      G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type),
  63     _pages_per_region(alloc_granularity / (os_commit_granularity * commit_factor)) {
  64 
  65     guarantee(alloc_granularity >= os_commit_granularity, "allocation granularity smaller than commit granularity");
  66     _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false);
  67   }
  68 
  69   virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
  70     _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
  71     _commit_map.set_range(start_idx, start_idx + num_regions);
  72     fire_on_commit(start_idx, num_regions);
  73   }
  74 
  75   virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
  76     _storage.uncommit(start_idx * _pages_per_region, num_regions * _pages_per_region);
  77     _commit_map.clear_range(start_idx, start_idx + num_regions);
  78   }
  79 };
  80 
  81 // G1RegionToSpaceMapper implementation where the region granularity is smaller
  82 // than the commit granularity.
  83 // Basically, the contents of one OS page span several regions.
  84 class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper {
  85  private:
  86   class CommitRefcountArray : public G1BiasedMappedArray<uint> {
  87    protected:
  88      virtual uint default_value() const { return 0; }
  89   };
  90 
  91   size_t _regions_per_page;
  92 


  98 
  99  public:
 100   G1RegionsSmallerThanCommitSizeMapper(ReservedSpace rs,
 101                                        size_t os_commit_granularity,
 102                                        size_t alloc_granularity,
 103                                        size_t commit_factor,
 104                                        MemoryType type) :
 105      G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type),
 106     _regions_per_page((os_commit_granularity * commit_factor) / alloc_granularity), _refcounts() {
 107 
 108     guarantee((os_commit_granularity * commit_factor) >= alloc_granularity, "allocation granularity smaller than commit granularity");
 109     _refcounts.initialize((HeapWord*)rs.base(), (HeapWord*)(rs.base() + rs.size()), os_commit_granularity);
 110     _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false);
 111   }
 112 
 113   virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
 114     for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) {
 115       assert(!_commit_map.at(i), err_msg("Trying to commit storage at region "INTPTR_FORMAT" that is already committed", i));
 116       uintptr_t idx = region_idx_to_page_idx(i);
 117       uint old_refcount = _refcounts.get_by_index(idx);

 118       if (old_refcount == 0) {
 119         _storage.commit(idx, 1);

 120       }
 121       _refcounts.set_by_index(idx, old_refcount + 1);
 122       _commit_map.set_bit(i);
 123       fire_on_commit(i, 1);
 124     }
 125   }
 126 
 127   virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
 128     for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) {
 129       assert(_commit_map.at(i), err_msg("Trying to uncommit storage at region "INTPTR_FORMAT" that is not committed", i));
 130       uintptr_t idx = region_idx_to_page_idx(i);
 131       uint old_refcount = _refcounts.get_by_index(idx);
 132       assert(old_refcount > 0, "must be");
 133       if (old_refcount == 1) {
 134         _storage.uncommit(idx, 1);
 135       }
 136       _refcounts.set_by_index(idx, old_refcount - 1);
 137       _commit_map.clear_bit(i);
 138     }
 139   }
 140 };
 141 
 142 void G1RegionToSpaceMapper::fire_on_commit(uint start_idx, size_t num_regions) {
 143   if (_listener != NULL) {
 144     _listener->on_commit(start_idx, num_regions);
 145   }
 146 }
 147 
 148 G1RegionToSpaceMapper* G1RegionToSpaceMapper::create_mapper(ReservedSpace rs,
 149                                                             size_t os_commit_granularity,
 150                                                             size_t region_granularity,
 151                                                             size_t commit_factor,
 152                                                             MemoryType type) {
 153 
 154   if (region_granularity >= (os_commit_granularity * commit_factor)) {
 155     return new G1RegionsLargerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type);
 156   } else {
 157     return new G1RegionsSmallerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type);
 158   }
 159 }


  52 class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper {
  53  private:
  54   size_t _pages_per_region;
  55 
  56  public:
  57   G1RegionsLargerThanCommitSizeMapper(ReservedSpace rs,
  58                                       size_t os_commit_granularity,
  59                                       size_t alloc_granularity,
  60                                       size_t commit_factor,
  61                                       MemoryType type) :
  62      G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type),
  63     _pages_per_region(alloc_granularity / (os_commit_granularity * commit_factor)) {
  64 
  65     guarantee(alloc_granularity >= os_commit_granularity, "allocation granularity smaller than commit granularity");
  66     _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false);
  67   }
  68 
  69   virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
  70     _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
  71     _commit_map.set_range(start_idx, start_idx + num_regions);
  72     fire_on_commit(start_idx, num_regions, true);
  73   }
  74 
  75   virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
  76     _storage.uncommit(start_idx * _pages_per_region, num_regions * _pages_per_region);
  77     _commit_map.clear_range(start_idx, start_idx + num_regions);
  78   }
  79 };
  80 
  81 // G1RegionToSpaceMapper implementation where the region granularity is smaller
  82 // than the commit granularity.
  83 // Basically, the contents of one OS page span several regions.
  84 class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper {
  85  private:
  86   class CommitRefcountArray : public G1BiasedMappedArray<uint> {
  87    protected:
  88      virtual uint default_value() const { return 0; }
  89   };
  90 
  91   size_t _regions_per_page;
  92 


  98 
  99  public:
 100   G1RegionsSmallerThanCommitSizeMapper(ReservedSpace rs,
 101                                        size_t os_commit_granularity,
 102                                        size_t alloc_granularity,
 103                                        size_t commit_factor,
 104                                        MemoryType type) :
 105      G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type),
 106     _regions_per_page((os_commit_granularity * commit_factor) / alloc_granularity), _refcounts() {
 107 
 108     guarantee((os_commit_granularity * commit_factor) >= alloc_granularity, "allocation granularity smaller than commit granularity");
 109     _refcounts.initialize((HeapWord*)rs.base(), (HeapWord*)(rs.base() + rs.size()), os_commit_granularity);
 110     _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false);
 111   }
 112 
 113   virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
 114     for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) {
 115       assert(!_commit_map.at(i), err_msg("Trying to commit storage at region "INTPTR_FORMAT" that is already committed", i));
 116       uintptr_t idx = region_idx_to_page_idx(i);
 117       uint old_refcount = _refcounts.get_by_index(idx);
 118       bool zero_filled = false;
 119       if (old_refcount == 0) {
 120         _storage.commit(idx, 1);
 121         zero_filled = true;
 122       }
 123       _refcounts.set_by_index(idx, old_refcount + 1);
 124       _commit_map.set_bit(i);
 125       fire_on_commit(i, 1, zero_filled);
 126     }
 127   }
 128 
 129   virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
 130     for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) {
 131       assert(_commit_map.at(i), err_msg("Trying to uncommit storage at region "INTPTR_FORMAT" that is not committed", i));
 132       uintptr_t idx = region_idx_to_page_idx(i);
 133       uint old_refcount = _refcounts.get_by_index(idx);
 134       assert(old_refcount > 0, "must be");
 135       if (old_refcount == 1) {
 136         _storage.uncommit(idx, 1);
 137       }
 138       _refcounts.set_by_index(idx, old_refcount - 1);
 139       _commit_map.clear_bit(i);
 140     }
 141   }
 142 };
 143 
 144 void G1RegionToSpaceMapper::fire_on_commit(uint start_idx, size_t num_regions, bool zero_filled) {
 145   if (_listener != NULL) {
 146     _listener->on_commit(start_idx, num_regions, zero_filled);
 147   }
 148 }
 149 
 150 G1RegionToSpaceMapper* G1RegionToSpaceMapper::create_mapper(ReservedSpace rs,
 151                                                             size_t os_commit_granularity,
 152                                                             size_t region_granularity,
 153                                                             size_t commit_factor,
 154                                                             MemoryType type) {
 155 
 156   if (region_granularity >= (os_commit_granularity * commit_factor)) {
 157     return new G1RegionsLargerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type);
 158   } else {
 159     return new G1RegionsSmallerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type);
 160   }
 161 }