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/heap/heap.h" | 5 #include "src/heap/heap.h" |
6 | 6 |
7 #include <unordered_map> | 7 #include <unordered_map> |
8 #include <unordered_set> | 8 #include <unordered_set> |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 4166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4177 bool Heap::HasHighFragmentation(size_t used, size_t committed) { | 4177 bool Heap::HasHighFragmentation(size_t used, size_t committed) { |
4178 const size_t kSlack = 16 * MB; | 4178 const size_t kSlack = 16 * MB; |
4179 // Fragmentation is high if committed > 2 * used + kSlack. | 4179 // Fragmentation is high if committed > 2 * used + kSlack. |
4180 // Rewrite the exression to avoid overflow. | 4180 // Rewrite the exression to avoid overflow. |
4181 DCHECK_GE(committed, used); | 4181 DCHECK_GE(committed, used); |
4182 return committed - used > used + kSlack; | 4182 return committed - used > used + kSlack; |
4183 } | 4183 } |
4184 | 4184 |
4185 bool Heap::ShouldOptimizeForMemoryUsage() { | 4185 bool Heap::ShouldOptimizeForMemoryUsage() { |
4186 return FLAG_optimize_for_size || isolate()->IsIsolateInBackground() || | 4186 return FLAG_optimize_for_size || isolate()->IsIsolateInBackground() || |
4187 HighMemoryPressure() || IsLowMemoryDevice(); | 4187 HighMemoryPressure(); |
4188 } | 4188 } |
4189 | 4189 |
4190 void Heap::ActivateMemoryReducerIfNeeded() { | 4190 void Heap::ActivateMemoryReducerIfNeeded() { |
4191 // Activate memory reducer when switching to background if | 4191 // Activate memory reducer when switching to background if |
4192 // - there was no mark compact since the start. | 4192 // - there was no mark compact since the start. |
4193 // - the committed memory can be potentially reduced. | 4193 // - the committed memory can be potentially reduced. |
4194 // 2 pages for the old, code, and map space + 1 page for new space. | 4194 // 2 pages for the old, code, and map space + 1 page for new space. |
4195 const int kMinCommittedMemory = 7 * Page::kPageSize; | 4195 const int kMinCommittedMemory = 7 * Page::kPageSize; |
4196 if (ms_count_ == 0 && CommittedMemory() > kMinCommittedMemory && | 4196 if (ms_count_ == 0 && CommittedMemory() > kMinCommittedMemory && |
4197 isolate()->IsIsolateInBackground()) { | 4197 isolate()->IsIsolateInBackground()) { |
(...skipping 1219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5417 // (Limit - Live) / mutator_speed = Limit * MU / (gc_speed * (1 - MU)) | 5417 // (Limit - Live) / mutator_speed = Limit * MU / (gc_speed * (1 - MU)) |
5418 // (Limit - Live) = Limit * MU * mutator_speed / (gc_speed * (1 - MU)) | 5418 // (Limit - Live) = Limit * MU * mutator_speed / (gc_speed * (1 - MU)) |
5419 // substitute R = gc_speed / mutator_speed | 5419 // substitute R = gc_speed / mutator_speed |
5420 // (Limit - Live) = Limit * MU / (R * (1 - MU)) | 5420 // (Limit - Live) = Limit * MU / (R * (1 - MU)) |
5421 // substitute F = Limit / Live | 5421 // substitute F = Limit / Live |
5422 // F - 1 = F * MU / (R * (1 - MU)) | 5422 // F - 1 = F * MU / (R * (1 - MU)) |
5423 // F - F * MU / (R * (1 - MU)) = 1 | 5423 // F - F * MU / (R * (1 - MU)) = 1 |
5424 // F * (1 - MU / (R * (1 - MU))) = 1 | 5424 // F * (1 - MU / (R * (1 - MU))) = 1 |
5425 // F * (R * (1 - MU) - MU) / (R * (1 - MU)) = 1 | 5425 // F * (R * (1 - MU) - MU) / (R * (1 - MU)) = 1 |
5426 // F = R * (1 - MU) / (R * (1 - MU) - MU) | 5426 // F = R * (1 - MU) / (R * (1 - MU) - MU) |
5427 double Heap::HeapGrowingFactor(double gc_speed, double mutator_speed) { | 5427 double Heap::HeapGrowingFactor(double gc_speed, double mutator_speed, |
5428 if (gc_speed == 0 || mutator_speed == 0) return kMaxHeapGrowingFactor; | 5428 double max_factor) { |
| 5429 DCHECK(max_factor >= kMinHeapGrowingFactor); |
| 5430 DCHECK(max_factor <= kMaxHeapGrowingFactor); |
| 5431 if (gc_speed == 0 || mutator_speed == 0) return max_factor; |
5429 | 5432 |
5430 const double speed_ratio = gc_speed / mutator_speed; | 5433 const double speed_ratio = gc_speed / mutator_speed; |
5431 const double mu = kTargetMutatorUtilization; | 5434 const double mu = kTargetMutatorUtilization; |
5432 | 5435 |
5433 const double a = speed_ratio * (1 - mu); | 5436 const double a = speed_ratio * (1 - mu); |
5434 const double b = speed_ratio * (1 - mu) - mu; | 5437 const double b = speed_ratio * (1 - mu) - mu; |
5435 | 5438 |
5436 // The factor is a / b, but we need to check for small b first. | 5439 // The factor is a / b, but we need to check for small b first. |
5437 double factor = | 5440 double factor = (a < b * max_factor) ? a / b : max_factor; |
5438 (a < b * kMaxHeapGrowingFactor) ? a / b : kMaxHeapGrowingFactor; | 5441 factor = Min(factor, max_factor); |
5439 factor = Min(factor, kMaxHeapGrowingFactor); | |
5440 factor = Max(factor, kMinHeapGrowingFactor); | 5442 factor = Max(factor, kMinHeapGrowingFactor); |
5441 return factor; | 5443 return factor; |
5442 } | 5444 } |
5443 | 5445 |
| 5446 double Heap::MaxHeapGrowingFactor(size_t max_old_generation_size) { |
| 5447 const double min_small_factor = 1.3; |
| 5448 const double max_small_factor = 2.0; |
| 5449 const double high_factor = 4.0; |
| 5450 |
| 5451 size_t max_old_generation_size_in_mb = max_old_generation_size / MB; |
| 5452 max_old_generation_size_in_mb = |
| 5453 Max(max_old_generation_size_in_mb, |
| 5454 static_cast<size_t>(kMinOldGenerationSize)); |
| 5455 |
| 5456 // If we are on a device with lots of memory, we allow a high heap |
| 5457 // growing factor. |
| 5458 if (max_old_generation_size_in_mb >= kMaxOldGenerationSize) { |
| 5459 return high_factor; |
| 5460 } |
| 5461 |
| 5462 DCHECK_GE(max_old_generation_size_in_mb, kMinOldGenerationSize); |
| 5463 DCHECK_LT(max_old_generation_size_in_mb, kMaxOldGenerationSize); |
| 5464 |
| 5465 // On smaller devices we linearly scale the factor: (X-A)/(B-A)*(D-C)+C |
| 5466 double factor = (max_old_generation_size_in_mb - kMinOldGenerationSize) * |
| 5467 (max_small_factor - min_small_factor) / |
| 5468 (kMaxOldGenerationSize - kMinOldGenerationSize) + |
| 5469 min_small_factor; |
| 5470 return factor; |
| 5471 } |
| 5472 |
5444 size_t Heap::CalculateOldGenerationAllocationLimit(double factor, | 5473 size_t Heap::CalculateOldGenerationAllocationLimit(double factor, |
5445 size_t old_gen_size) { | 5474 size_t old_gen_size) { |
5446 CHECK(factor > 1.0); | 5475 CHECK(factor > 1.0); |
5447 CHECK(old_gen_size > 0); | 5476 CHECK(old_gen_size > 0); |
5448 uint64_t limit = static_cast<uint64_t>(old_gen_size * factor); | 5477 uint64_t limit = static_cast<uint64_t>(old_gen_size * factor); |
5449 limit = Max(limit, static_cast<uint64_t>(old_gen_size) + | 5478 limit = Max(limit, static_cast<uint64_t>(old_gen_size) + |
5450 MinimumAllocationLimitGrowingStep()); | 5479 MinimumAllocationLimitGrowingStep()); |
5451 limit += new_space_->Capacity(); | 5480 limit += new_space_->Capacity(); |
5452 uint64_t halfway_to_the_max = | 5481 uint64_t halfway_to_the_max = |
5453 (static_cast<uint64_t>(old_gen_size) + max_old_generation_size_) / 2; | 5482 (static_cast<uint64_t>(old_gen_size) + max_old_generation_size_) / 2; |
5454 return static_cast<size_t>(Min(limit, halfway_to_the_max)); | 5483 return static_cast<size_t>(Min(limit, halfway_to_the_max)); |
5455 } | 5484 } |
5456 | 5485 |
5457 size_t Heap::MinimumAllocationLimitGrowingStep() { | 5486 size_t Heap::MinimumAllocationLimitGrowingStep() { |
5458 const size_t kRegularAllocationLimitGrowingStep = 8; | 5487 const size_t kRegularAllocationLimitGrowingStep = 8; |
5459 const size_t kLowMemoryAllocationLimitGrowingStep = 2; | 5488 const size_t kLowMemoryAllocationLimitGrowingStep = 2; |
5460 size_t limit = (Page::kPageSize > MB ? Page::kPageSize : MB); | 5489 size_t limit = (Page::kPageSize > MB ? Page::kPageSize : MB); |
5461 return limit * (ShouldOptimizeForMemoryUsage() | 5490 return limit * (ShouldOptimizeForMemoryUsage() |
5462 ? kLowMemoryAllocationLimitGrowingStep | 5491 ? kLowMemoryAllocationLimitGrowingStep |
5463 : kRegularAllocationLimitGrowingStep); | 5492 : kRegularAllocationLimitGrowingStep); |
5464 } | 5493 } |
5465 | 5494 |
5466 void Heap::SetOldGenerationAllocationLimit(size_t old_gen_size, double gc_speed, | 5495 void Heap::SetOldGenerationAllocationLimit(size_t old_gen_size, double gc_speed, |
5467 double mutator_speed) { | 5496 double mutator_speed) { |
5468 double factor = HeapGrowingFactor(gc_speed, mutator_speed); | 5497 double max_factor = MaxHeapGrowingFactor(max_old_generation_size_); |
| 5498 double factor = HeapGrowingFactor(gc_speed, mutator_speed, max_factor); |
5469 | 5499 |
5470 if (FLAG_trace_gc_verbose) { | 5500 if (FLAG_trace_gc_verbose) { |
5471 isolate_->PrintWithTimestamp( | 5501 isolate_->PrintWithTimestamp( |
5472 "Heap growing factor %.1f based on mu=%.3f, speed_ratio=%.f " | 5502 "Heap growing factor %.1f based on mu=%.3f, speed_ratio=%.f " |
5473 "(gc=%.f, mutator=%.f)\n", | 5503 "(gc=%.f, mutator=%.f)\n", |
5474 factor, kTargetMutatorUtilization, gc_speed / mutator_speed, gc_speed, | 5504 factor, kTargetMutatorUtilization, gc_speed / mutator_speed, gc_speed, |
5475 mutator_speed); | 5505 mutator_speed); |
5476 } | 5506 } |
5477 | 5507 |
5478 if (IsMemoryConstrainedDevice()) { | |
5479 factor = Min(factor, kMaxHeapGrowingFactorMemoryConstrained); | |
5480 } | |
5481 | |
5482 if (memory_reducer_->ShouldGrowHeapSlowly() || | 5508 if (memory_reducer_->ShouldGrowHeapSlowly() || |
5483 ShouldOptimizeForMemoryUsage()) { | 5509 ShouldOptimizeForMemoryUsage()) { |
5484 factor = Min(factor, kConservativeHeapGrowingFactor); | 5510 factor = Min(factor, kConservativeHeapGrowingFactor); |
5485 } | 5511 } |
5486 | 5512 |
5487 if (FLAG_stress_compaction || ShouldReduceMemory()) { | 5513 if (FLAG_stress_compaction || ShouldReduceMemory()) { |
5488 factor = kMinHeapGrowingFactor; | 5514 factor = kMinHeapGrowingFactor; |
5489 } | 5515 } |
5490 | 5516 |
5491 if (FLAG_heap_growing_percent > 0) { | 5517 if (FLAG_heap_growing_percent > 0) { |
5492 factor = 1.0 + FLAG_heap_growing_percent / 100.0; | 5518 factor = 1.0 + FLAG_heap_growing_percent / 100.0; |
5493 } | 5519 } |
5494 | 5520 |
5495 old_generation_allocation_limit_ = | 5521 old_generation_allocation_limit_ = |
5496 CalculateOldGenerationAllocationLimit(factor, old_gen_size); | 5522 CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
5497 | 5523 |
5498 if (FLAG_trace_gc_verbose) { | 5524 if (FLAG_trace_gc_verbose) { |
5499 isolate_->PrintWithTimestamp( | 5525 isolate_->PrintWithTimestamp( |
5500 "Grow: old size: %" PRIuS " KB, new limit: %" PRIuS " KB (%.1f)\n", | 5526 "Grow: old size: %" PRIuS " KB, new limit: %" PRIuS " KB (%.1f)\n", |
5501 old_gen_size / KB, old_generation_allocation_limit_ / KB, factor); | 5527 old_gen_size / KB, old_generation_allocation_limit_ / KB, factor); |
5502 } | 5528 } |
5503 } | 5529 } |
5504 | 5530 |
5505 void Heap::DampenOldGenerationAllocationLimit(size_t old_gen_size, | 5531 void Heap::DampenOldGenerationAllocationLimit(size_t old_gen_size, |
5506 double gc_speed, | 5532 double gc_speed, |
5507 double mutator_speed) { | 5533 double mutator_speed) { |
5508 double factor = HeapGrowingFactor(gc_speed, mutator_speed); | 5534 double max_factor = MaxHeapGrowingFactor(max_old_generation_size_); |
| 5535 double factor = HeapGrowingFactor(gc_speed, mutator_speed, max_factor); |
5509 size_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size); | 5536 size_t limit = CalculateOldGenerationAllocationLimit(factor, old_gen_size); |
5510 if (limit < old_generation_allocation_limit_) { | 5537 if (limit < old_generation_allocation_limit_) { |
5511 if (FLAG_trace_gc_verbose) { | 5538 if (FLAG_trace_gc_verbose) { |
5512 isolate_->PrintWithTimestamp( | 5539 isolate_->PrintWithTimestamp( |
5513 "Dampen: old size: %" PRIuS " KB, old limit: %" PRIuS | 5540 "Dampen: old size: %" PRIuS " KB, old limit: %" PRIuS |
5514 " KB, " | 5541 " KB, " |
5515 "new limit: %" PRIuS " KB (%.1f)\n", | 5542 "new limit: %" PRIuS " KB (%.1f)\n", |
5516 old_gen_size / KB, old_generation_allocation_limit_ / KB, limit / KB, | 5543 old_gen_size / KB, old_generation_allocation_limit_ / KB, limit / KB, |
5517 factor); | 5544 factor); |
5518 } | 5545 } |
(...skipping 1081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6600 case LO_SPACE: | 6627 case LO_SPACE: |
6601 return "LO_SPACE"; | 6628 return "LO_SPACE"; |
6602 default: | 6629 default: |
6603 UNREACHABLE(); | 6630 UNREACHABLE(); |
6604 } | 6631 } |
6605 return NULL; | 6632 return NULL; |
6606 } | 6633 } |
6607 | 6634 |
6608 } // namespace internal | 6635 } // namespace internal |
6609 } // namespace v8 | 6636 } // namespace v8 |
OLD | NEW |