src/hotspot/share/gc/epsilon/epsilonHeap.cpp
branchepsilon-gc-branch
changeset 56581 d6ace215b52c
parent 56580 b6c934c3fda2
child 56582 c75a617df2f8
equal deleted inserted replaced
56580:b6c934c3fda2 56581:d6ace215b52c
    29 #include "memory/allocation.inline.hpp"
    29 #include "memory/allocation.inline.hpp"
    30 #include "memory/resourceArea.hpp"
    30 #include "memory/resourceArea.hpp"
    31 
    31 
    32 jint EpsilonHeap::initialize() {
    32 jint EpsilonHeap::initialize() {
    33   size_t init_byte_size = _policy->initial_heap_byte_size();
    33   size_t init_byte_size = _policy->initial_heap_byte_size();
    34   size_t max_byte_size = _policy->max_heap_byte_size();
    34   size_t max_byte_size  = _policy->max_heap_byte_size();
    35   size_t align = _policy->heap_alignment();
    35 
    36 
    36   // Initialize backing storage
    37   ReservedSpace heap_rs = Universe::reserve_heap(max_byte_size,  align);
    37   ReservedSpace heap_rs = Universe::reserve_heap(max_byte_size, _policy->heap_alignment());
    38   _virtual_space.initialize(heap_rs, init_byte_size);
    38   _virtual_space.initialize(heap_rs, init_byte_size);
    39 
    39 
    40   MemRegion committed_region((HeapWord*)_virtual_space.low(), (HeapWord*)_virtual_space.high());
    40   MemRegion committed_region((HeapWord*)_virtual_space.low(),          (HeapWord*)_virtual_space.high());
    41   MemRegion reserved_region((HeapWord*)_virtual_space.low_boundary(), (HeapWord*)_virtual_space.high_boundary());
    41   MemRegion  reserved_region((HeapWord*)_virtual_space.low_boundary(), (HeapWord*)_virtual_space.high_boundary());
    42 
    42 
    43   initialize_reserved_region(reserved_region.start(), reserved_region.end());
    43   initialize_reserved_region(reserved_region.start(), reserved_region.end());
    44 
    44 
    45   _space = new ContiguousSpace();
    45   _space = new ContiguousSpace();
    46   _space->initialize(committed_region, true, true);
    46   _space->initialize(committed_region, /* clear_space = */ true, /* mangle_space */ = true);
    47 
    47 
    48   BarrierSet::set_barrier_set(new EpsilonBarrierSet());
    48   // Precompute hot fields
    49 
       
    50   _max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), EpsilonMaxTLABSize / HeapWordSize);
    49   _max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), EpsilonMaxTLABSize / HeapWordSize);
    51 
    50   _step_counter_update = MIN2<size_t>(max_byte_size / 16, EpsilonUpdateCountersStep);
       
    51   _step_heap_print = (EpsilonPrintHeapStep == 0) ? SIZE_MAX : (max_byte_size / EpsilonPrintHeapStep);
       
    52   _decay_time_ns = (int64_t) EpsilonTLABDecayTime * 1000 * 1000;
       
    53 
       
    54   // Enable monitoring
    52   _monitoring_support = new EpsilonMonitoringSupport(this);
    55   _monitoring_support = new EpsilonMonitoringSupport(this);
    53   _last_counter_update = 0;
    56   _last_counter_update = 0;
    54   _last_heap_print = 0;
    57   _last_heap_print = 0;
    55 
    58 
    56   _step_counter_update = MIN2<size_t>(max_byte_size / 16, EpsilonUpdateCountersStep);
    59   // Install barrier set
    57   _step_heap_print = (EpsilonPrintHeapStep == 0) ? SIZE_MAX : (max_byte_size / EpsilonPrintHeapStep);
    60   BarrierSet::set_barrier_set(new EpsilonBarrierSet());
    58 
    61 
    59   _decay_time_ns = (int64_t) EpsilonTLABDecayTime * 1000 * 1000;
    62   // All done, print out the configuration
    60 
       
    61   if (init_byte_size != max_byte_size) {
    63   if (init_byte_size != max_byte_size) {
    62     log_info(gc)("Resizeable heap; starting at " SIZE_FORMAT "M, max: " SIZE_FORMAT "M, step: " SIZE_FORMAT "M",
    64     log_info(gc)("Resizeable heap; starting at " SIZE_FORMAT "M, max: " SIZE_FORMAT "M, step: " SIZE_FORMAT "M",
    63                  init_byte_size / M, max_byte_size / M, EpsilonMinHeapExpand / M);
    65                  init_byte_size / M, max_byte_size / M, EpsilonMinHeapExpand / M);
    64   } else {
    66   } else {
    65     log_info(gc)("Non-resizeable heap; start/max: " SIZE_FORMAT "M", init_byte_size / M);
    67     log_info(gc)("Non-resizeable heap; start/max: " SIZE_FORMAT "M", init_byte_size / M);
    66   }
    68   }
       
    69 
    67   if (UseTLAB) {
    70   if (UseTLAB) {
    68     log_info(gc)("Using TLAB allocation; max: " SIZE_FORMAT "K", _max_tlab_size * HeapWordSize / K);
    71     log_info(gc)("Using TLAB allocation; max: " SIZE_FORMAT "K", _max_tlab_size * HeapWordSize / K);
    69     if (EpsilonElasticTLAB) {
    72     if (EpsilonElasticTLAB) {
    70       log_info(gc)("Elastic TLABs enabled; elasticity: %.2fx", EpsilonTLABElasticity);
    73       log_info(gc)("Elastic TLABs enabled; elasticity: %.2fx", EpsilonTLABElasticity);
    71     }
    74     }
   127       // Enough space to expand in bulk:
   130       // Enough space to expand in bulk:
   128       bool expand = _virtual_space.expand_by(want_space);
   131       bool expand = _virtual_space.expand_by(want_space);
   129       assert(expand, "Should be able to expand");
   132       assert(expand, "Should be able to expand");
   130     } else if (size < space_left) {
   133     } else if (size < space_left) {
   131       // No space to expand in bulk, and this allocation is still possible,
   134       // No space to expand in bulk, and this allocation is still possible,
   132       // take all the space left:
   135       // take all the remaining space:
   133       bool expand = _virtual_space.expand_by(space_left);
   136       bool expand = _virtual_space.expand_by(space_left);
   134       assert(expand, "Should be able to expand");
   137       assert(expand, "Should be able to expand");
   135     } else {
   138     } else {
   136       // No space left:
   139       // No space left:
   137       return NULL;
   140       return NULL;
   139 
   142 
   140     _space->set_end((HeapWord *) _virtual_space.high());
   143     _space->set_end((HeapWord *) _virtual_space.high());
   141     res = _space->par_allocate(size);
   144     res = _space->par_allocate(size);
   142   }
   145   }
   143 
   146 
       
   147   // Allocation successful, update counters
   144   size_t used = _space->used();
   148   size_t used = _space->used();
   145   if (used - _last_counter_update >= _step_counter_update) {
   149   if (used - _last_counter_update >= _step_counter_update) {
   146     _last_counter_update = used;
   150     _last_counter_update = used;
   147     _monitoring_support->update_counters();
   151     _monitoring_support->update_counters();
   148   }
   152   }
   149 
   153 
       
   154   // ...and print the occupancy line, if needed
   150   if (used - _last_heap_print >= _step_heap_print) {
   155   if (used - _last_heap_print >= _step_heap_print) {
   151     log_info(gc)("Heap: " SIZE_FORMAT "M reserved, " SIZE_FORMAT "M committed, " SIZE_FORMAT "M used",
   156     log_info(gc)("Heap: " SIZE_FORMAT "M reserved, " SIZE_FORMAT "M committed, " SIZE_FORMAT "M used",
   152                  max_capacity() / M, capacity() / M, used / M);
   157                  max_capacity() / M, capacity() / M, used / M);
   153     _last_heap_print = used;
   158     _last_heap_print = used;
   154   }
   159   }
   169 
   174 
   170   if (EpsilonElasticTLAB) {
   175   if (EpsilonElasticTLAB) {
   171     ergo_tlab = EpsilonThreadLocalData::ergo_tlab_size(thread);
   176     ergo_tlab = EpsilonThreadLocalData::ergo_tlab_size(thread);
   172 
   177 
   173     if (EpsilonElasticTLABDecay) {
   178     if (EpsilonElasticTLABDecay) {
   174       int64_t last_alloc = EpsilonThreadLocalData::last_alloc_time(thread);
   179       int64_t last_time = EpsilonThreadLocalData::last_tlab_time(thread);
   175       time = (int64_t) os::javaTimeNanos();
   180       time = (int64_t) os::javaTimeNanos();
   176 
   181 
   177       assert(last_alloc <= time, "time should be monotonic");
   182       assert(last_time <= time, "time should be monotonic");
   178 
   183 
   179       // If the thread had not allocated recently, retract the ergonomic size.
   184       // If the thread had not allocated recently, retract the ergonomic size.
   180       // This conserves memory when the thread had initial burst of allocations,
   185       // This conserves memory when the thread had initial burst of allocations,
   181       // and then started allocating only sporadically.
   186       // and then started allocating only sporadically.
   182       if (last_alloc != 0 && (time - last_alloc > _decay_time_ns)) {
   187       if (last_time != 0 && (time - last_time > _decay_time_ns)) {
   183         ergo_tlab = 0;
   188         ergo_tlab = 0;
   184         EpsilonThreadLocalData::set_ergo_tlab_size(thread, 0);
   189         EpsilonThreadLocalData::set_ergo_tlab_size(thread, 0);
   185       }
   190       }
   186     }
   191     }
   187 
   192 
   191     if (!fits) {
   196     if (!fits) {
   192       size = (size_t) (ergo_tlab * EpsilonTLABElasticity);
   197       size = (size_t) (ergo_tlab * EpsilonTLABElasticity);
   193     }
   198     }
   194   }
   199   }
   195 
   200 
   196   // Honor boundaries
   201   // Always honor boundaries
   197   size = MAX2(min_size, MIN2(_max_tlab_size, size));
   202   size = MAX2(min_size, MIN2(_max_tlab_size, size));
   198 
   203 
   199   if (log_is_enabled(Trace, gc)) {
   204   if (log_is_enabled(Trace, gc)) {
   200     ResourceMark rm;
   205     ResourceMark rm;
   201     log_trace(gc)("TLAB size for \"%s\" (Requested: " SIZE_FORMAT "K, Min: " SIZE_FORMAT
   206     log_trace(gc)("TLAB size for \"%s\" (Requested: " SIZE_FORMAT "K, Min: " SIZE_FORMAT
   206                   _max_tlab_size * HeapWordSize / K,
   211                   _max_tlab_size * HeapWordSize / K,
   207                   ergo_tlab * HeapWordSize / K,
   212                   ergo_tlab * HeapWordSize / K,
   208                   size * HeapWordSize / K);
   213                   size * HeapWordSize / K);
   209   }
   214   }
   210 
   215 
       
   216   // All prepared, let's do it!
   211   HeapWord* res = allocate_work(size);
   217   HeapWord* res = allocate_work(size);
       
   218 
   212   if (res != NULL) {
   219   if (res != NULL) {
   213     // Allocation successful
   220     // Allocation successful
   214     *actual_size = size;
   221     *actual_size = size;
   215     if (EpsilonElasticTLABDecay) {
   222     if (EpsilonElasticTLABDecay) {
   216       EpsilonThreadLocalData::set_last_alloc_time(thread, time);
   223       EpsilonThreadLocalData::set_last_tlab_time(thread, time);
   217     }
   224     }
   218     if (EpsilonElasticTLAB && !fits) {
   225     if (EpsilonElasticTLAB && !fits) {
   219       // If we requested expansion, this is our new ergonomic TLAB size
   226       // If we requested expansion, this is our new ergonomic TLAB size
   220       EpsilonThreadLocalData::set_ergo_tlab_size(thread, size);
   227       EpsilonThreadLocalData::set_ergo_tlab_size(thread, size);
   221     }
   228     }