< prev index next >

src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp

Print this page




 161  * not catching up. To bootstrap this feedback cycle, we need to start with some initial budget
 162  * for applications to allocate at.
 163  */
 164 
 165 void ShenandoahPacer::setup_for_idle() {
 166   assert(ShenandoahPacing, "Only be here when pacing is enabled");
 167 
 168   size_t initial = _heap->max_capacity() / 100 * ShenandoahPacingIdleSlack;
 169   double tax = 1;
 170 
 171   restart_with(initial, tax);
 172 
 173   log_info(gc, ergo)("Pacer for Idle. Initial: " SIZE_FORMAT "%s, Alloc Tax Rate: %.1fx",
 174                      byte_size_in_proper_unit(initial), proper_unit_for_byte_size(initial),
 175                      tax);
 176 }
 177 
 178 size_t ShenandoahPacer::update_and_get_progress_history() {
 179   if (_progress == -1) {
 180     // First initialization, report some prior
 181     Atomic::store((intptr_t)PACING_PROGRESS_ZERO, &_progress);
 182     return (size_t) (_heap->max_capacity() * 0.1);
 183   } else {
 184     // Record history, and reply historical data
 185     _progress_history->add(_progress);
 186     Atomic::store((intptr_t)PACING_PROGRESS_ZERO, &_progress);
 187     return (size_t) (_progress_history->avg() * HeapWordSize);
 188   }
 189 }
 190 
 191 void ShenandoahPacer::restart_with(size_t non_taxable_bytes, double tax_rate) {
 192   size_t initial = (size_t)(non_taxable_bytes * tax_rate) >> LogHeapWordSize;
 193   STATIC_ASSERT(sizeof(size_t) <= sizeof(intptr_t));
 194   Atomic::xchg((intptr_t)initial, &_budget);
 195   Atomic::store(tax_rate, &_tax_rate);
 196   Atomic::inc(&_epoch);
 197 }
 198 
 199 bool ShenandoahPacer::claim_for_alloc(size_t words, bool force) {
 200   assert(ShenandoahPacing, "Only be here when pacing is enabled");
 201 
 202   intptr_t tax = MAX2<intptr_t>(1, words * Atomic::load(&_tax_rate));
 203 
 204   intptr_t cur = 0;
 205   intptr_t new_val = 0;
 206   do {
 207     cur = Atomic::load(&_budget);
 208     if (cur < tax && !force) {
 209       // Progress depleted, alas.
 210       return false;
 211     }
 212     new_val = cur - tax;
 213   } while (Atomic::cmpxchg(new_val, &_budget, cur) != cur);
 214   return true;
 215 }
 216 
 217 void ShenandoahPacer::unpace_for_alloc(intptr_t epoch, size_t words) {
 218   assert(ShenandoahPacing, "Only be here when pacing is enabled");
 219 
 220   if (_epoch != epoch) {
 221     // Stale ticket, no need to unpace.
 222     return;
 223   }
 224 
 225   intptr_t tax = MAX2<intptr_t>(1, words * Atomic::load(&_tax_rate));
 226   Atomic::add(tax, &_budget);
 227 }
 228 
 229 intptr_t ShenandoahPacer::epoch() {
 230   return Atomic::load(&_epoch);
 231 }
 232 
 233 void ShenandoahPacer::pace_for_alloc(size_t words) {
 234   assert(ShenandoahPacing, "Only be here when pacing is enabled");
 235 
 236   // Fast path: try to allocate right away
 237   if (claim_for_alloc(words, false)) {
 238     return;
 239   }
 240 
 241   // Threads that are attaching should not block at all: they are not
 242   // fully initialized yet. Calling sleep() on them would be awkward.
 243   // This is probably the path that allocates the thread oop itself.
 244   // Forcefully claim without waiting.
 245   if (JavaThread::current()->is_attaching_via_jni()) {
 246     claim_for_alloc(words, true);




 161  * not catching up. To bootstrap this feedback cycle, we need to start with some initial budget
 162  * for applications to allocate at.
 163  */
 164 
 165 void ShenandoahPacer::setup_for_idle() {
 166   assert(ShenandoahPacing, "Only be here when pacing is enabled");
 167 
 168   size_t initial = _heap->max_capacity() / 100 * ShenandoahPacingIdleSlack;
 169   double tax = 1;
 170 
 171   restart_with(initial, tax);
 172 
 173   log_info(gc, ergo)("Pacer for Idle. Initial: " SIZE_FORMAT "%s, Alloc Tax Rate: %.1fx",
 174                      byte_size_in_proper_unit(initial), proper_unit_for_byte_size(initial),
 175                      tax);
 176 }
 177 
 178 size_t ShenandoahPacer::update_and_get_progress_history() {
 179   if (_progress == -1) {
 180     // First initialization, report some prior
 181     Atomic::store(&_progress, (intptr_t)PACING_PROGRESS_ZERO);
 182     return (size_t) (_heap->max_capacity() * 0.1);
 183   } else {
 184     // Record history, and reply historical data
 185     _progress_history->add(_progress);
 186     Atomic::store(&_progress, (intptr_t)PACING_PROGRESS_ZERO);
 187     return (size_t) (_progress_history->avg() * HeapWordSize);
 188   }
 189 }
 190 
 191 void ShenandoahPacer::restart_with(size_t non_taxable_bytes, double tax_rate) {
 192   size_t initial = (size_t)(non_taxable_bytes * tax_rate) >> LogHeapWordSize;
 193   STATIC_ASSERT(sizeof(size_t) <= sizeof(intptr_t));
 194   Atomic::xchg(&_budget, (intptr_t)initial);
 195   Atomic::store(&_tax_rate, tax_rate);
 196   Atomic::inc(&_epoch);
 197 }
 198 
 199 bool ShenandoahPacer::claim_for_alloc(size_t words, bool force) {
 200   assert(ShenandoahPacing, "Only be here when pacing is enabled");
 201 
 202   intptr_t tax = MAX2<intptr_t>(1, words * Atomic::load(&_tax_rate));
 203 
 204   intptr_t cur = 0;
 205   intptr_t new_val = 0;
 206   do {
 207     cur = Atomic::load(&_budget);
 208     if (cur < tax && !force) {
 209       // Progress depleted, alas.
 210       return false;
 211     }
 212     new_val = cur - tax;
 213   } while (Atomic::cmpxchg(&_budget, cur, new_val) != cur);
 214   return true;
 215 }
 216 
 217 void ShenandoahPacer::unpace_for_alloc(intptr_t epoch, size_t words) {
 218   assert(ShenandoahPacing, "Only be here when pacing is enabled");
 219 
 220   if (_epoch != epoch) {
 221     // Stale ticket, no need to unpace.
 222     return;
 223   }
 224 
 225   intptr_t tax = MAX2<intptr_t>(1, words * Atomic::load(&_tax_rate));
 226   Atomic::add(&_budget, tax);
 227 }
 228 
 229 intptr_t ShenandoahPacer::epoch() {
 230   return Atomic::load(&_epoch);
 231 }
 232 
 233 void ShenandoahPacer::pace_for_alloc(size_t words) {
 234   assert(ShenandoahPacing, "Only be here when pacing is enabled");
 235 
 236   // Fast path: try to allocate right away
 237   if (claim_for_alloc(words, false)) {
 238     return;
 239   }
 240 
 241   // Threads that are attaching should not block at all: they are not
 242   // fully initialized yet. Calling sleep() on them would be awkward.
 243   // This is probably the path that allocates the thread oop itself.
 244   // Forcefully claim without waiting.
 245   if (JavaThread::current()->is_attaching_via_jni()) {
 246     claim_for_alloc(words, true);


< prev index next >