Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
| (...skipping 1201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1212 } | 1212 } |
| 1213 | 1213 |
| 1214 if (collector == MARK_COMPACTOR) { | 1214 if (collector == MARK_COMPACTOR) { |
| 1215 UpdateOldGenerationAllocationCounter(); | 1215 UpdateOldGenerationAllocationCounter(); |
| 1216 // Perform mark-sweep with optional compaction. | 1216 // Perform mark-sweep with optional compaction. |
| 1217 MarkCompact(); | 1217 MarkCompact(); |
| 1218 sweep_generation_++; | 1218 sweep_generation_++; |
| 1219 old_gen_exhausted_ = false; | 1219 old_gen_exhausted_ = false; |
| 1220 old_generation_size_configured_ = true; | 1220 old_generation_size_configured_ = true; |
| 1221 // This should be updated before PostGarbageCollectionProcessing, which can | 1221 // This should be updated before PostGarbageCollectionProcessing, which can |
| 1222 // cause another GC. | 1222 // cause another GC. Take into account the objects promoted during GC. |
| 1223 old_generation_allocation_counter_ += | |
| 1224 static_cast<size_t>(promoted_objects_size_); | |
| 1223 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); | 1225 old_generation_size_at_last_gc_ = PromotedSpaceSizeOfObjects(); |
| 1224 } else { | 1226 } else { |
| 1225 Scavenge(); | 1227 Scavenge(); |
| 1226 } | 1228 } |
| 1227 | 1229 |
| 1228 | 1230 |
| 1229 UpdateSurvivalStatistics(start_new_space_size); | 1231 UpdateSurvivalStatistics(start_new_space_size); |
| 1230 ConfigureInitialOldGenerationSize(); | 1232 ConfigureInitialOldGenerationSize(); |
| 1231 | 1233 |
| 1232 isolate_->counters()->objs_since_last_young()->Set(0); | 1234 isolate_->counters()->objs_since_last_young()->Set(0); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1254 | 1256 |
| 1255 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); | 1257 isolate_->eternal_handles()->PostGarbageCollectionProcessing(this); |
| 1256 | 1258 |
| 1257 // Update relocatables. | 1259 // Update relocatables. |
| 1258 Relocatable::PostGarbageCollectionProcessing(isolate_); | 1260 Relocatable::PostGarbageCollectionProcessing(isolate_); |
| 1259 | 1261 |
| 1260 if (collector == MARK_COMPACTOR) { | 1262 if (collector == MARK_COMPACTOR) { |
| 1261 // Register the amount of external allocated memory. | 1263 // Register the amount of external allocated memory. |
| 1262 amount_of_external_allocated_memory_at_last_global_gc_ = | 1264 amount_of_external_allocated_memory_at_last_global_gc_ = |
| 1263 amount_of_external_allocated_memory_; | 1265 amount_of_external_allocated_memory_; |
| 1264 SetOldGenerationAllocationLimit( | 1266 double gc_speed = tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond(); |
| 1265 PromotedSpaceSizeOfObjects(), | 1267 double mutator_speed = static_cast<double>( |
| 1266 tracer()->CurrentAllocationThroughputInBytesPerMillisecond()); | 1268 tracer() |
| 1269 ->CurrentOldGenerationAllocationThroughputInBytesPerMillisecond()); | |
| 1270 intptr_t old_gen_size = PromotedSpaceSizeOfObjects(); | |
| 1271 SetOldGenerationAllocationLimit(old_gen_size, gc_speed, mutator_speed); | |
| 1267 } | 1272 } |
| 1268 | 1273 |
| 1269 { | 1274 { |
| 1270 GCCallbacksScope scope(this); | 1275 GCCallbacksScope scope(this); |
| 1271 if (scope.CheckReenter()) { | 1276 if (scope.CheckReenter()) { |
| 1272 AllowHeapAllocation allow_allocation; | 1277 AllowHeapAllocation allow_allocation; |
| 1273 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); | 1278 GCTracer::Scope scope(tracer(), GCTracer::Scope::EXTERNAL); |
| 1274 VMState<EXTERNAL> state(isolate_); | 1279 VMState<EXTERNAL> state(isolate_); |
| 1275 HandleScope handle_scope(isolate_); | 1280 HandleScope handle_scope(isolate_); |
| 1276 CallGCEpilogueCallbacks(gc_type, gc_callback_flags); | 1281 CallGCEpilogueCallbacks(gc_type, gc_callback_flags); |
| (...skipping 4002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5279 | 5284 |
| 5280 int64_t Heap::PromotedExternalMemorySize() { | 5285 int64_t Heap::PromotedExternalMemorySize() { |
| 5281 if (amount_of_external_allocated_memory_ <= | 5286 if (amount_of_external_allocated_memory_ <= |
| 5282 amount_of_external_allocated_memory_at_last_global_gc_) | 5287 amount_of_external_allocated_memory_at_last_global_gc_) |
| 5283 return 0; | 5288 return 0; |
| 5284 return amount_of_external_allocated_memory_ - | 5289 return amount_of_external_allocated_memory_ - |
| 5285 amount_of_external_allocated_memory_at_last_global_gc_; | 5290 amount_of_external_allocated_memory_at_last_global_gc_; |
| 5286 } | 5291 } |
| 5287 | 5292 |
| 5288 | 5293 |
| 5294 const double Heap::kMinHeapGrowingFactor = 1.1; | |
| 5295 const double Heap::kMaxHeapGrowingFactor = 4.0; | |
| 5296 const double Heap::kMaxHeapGrowingFactorMemoryConstrained = 2.0; | |
| 5297 const double Heap::kMaxHeapGrowingFactorIdle = 1.5; | |
| 5298 const double Heap::kTargetMutatorUtilization = 0.97; | |
| 5299 | |
| 5300 | |
| 5301 // Given GC speed in bytes per ms, the allocation throughput in bytes per ms | |
| 5302 // (mutator speed), this functions returns the heap growing factor that will | |
| 5303 // achive the kTargetMutatorUtilisation if the GC speed and the mutator speed | |
| 5304 // remain the same until the next GC. For details and explanation see | |
| 5305 // https://goo.gl/LLGvBs. | |
|
Hannes Payer (out of office)
2015/06/11 01:33:57
Instead of posting a link, can we add the necessar
ulan
2015/06/11 08:49:37
Done.
| |
| 5306 double Heap::HeapGrowingFactor(double gc_speed, double mutator_speed) { | |
| 5307 double max_factor = kMaxHeapGrowingFactor; | |
| 5308 // We set the old generation growing factor to 2 to grow the heap slower on | |
| 5309 // memory-constrained devices. | |
| 5310 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { | |
|
Hannes Payer (out of office)
2015/06/11 01:33:57
If we would not access max_old_generation_size_, t
ulan
2015/06/11 08:49:37
Done. The first function to be unit-tested in Heap
| |
| 5311 max_factor = kMaxHeapGrowingFactorMemoryConstrained; | |
| 5312 } | |
| 5313 | |
| 5314 if (gc_speed == 0 || mutator_speed == 0) return max_factor; | |
| 5315 | |
| 5316 const double speed_ratio = gc_speed / mutator_speed; | |
| 5317 const double mu = kTargetMutatorUtilization; | |
| 5318 | |
| 5319 const double a = speed_ratio * (1 - mu); | |
| 5320 const double b = speed_ratio * (1 - mu) - mu; | |
| 5321 | |
| 5322 // The factor is a / b, but we need to check for small b first. | |
| 5323 double factor = (a < b * max_factor) ? a / b : max_factor; | |
| 5324 factor = Min(factor, max_factor); | |
| 5325 factor = Max(factor, kMinHeapGrowingFactor); | |
| 5326 if (FLAG_trace_gc_verbose) { | |
| 5327 PrintIsolate(isolate_, | |
| 5328 "Heap growing factor %.1f based on mu=%.3f, speed_ratio=%.f " | |
| 5329 "(gc=%.f, mutator=%.f)\n", | |
| 5330 factor, mu, speed_ratio, gc_speed, mutator_speed); | |
| 5331 } | |
| 5332 return factor; | |
| 5333 } | |
| 5334 | |
| 5335 | |
| 5289 intptr_t Heap::CalculateOldGenerationAllocationLimit(double factor, | 5336 intptr_t Heap::CalculateOldGenerationAllocationLimit(double factor, |
| 5290 intptr_t old_gen_size) { | 5337 intptr_t old_gen_size) { |
| 5291 CHECK(factor > 1.0); | 5338 CHECK(factor > 1.0); |
| 5292 CHECK(old_gen_size > 0); | 5339 CHECK(old_gen_size > 0); |
| 5293 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); | 5340 intptr_t limit = static_cast<intptr_t>(old_gen_size * factor); |
| 5294 limit = Max(limit, old_gen_size + kMinimumOldGenerationAllocationLimit); | 5341 limit = Max(limit, old_gen_size + kMinimumOldGenerationAllocationLimit); |
| 5295 limit += new_space_.Capacity(); | 5342 limit += new_space_.Capacity(); |
| 5296 intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; | 5343 intptr_t halfway_to_the_max = (old_gen_size + max_old_generation_size_) / 2; |
| 5297 return Min(limit, halfway_to_the_max); | 5344 return Min(limit, halfway_to_the_max); |
| 5298 } | 5345 } |
| 5299 | 5346 |
| 5300 | 5347 |
| 5301 void Heap::SetOldGenerationAllocationLimit( | 5348 void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size, |
| 5302 intptr_t old_gen_size, size_t current_allocation_throughput) { | 5349 double gc_speed, |
| 5303 // Allocation throughput on Android devices is typically lower than on | 5350 double mutator_speed) { |
| 5304 // non-mobile devices. | 5351 double factor = HeapGrowingFactor(gc_speed, mutator_speed); |
| 5305 #if V8_OS_ANDROID | |
| 5306 const size_t kHighThroughput = 2500; | |
| 5307 const size_t kLowThroughput = 250; | |
| 5308 #else | |
| 5309 const size_t kHighThroughput = 10000; | |
| 5310 const size_t kLowThroughput = 1000; | |
| 5311 #endif | |
| 5312 const double min_scaling_factor = 1.1; | |
| 5313 const double max_scaling_factor = 1.5; | |
| 5314 double max_factor = 4; | |
| 5315 const double idle_max_factor = 1.5; | |
| 5316 // We set the old generation growing factor to 2 to grow the heap slower on | |
| 5317 // memory-constrained devices. | |
| 5318 if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { | |
| 5319 max_factor = 2; | |
| 5320 } | |
| 5321 | |
| 5322 double factor; | |
| 5323 double idle_factor; | |
| 5324 if (current_allocation_throughput == 0 || | |
| 5325 current_allocation_throughput >= kHighThroughput) { | |
| 5326 factor = max_factor; | |
| 5327 } else if (current_allocation_throughput <= kLowThroughput) { | |
| 5328 factor = min_scaling_factor; | |
| 5329 } else { | |
| 5330 // Compute factor using linear interpolation between points | |
| 5331 // (kHighThroughput, max_scaling_factor) and (kLowThroughput, min_factor). | |
| 5332 factor = min_scaling_factor + | |
| 5333 (current_allocation_throughput - kLowThroughput) * | |
| 5334 (max_scaling_factor - min_scaling_factor) / | |
| 5335 (kHighThroughput - kLowThroughput); | |
| 5336 } | |
| 5337 | 5352 |
| 5338 if (FLAG_stress_compaction || | 5353 if (FLAG_stress_compaction || |
| 5339 mark_compact_collector()->reduce_memory_footprint_) { | 5354 mark_compact_collector()->reduce_memory_footprint_) { |
| 5340 factor = min_scaling_factor; | 5355 factor = kMinHeapGrowingFactor; |
| 5341 } | 5356 } |
| 5342 | 5357 |
| 5343 // TODO(hpayer): Investigate if idle_old_generation_allocation_limit_ is still | 5358 // TODO(hpayer): Investigate if idle_old_generation_allocation_limit_ is still |
| 5344 // needed after taking the allocation rate for the old generation limit into | 5359 // needed after taking the allocation rate for the old generation limit into |
| 5345 // account. | 5360 // account. |
| 5346 idle_factor = Min(factor, idle_max_factor); | 5361 double idle_factor = Min(factor, kMaxHeapGrowingFactorIdle); |
| 5347 | 5362 |
| 5348 old_generation_allocation_limit_ = | 5363 old_generation_allocation_limit_ = |
| 5349 CalculateOldGenerationAllocationLimit(factor, old_gen_size); | 5364 CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
| 5350 idle_old_generation_allocation_limit_ = | 5365 idle_old_generation_allocation_limit_ = |
| 5351 CalculateOldGenerationAllocationLimit(idle_factor, old_gen_size); | 5366 CalculateOldGenerationAllocationLimit(idle_factor, old_gen_size); |
| 5352 | 5367 |
| 5353 if (FLAG_trace_gc_verbose) { | 5368 if (FLAG_trace_gc_verbose) { |
| 5354 PrintIsolate( | 5369 PrintIsolate( |
| 5355 isolate_, | 5370 isolate_, |
| 5356 "Grow: old size: %" V8_PTR_PREFIX "d KB, new limit: %" V8_PTR_PREFIX | 5371 "Grow: old size: %" V8_PTR_PREFIX "d KB, new limit: %" V8_PTR_PREFIX |
| (...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6573 *object_type = "CODE_TYPE"; \ | 6588 *object_type = "CODE_TYPE"; \ |
| 6574 *object_sub_type = "CODE_AGE/" #name; \ | 6589 *object_sub_type = "CODE_AGE/" #name; \ |
| 6575 return true; | 6590 return true; |
| 6576 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) | 6591 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) |
| 6577 #undef COMPARE_AND_RETURN_NAME | 6592 #undef COMPARE_AND_RETURN_NAME |
| 6578 } | 6593 } |
| 6579 return false; | 6594 return false; |
| 6580 } | 6595 } |
| 6581 } // namespace internal | 6596 } // namespace internal |
| 6582 } // namespace v8 | 6597 } // namespace v8 |
| OLD | NEW |