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 |