[heap] Fix global memory scheduling
Rework limit computation: - Model controller as static classes based on traits. - Compute growing factors for both controllers and pick the larger growing factor for both controllers. - Factor out limit computation in its own function. Bug: chromium:948807 Change-Id: Id466a66d7aa573de91ad388ea9218e9f6721d19a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1627534 Commit-Queue: Michael Lippautz <mlippautz@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#61801}
This commit is contained in:
parent
e448740e2a
commit
aa1b81b697
@ -10,6 +10,49 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
template <typename Trait>
|
||||||
|
double MemoryController<Trait>::GrowingFactor(Heap* heap, size_t max_heap_size,
|
||||||
|
double gc_speed,
|
||||||
|
double mutator_speed) {
|
||||||
|
const double max_factor = MaxGrowingFactor(max_heap_size);
|
||||||
|
const double factor =
|
||||||
|
DynamicGrowingFactor(gc_speed, mutator_speed, max_factor);
|
||||||
|
if (FLAG_trace_gc_verbose) {
|
||||||
|
Isolate::FromHeap(heap)->PrintWithTimestamp(
|
||||||
|
"[%s] factor %.1f based on mu=%.3f, speed_ratio=%.f "
|
||||||
|
"(gc=%.f, mutator=%.f)\n",
|
||||||
|
Trait::kName, factor, Trait::kTargetMutatorUtilization,
|
||||||
|
gc_speed / mutator_speed, gc_speed, mutator_speed);
|
||||||
|
}
|
||||||
|
return factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Trait>
|
||||||
|
double MemoryController<Trait>::MaxGrowingFactor(size_t max_heap_size) {
|
||||||
|
constexpr double kMinSmallFactor = 1.3;
|
||||||
|
constexpr double kMaxSmallFactor = 2.0;
|
||||||
|
constexpr double kHighFactor = 4.0;
|
||||||
|
|
||||||
|
size_t max_size_in_mb = max_heap_size / MB;
|
||||||
|
max_size_in_mb = Max(max_size_in_mb, Trait::kMinSize);
|
||||||
|
|
||||||
|
// If we are on a device with lots of memory, we allow a high heap
|
||||||
|
// growing factor.
|
||||||
|
if (max_size_in_mb >= Trait::kMaxSize) {
|
||||||
|
return kHighFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
DCHECK_GE(max_size_in_mb, Trait::kMinSize);
|
||||||
|
DCHECK_LT(max_size_in_mb, Trait::kMaxSize);
|
||||||
|
|
||||||
|
// On smaller devices we linearly scale the factor: (X-A)/(B-A)*(D-C)+C
|
||||||
|
double factor = (max_size_in_mb - Trait::kMinSize) *
|
||||||
|
(kMaxSmallFactor - kMinSmallFactor) /
|
||||||
|
(Trait::kMaxSize - Trait::kMinSize) +
|
||||||
|
kMinSmallFactor;
|
||||||
|
return factor;
|
||||||
|
}
|
||||||
|
|
||||||
// Given GC speed in bytes per ms, the allocation throughput in bytes per ms
|
// Given GC speed in bytes per ms, the allocation throughput in bytes per ms
|
||||||
// (mutator speed), this function returns the heap growing factor that will
|
// (mutator speed), this function returns the heap growing factor that will
|
||||||
// achieve the target_mutator_utilization_ if the GC speed and the mutator speed
|
// achieve the target_mutator_utilization_ if the GC speed and the mutator speed
|
||||||
@ -49,63 +92,29 @@ namespace internal {
|
|||||||
// F * (1 - MU / (R * (1 - MU))) = 1
|
// F * (1 - MU / (R * (1 - MU))) = 1
|
||||||
// F * (R * (1 - MU) - MU) / (R * (1 - MU)) = 1
|
// F * (R * (1 - MU) - MU) / (R * (1 - MU)) = 1
|
||||||
// F = R * (1 - MU) / (R * (1 - MU) - MU)
|
// F = R * (1 - MU) / (R * (1 - MU) - MU)
|
||||||
double MemoryController::GrowingFactor(double gc_speed, double mutator_speed,
|
template <typename Trait>
|
||||||
|
double MemoryController<Trait>::DynamicGrowingFactor(double gc_speed,
|
||||||
|
double mutator_speed,
|
||||||
double max_factor) {
|
double max_factor) {
|
||||||
DCHECK_LE(min_growing_factor_, max_factor);
|
DCHECK_LE(Trait::kMinGrowingFactor, max_factor);
|
||||||
DCHECK_GE(max_growing_factor_, max_factor);
|
DCHECK_GE(Trait::kMaxGrowingFactor, max_factor);
|
||||||
if (gc_speed == 0 || mutator_speed == 0) return max_factor;
|
if (gc_speed == 0 || mutator_speed == 0) return max_factor;
|
||||||
|
|
||||||
const double speed_ratio = gc_speed / mutator_speed;
|
const double speed_ratio = gc_speed / mutator_speed;
|
||||||
|
|
||||||
const double a = speed_ratio * (1 - target_mutator_utlization_);
|
const double a = speed_ratio * (1 - Trait::kTargetMutatorUtilization);
|
||||||
const double b = speed_ratio * (1 - target_mutator_utlization_) -
|
const double b = speed_ratio * (1 - Trait::kTargetMutatorUtilization) -
|
||||||
target_mutator_utlization_;
|
Trait::kTargetMutatorUtilization;
|
||||||
|
|
||||||
// The factor is a / b, but we need to check for small b first.
|
// The factor is a / b, but we need to check for small b first.
|
||||||
double factor = (a < b * max_factor) ? a / b : max_factor;
|
double factor = (a < b * max_factor) ? a / b : max_factor;
|
||||||
factor = Min(factor, max_factor);
|
factor = Min(factor, max_factor);
|
||||||
factor = Max(factor, min_growing_factor_);
|
factor = Max(factor, Trait::kMinGrowingFactor);
|
||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MemoryController::CalculateAllocationLimitBase(
|
template <typename Trait>
|
||||||
size_t curr_size, size_t max_size, double factor, size_t additional_bytes,
|
size_t MemoryController<Trait>::MinimumAllocationLimitGrowingStep(
|
||||||
Heap::HeapGrowingMode growing_mode) {
|
|
||||||
switch (growing_mode) {
|
|
||||||
case Heap::HeapGrowingMode::kConservative:
|
|
||||||
case Heap::HeapGrowingMode::kSlow:
|
|
||||||
factor = Min(factor, conservative_growing_factor_);
|
|
||||||
break;
|
|
||||||
case Heap::HeapGrowingMode::kMinimal:
|
|
||||||
factor = min_growing_factor_;
|
|
||||||
break;
|
|
||||||
case Heap::HeapGrowingMode::kDefault:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FLAG_heap_growing_percent > 0) {
|
|
||||||
factor = 1.0 + FLAG_heap_growing_percent / 100.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_LT(1.0, factor);
|
|
||||||
CHECK_LT(0, curr_size);
|
|
||||||
const uint64_t limit =
|
|
||||||
Max(static_cast<uint64_t>(curr_size * factor),
|
|
||||||
static_cast<uint64_t>(curr_size) +
|
|
||||||
MinimumAllocationLimitGrowingStep(growing_mode)) +
|
|
||||||
additional_bytes;
|
|
||||||
const uint64_t halfway_to_the_max =
|
|
||||||
(static_cast<uint64_t>(curr_size) + max_size) / 2;
|
|
||||||
const size_t result = static_cast<size_t>(Min(limit, halfway_to_the_max));
|
|
||||||
if (FLAG_trace_gc_verbose) {
|
|
||||||
Isolate::FromHeap(heap_)->PrintWithTimestamp(
|
|
||||||
"[%s] Limit: old size: %zu KB, new limit: %zu KB (%.1f)\n",
|
|
||||||
ControllerName(), curr_size / KB, result / KB, factor);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t MemoryController::MinimumAllocationLimitGrowingStep(
|
|
||||||
Heap::HeapGrowingMode growing_mode) {
|
Heap::HeapGrowingMode growing_mode) {
|
||||||
const size_t kRegularAllocationLimitGrowingStep = 8;
|
const size_t kRegularAllocationLimitGrowingStep = 8;
|
||||||
const size_t kLowMemoryAllocationLimitGrowingStep = 2;
|
const size_t kLowMemoryAllocationLimitGrowingStep = 2;
|
||||||
@ -115,91 +124,53 @@ size_t MemoryController::MinimumAllocationLimitGrowingStep(
|
|||||||
: kRegularAllocationLimitGrowingStep);
|
: kRegularAllocationLimitGrowingStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
double HeapController::MaxGrowingFactor(size_t curr_max_size) {
|
template <typename Trait>
|
||||||
constexpr double kMinSmallFactor = 1.3;
|
size_t MemoryController<Trait>::CalculateAllocationLimit(
|
||||||
constexpr double kMaxSmallFactor = 2.0;
|
Heap* heap, size_t current_size, size_t max_size, size_t new_space_capacity,
|
||||||
constexpr double kHighFactor = 4.0;
|
double factor, Heap::HeapGrowingMode growing_mode) {
|
||||||
|
switch (growing_mode) {
|
||||||
size_t max_size_in_mb = curr_max_size / MB;
|
case Heap::HeapGrowingMode::kConservative:
|
||||||
max_size_in_mb = Max(max_size_in_mb, kMinSize);
|
case Heap::HeapGrowingMode::kSlow:
|
||||||
|
factor = Min(factor, Trait::kConservativeGrowingFactor);
|
||||||
// If we are on a device with lots of memory, we allow a high heap
|
break;
|
||||||
// growing factor.
|
case Heap::HeapGrowingMode::kMinimal:
|
||||||
if (max_size_in_mb >= kMaxSize) {
|
factor = Trait::kMinGrowingFactor;
|
||||||
return kHighFactor;
|
break;
|
||||||
|
case Heap::HeapGrowingMode::kDefault:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DCHECK_GE(max_size_in_mb, kMinSize);
|
if (FLAG_heap_growing_percent > 0) {
|
||||||
DCHECK_LT(max_size_in_mb, kMaxSize);
|
factor = 1.0 + FLAG_heap_growing_percent / 100.0;
|
||||||
|
|
||||||
// On smaller devices we linearly scale the factor: (X-A)/(B-A)*(D-C)+C
|
|
||||||
double factor = (max_size_in_mb - kMinSize) *
|
|
||||||
(kMaxSmallFactor - kMinSmallFactor) /
|
|
||||||
(kMaxSize - kMinSize) +
|
|
||||||
kMinSmallFactor;
|
|
||||||
return factor;
|
|
||||||
}
|
|
||||||
|
|
||||||
double GlobalMemoryController::MaxGrowingFactor(size_t curr_max_size) {
|
|
||||||
constexpr double kMinSmallFactor = 1.3;
|
|
||||||
constexpr double kMaxSmallFactor = 2.0;
|
|
||||||
constexpr double kHighFactor = 4.0;
|
|
||||||
|
|
||||||
size_t max_size_in_mb = curr_max_size / MB;
|
|
||||||
max_size_in_mb = Max(max_size_in_mb, kMinSize);
|
|
||||||
|
|
||||||
// If we are on a device with lots of memory, we allow a high heap
|
|
||||||
// growing factor.
|
|
||||||
if (max_size_in_mb >= kMaxSize) {
|
|
||||||
return kHighFactor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DCHECK_GE(max_size_in_mb, kMinSize);
|
if (FLAG_heap_growing_percent > 0) {
|
||||||
DCHECK_LT(max_size_in_mb, kMaxSize);
|
factor = 1.0 + FLAG_heap_growing_percent / 100.0;
|
||||||
|
}
|
||||||
// On smaller devices we linearly scale the factor: (X-A)/(B-A)*(D-C)+C
|
|
||||||
double factor = (max_size_in_mb - kMinSize) *
|
|
||||||
(kMaxSmallFactor - kMinSmallFactor) /
|
|
||||||
(kMaxSize - kMinSize) +
|
|
||||||
kMinSmallFactor;
|
|
||||||
return factor;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t HeapController::CalculateAllocationLimit(
|
|
||||||
size_t curr_size, size_t max_size, double gc_speed, double mutator_speed,
|
|
||||||
size_t new_space_capacity, Heap::HeapGrowingMode growing_mode) {
|
|
||||||
const double max_factor = MaxGrowingFactor(max_size);
|
|
||||||
const double factor = GrowingFactor(gc_speed, mutator_speed, max_factor);
|
|
||||||
|
|
||||||
|
CHECK_LT(1.0, factor);
|
||||||
|
CHECK_LT(0, current_size);
|
||||||
|
const uint64_t limit =
|
||||||
|
Max(static_cast<uint64_t>(current_size * factor),
|
||||||
|
static_cast<uint64_t>(current_size) +
|
||||||
|
MinimumAllocationLimitGrowingStep(growing_mode)) +
|
||||||
|
new_space_capacity;
|
||||||
|
const uint64_t halfway_to_the_max =
|
||||||
|
(static_cast<uint64_t>(current_size) + max_size) / 2;
|
||||||
|
const size_t result = static_cast<size_t>(Min(limit, halfway_to_the_max));
|
||||||
if (FLAG_trace_gc_verbose) {
|
if (FLAG_trace_gc_verbose) {
|
||||||
Isolate::FromHeap(heap_)->PrintWithTimestamp(
|
Isolate::FromHeap(heap)->PrintWithTimestamp(
|
||||||
"[%s] factor %.1f based on mu=%.3f, speed_ratio=%.f "
|
"[%s] Limit: old size: %zu KB, new limit: %zu KB (%.1f)\n",
|
||||||
"(gc=%.f, mutator=%.f)\n",
|
Trait::kName, current_size / KB, result / KB, factor);
|
||||||
ControllerName(), factor, target_mutator_utlization_,
|
|
||||||
gc_speed / mutator_speed, gc_speed, mutator_speed);
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
return CalculateAllocationLimitBase(curr_size, max_size, factor,
|
|
||||||
new_space_capacity, growing_mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GlobalMemoryController::CalculateAllocationLimit(
|
template class V8_EXPORT_PRIVATE MemoryController<V8HeapTrait>;
|
||||||
size_t curr_size, size_t max_size, double gc_speed, double mutator_speed,
|
template class V8_EXPORT_PRIVATE MemoryController<GlobalMemoryTrait>;
|
||||||
size_t new_space_capacity, Heap::HeapGrowingMode growing_mode) {
|
|
||||||
const double max_factor = MaxGrowingFactor(max_size);
|
|
||||||
const double factor = GrowingFactor(gc_speed, mutator_speed, max_factor);
|
|
||||||
|
|
||||||
if (FLAG_trace_gc_verbose) {
|
const char* V8HeapTrait::kName = "HeapController";
|
||||||
Isolate::FromHeap(heap_)->PrintWithTimestamp(
|
const char* GlobalMemoryTrait::kName = "GlobalMemoryController";
|
||||||
"[%s] factor %.1f based on mu=%.3f, speed_ratio=%.f "
|
|
||||||
"(gc=%.f, mutator=%.f)\n",
|
|
||||||
ControllerName(), factor, target_mutator_utlization_,
|
|
||||||
gc_speed / mutator_speed, gc_speed, mutator_speed);
|
|
||||||
}
|
|
||||||
|
|
||||||
return CalculateAllocationLimitBase(curr_size, max_size, factor,
|
|
||||||
new_space_capacity, growing_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -13,85 +13,48 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
class V8_EXPORT_PRIVATE MemoryController {
|
struct BaseControllerTrait {
|
||||||
|
// Sizes are in MB.
|
||||||
|
static constexpr size_t kMinSize = 128 * Heap::kPointerMultiplier;
|
||||||
|
static constexpr size_t kMaxSize = 1024 * Heap::kPointerMultiplier;
|
||||||
|
|
||||||
|
static constexpr double kMinGrowingFactor = 1.1;
|
||||||
|
static constexpr double kMaxGrowingFactor = 4.0;
|
||||||
|
static constexpr double kConservativeGrowingFactor = 1.3;
|
||||||
|
static constexpr double kTargetMutatorUtilization = 0.97;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct V8HeapTrait : public BaseControllerTrait {
|
||||||
|
static const char* kName;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GlobalMemoryTrait : public BaseControllerTrait {
|
||||||
|
static const char* kName;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Trait>
|
||||||
|
class V8_EXPORT_PRIVATE MemoryController : public AllStatic {
|
||||||
public:
|
public:
|
||||||
// Computes the growing step when the limit increases.
|
// Computes the growing step when the limit increases.
|
||||||
static size_t MinimumAllocationLimitGrowingStep(
|
static size_t MinimumAllocationLimitGrowingStep(
|
||||||
Heap::HeapGrowingMode growing_mode);
|
Heap::HeapGrowingMode growing_mode);
|
||||||
|
|
||||||
virtual ~MemoryController() = default;
|
static double GrowingFactor(Heap* heap, size_t max_heap_size, double gc_speed,
|
||||||
|
double mutator_speed);
|
||||||
|
|
||||||
protected:
|
static size_t CalculateAllocationLimit(Heap* heap, size_t current_size,
|
||||||
MemoryController(Heap* heap, double min_growing_factor,
|
size_t max_size,
|
||||||
double max_growing_factor,
|
size_t new_space_capacity,
|
||||||
double conservative_growing_factor,
|
double factor,
|
||||||
double target_mutator_utlization)
|
|
||||||
: heap_(heap),
|
|
||||||
min_growing_factor_(min_growing_factor),
|
|
||||||
max_growing_factor_(max_growing_factor),
|
|
||||||
conservative_growing_factor_(conservative_growing_factor),
|
|
||||||
target_mutator_utlization_(target_mutator_utlization) {}
|
|
||||||
|
|
||||||
// Computes the allocation limit to trigger the next garbage collection.
|
|
||||||
size_t CalculateAllocationLimitBase(size_t curr_size, size_t max_size,
|
|
||||||
double factor, size_t additional_bytes,
|
|
||||||
Heap::HeapGrowingMode growing_mode);
|
Heap::HeapGrowingMode growing_mode);
|
||||||
|
|
||||||
double GrowingFactor(double gc_speed, double mutator_speed,
|
private:
|
||||||
|
static double MaxGrowingFactor(size_t max_heap_size);
|
||||||
|
static double DynamicGrowingFactor(double gc_speed, double mutator_speed,
|
||||||
double max_factor);
|
double max_factor);
|
||||||
|
|
||||||
virtual const char* ControllerName() = 0;
|
FRIEND_TEST(MemoryControllerTest, HeapGrowingFactor);
|
||||||
|
FRIEND_TEST(MemoryControllerTest, MaxHeapGrowingFactor);
|
||||||
Heap* const heap_;
|
|
||||||
const double min_growing_factor_;
|
|
||||||
const double max_growing_factor_;
|
|
||||||
const double conservative_growing_factor_;
|
|
||||||
const double target_mutator_utlization_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class V8_EXPORT_PRIVATE HeapController : public MemoryController {
|
|
||||||
public:
|
|
||||||
// Sizes are in MB.
|
|
||||||
static constexpr size_t kMinSize = 128 * Heap::kPointerMultiplier;
|
|
||||||
static constexpr size_t kMaxSize = 1024 * Heap::kPointerMultiplier;
|
|
||||||
|
|
||||||
explicit HeapController(Heap* heap)
|
|
||||||
: MemoryController(heap, 1.1, 4.0, 1.3, 0.97) {}
|
|
||||||
|
|
||||||
size_t CalculateAllocationLimit(size_t curr_size, size_t max_size,
|
|
||||||
double gc_speed, double mutator_speed,
|
|
||||||
size_t new_space_capacity,
|
|
||||||
Heap::HeapGrowingMode growing_mode);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
double MaxGrowingFactor(size_t curr_max_size);
|
|
||||||
|
|
||||||
const char* ControllerName() override { return "HeapController"; }
|
|
||||||
|
|
||||||
FRIEND_TEST(HeapControllerTest, HeapGrowingFactor);
|
|
||||||
FRIEND_TEST(HeapControllerTest, MaxHeapGrowingFactor);
|
|
||||||
FRIEND_TEST(HeapControllerTest, MaxOldGenerationSize);
|
|
||||||
FRIEND_TEST(HeapControllerTest, OldGenerationAllocationLimit);
|
|
||||||
};
|
|
||||||
|
|
||||||
class V8_EXPORT_PRIVATE GlobalMemoryController : public MemoryController {
|
|
||||||
public:
|
|
||||||
// Sizes are in MB.
|
|
||||||
static constexpr size_t kMinSize = 128 * Heap::kPointerMultiplier;
|
|
||||||
static constexpr size_t kMaxSize = 1024 * Heap::kPointerMultiplier;
|
|
||||||
|
|
||||||
explicit GlobalMemoryController(Heap* heap)
|
|
||||||
: MemoryController(heap, 1.1, 4.0, 1.3, 0.97) {}
|
|
||||||
|
|
||||||
size_t CalculateAllocationLimit(size_t curr_size, size_t max_size,
|
|
||||||
double gc_speed, double mutator_speed,
|
|
||||||
size_t new_space_capacity,
|
|
||||||
Heap::HeapGrowingMode growing_mode);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
double MaxGrowingFactor(size_t curr_max_size);
|
|
||||||
|
|
||||||
const char* ControllerName() override { return "GlobalMemoryController"; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
153
src/heap/heap.cc
153
src/heap/heap.cc
@ -212,7 +212,7 @@ size_t Heap::ComputeMaxOldGenerationSize(uint64_t physical_memory) {
|
|||||||
size_t computed_size = static_cast<size_t>(physical_memory / i::MB /
|
size_t computed_size = static_cast<size_t>(physical_memory / i::MB /
|
||||||
old_space_physical_memory_factor *
|
old_space_physical_memory_factor *
|
||||||
kPointerMultiplier);
|
kPointerMultiplier);
|
||||||
size_t max_size_in_mb = HeapController::kMaxSize;
|
size_t max_size_in_mb = V8HeapTrait::kMaxSize;
|
||||||
|
|
||||||
// Finch experiment: Increase the heap size from 2GB to 4GB for 64-bit
|
// Finch experiment: Increase the heap size from 2GB to 4GB for 64-bit
|
||||||
// systems with physical memory bigger than 16GB.
|
// systems with physical memory bigger than 16GB.
|
||||||
@ -223,7 +223,7 @@ size_t Heap::ComputeMaxOldGenerationSize(uint64_t physical_memory) {
|
|||||||
max_size_in_mb = 4096; // 4GB
|
max_size_in_mb = 4096; // 4GB
|
||||||
}
|
}
|
||||||
|
|
||||||
return Max(Min(computed_size, max_size_in_mb), HeapController::kMinSize);
|
return Max(Min(computed_size, max_size_in_mb), V8HeapTrait::kMinSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Heap::Capacity() {
|
size_t Heap::Capacity() {
|
||||||
@ -1928,68 +1928,7 @@ bool Heap::PerformGarbageCollection(
|
|||||||
// Update relocatables.
|
// Update relocatables.
|
||||||
Relocatable::PostGarbageCollectionProcessing(isolate_);
|
Relocatable::PostGarbageCollectionProcessing(isolate_);
|
||||||
|
|
||||||
double gc_speed = tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond();
|
RecomputeLimits(collector);
|
||||||
double mutator_speed =
|
|
||||||
tracer()->CurrentOldGenerationAllocationThroughputInBytesPerMillisecond();
|
|
||||||
size_t old_gen_size = OldGenerationSizeOfObjects();
|
|
||||||
|
|
||||||
double global_mutator_speed;
|
|
||||||
double global_gc_speed;
|
|
||||||
size_t global_memory_size;
|
|
||||||
if (UseGlobalMemoryScheduling()) {
|
|
||||||
global_mutator_speed = GCTracer::CombineSpeedsInBytesPerMillisecond(
|
|
||||||
mutator_speed,
|
|
||||||
local_embedder_heap_tracer()
|
|
||||||
? tracer()
|
|
||||||
->CurrentEmbedderAllocationThroughputInBytesPerMillisecond()
|
|
||||||
: 0.0);
|
|
||||||
global_gc_speed = GCTracer::CombineSpeedsInBytesPerMillisecond(
|
|
||||||
gc_speed, local_embedder_heap_tracer()
|
|
||||||
? tracer()->EmbedderSpeedInBytesPerMillisecond()
|
|
||||||
: 0.0);
|
|
||||||
global_memory_size = GlobalSizeOfObjects();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (collector == MARK_COMPACTOR) {
|
|
||||||
// Register the amount of external allocated memory.
|
|
||||||
isolate()->isolate_data()->external_memory_at_last_mark_compact_ =
|
|
||||||
isolate()->isolate_data()->external_memory_;
|
|
||||||
isolate()->isolate_data()->external_memory_limit_ =
|
|
||||||
isolate()->isolate_data()->external_memory_ +
|
|
||||||
kExternalAllocationSoftLimit;
|
|
||||||
|
|
||||||
old_generation_allocation_limit_ =
|
|
||||||
heap_controller()->CalculateAllocationLimit(
|
|
||||||
old_gen_size, max_old_generation_size_, gc_speed, mutator_speed,
|
|
||||||
new_space()->Capacity(), CurrentHeapGrowingMode());
|
|
||||||
if (UseGlobalMemoryScheduling()) {
|
|
||||||
global_allocation_limit_ =
|
|
||||||
global_memory_controller()->CalculateAllocationLimit(
|
|
||||||
global_memory_size, max_global_memory_size_, global_gc_speed,
|
|
||||||
global_mutator_speed, new_space()->Capacity(),
|
|
||||||
CurrentHeapGrowingMode());
|
|
||||||
}
|
|
||||||
CheckIneffectiveMarkCompact(
|
|
||||||
old_gen_size, tracer()->AverageMarkCompactMutatorUtilization());
|
|
||||||
} else if (HasLowYoungGenerationAllocationRate() &&
|
|
||||||
old_generation_size_configured_) {
|
|
||||||
size_t new_limit = heap_controller()->CalculateAllocationLimit(
|
|
||||||
old_gen_size, max_old_generation_size_, gc_speed, mutator_speed,
|
|
||||||
new_space()->Capacity(), CurrentHeapGrowingMode());
|
|
||||||
if (new_limit < old_generation_allocation_limit_) {
|
|
||||||
old_generation_allocation_limit_ = new_limit;
|
|
||||||
}
|
|
||||||
if (UseGlobalMemoryScheduling()) {
|
|
||||||
const size_t new_global_limit =
|
|
||||||
global_memory_controller()->CalculateAllocationLimit(
|
|
||||||
global_memory_size, max_global_memory_size_, global_gc_speed,
|
|
||||||
global_mutator_speed, new_space()->Capacity(),
|
|
||||||
CurrentHeapGrowingMode());
|
|
||||||
if (new_global_limit < global_allocation_limit_) {
|
|
||||||
global_allocation_limit_ = new_global_limit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
GCCallbacksScope scope(this);
|
GCCallbacksScope scope(this);
|
||||||
@ -2012,6 +1951,84 @@ bool Heap::PerformGarbageCollection(
|
|||||||
return freed_global_handles > 0;
|
return freed_global_handles > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Heap::RecomputeLimits(GarbageCollector collector) {
|
||||||
|
if (!((collector == MARK_COMPACTOR) ||
|
||||||
|
(HasLowYoungGenerationAllocationRate() &&
|
||||||
|
old_generation_size_configured_))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double v8_gc_speed =
|
||||||
|
tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond();
|
||||||
|
double v8_mutator_speed =
|
||||||
|
tracer()->CurrentOldGenerationAllocationThroughputInBytesPerMillisecond();
|
||||||
|
double v8_growing_factor = MemoryController<V8HeapTrait>::GrowingFactor(
|
||||||
|
this, max_old_generation_size_, v8_gc_speed, v8_mutator_speed);
|
||||||
|
double global_growing_factor = 0;
|
||||||
|
if (UseGlobalMemoryScheduling()) {
|
||||||
|
double embedder_gc_speed =
|
||||||
|
local_embedder_heap_tracer()
|
||||||
|
? tracer()
|
||||||
|
->CurrentEmbedderAllocationThroughputInBytesPerMillisecond()
|
||||||
|
: 0.0;
|
||||||
|
double embedder_speed = local_embedder_heap_tracer()
|
||||||
|
? tracer()->EmbedderSpeedInBytesPerMillisecond()
|
||||||
|
: 0.0;
|
||||||
|
double embedder_growing_factor =
|
||||||
|
(embedder_gc_speed > 0 && embedder_speed > 0)
|
||||||
|
? MemoryController<GlobalMemoryTrait>::GrowingFactor(
|
||||||
|
this, max_global_memory_size_, embedder_gc_speed,
|
||||||
|
embedder_speed)
|
||||||
|
: 0;
|
||||||
|
global_growing_factor = Max(v8_growing_factor, embedder_growing_factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t old_gen_size = OldGenerationSizeOfObjects();
|
||||||
|
size_t new_space_capacity = new_space()->Capacity();
|
||||||
|
HeapGrowingMode mode = CurrentHeapGrowingMode();
|
||||||
|
|
||||||
|
if (collector == MARK_COMPACTOR) {
|
||||||
|
// Register the amount of external allocated memory.
|
||||||
|
isolate()->isolate_data()->external_memory_at_last_mark_compact_ =
|
||||||
|
isolate()->isolate_data()->external_memory_;
|
||||||
|
isolate()->isolate_data()->external_memory_limit_ =
|
||||||
|
isolate()->isolate_data()->external_memory_ +
|
||||||
|
kExternalAllocationSoftLimit;
|
||||||
|
|
||||||
|
old_generation_allocation_limit_ =
|
||||||
|
MemoryController<V8HeapTrait>::CalculateAllocationLimit(
|
||||||
|
this, old_gen_size, max_old_generation_size_, new_space_capacity,
|
||||||
|
v8_growing_factor, mode);
|
||||||
|
if (UseGlobalMemoryScheduling()) {
|
||||||
|
DCHECK_GT(global_growing_factor, 0);
|
||||||
|
global_allocation_limit_ =
|
||||||
|
MemoryController<GlobalMemoryTrait>::CalculateAllocationLimit(
|
||||||
|
this, GlobalSizeOfObjects(), max_global_memory_size_,
|
||||||
|
new_space_capacity, global_growing_factor, mode);
|
||||||
|
}
|
||||||
|
CheckIneffectiveMarkCompact(
|
||||||
|
old_gen_size, tracer()->AverageMarkCompactMutatorUtilization());
|
||||||
|
} else if (HasLowYoungGenerationAllocationRate() &&
|
||||||
|
old_generation_size_configured_) {
|
||||||
|
size_t new_old_generation_limit =
|
||||||
|
MemoryController<V8HeapTrait>::CalculateAllocationLimit(
|
||||||
|
this, old_gen_size, max_old_generation_size_, new_space_capacity,
|
||||||
|
v8_growing_factor, mode);
|
||||||
|
if (new_old_generation_limit < old_generation_allocation_limit_) {
|
||||||
|
old_generation_allocation_limit_ = new_old_generation_limit;
|
||||||
|
}
|
||||||
|
if (UseGlobalMemoryScheduling()) {
|
||||||
|
DCHECK_GT(global_growing_factor, 0);
|
||||||
|
size_t new_global_limit =
|
||||||
|
MemoryController<GlobalMemoryTrait>::CalculateAllocationLimit(
|
||||||
|
this, GlobalSizeOfObjects(), max_global_memory_size_,
|
||||||
|
new_space_capacity, global_growing_factor, mode);
|
||||||
|
if (new_global_limit < global_allocation_limit_) {
|
||||||
|
global_allocation_limit_ = new_global_limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) {
|
void Heap::CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags) {
|
||||||
RuntimeCallTimerScope runtime_timer(
|
RuntimeCallTimerScope runtime_timer(
|
||||||
@ -2646,7 +2663,7 @@ void Heap::UnregisterArrayBuffer(JSArrayBuffer buffer) {
|
|||||||
void Heap::ConfigureInitialOldGenerationSize() {
|
void Heap::ConfigureInitialOldGenerationSize() {
|
||||||
if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) {
|
if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) {
|
||||||
const size_t minimum_growing_step =
|
const size_t minimum_growing_step =
|
||||||
MemoryController::MinimumAllocationLimitGrowingStep(
|
MemoryController<V8HeapTrait>::MinimumAllocationLimitGrowingStep(
|
||||||
CurrentHeapGrowingMode());
|
CurrentHeapGrowingMode());
|
||||||
const size_t new_old_generation_allocation_limit =
|
const size_t new_old_generation_allocation_limit =
|
||||||
Max(OldGenerationSizeOfObjects() + minimum_growing_step,
|
Max(OldGenerationSizeOfObjects() + minimum_growing_step,
|
||||||
@ -4729,9 +4746,6 @@ void Heap::SetUp() {
|
|||||||
|
|
||||||
store_buffer_.reset(new StoreBuffer(this));
|
store_buffer_.reset(new StoreBuffer(this));
|
||||||
|
|
||||||
heap_controller_.reset(new HeapController(this));
|
|
||||||
global_memory_controller_.reset(new GlobalMemoryController(this));
|
|
||||||
|
|
||||||
mark_compact_collector_.reset(new MarkCompactCollector(this));
|
mark_compact_collector_.reset(new MarkCompactCollector(this));
|
||||||
|
|
||||||
scavenger_collector_.reset(new ScavengerCollector(this));
|
scavenger_collector_.reset(new ScavengerCollector(this));
|
||||||
@ -5007,9 +5021,6 @@ void Heap::TearDown() {
|
|||||||
stress_scavenge_observer_ = nullptr;
|
stress_scavenge_observer_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_controller_.reset();
|
|
||||||
global_memory_controller_.reset();
|
|
||||||
|
|
||||||
if (mark_compact_collector_) {
|
if (mark_compact_collector_) {
|
||||||
mark_compact_collector_->TearDown();
|
mark_compact_collector_->TearDown();
|
||||||
mark_compact_collector_.reset();
|
mark_compact_collector_.reset();
|
||||||
|
@ -62,7 +62,6 @@ class ConcurrentMarking;
|
|||||||
class GCIdleTimeHandler;
|
class GCIdleTimeHandler;
|
||||||
class GCIdleTimeHeapState;
|
class GCIdleTimeHeapState;
|
||||||
class GCTracer;
|
class GCTracer;
|
||||||
class GlobalMemoryController;
|
|
||||||
class HeapController;
|
class HeapController;
|
||||||
class HeapObjectAllocationTracker;
|
class HeapObjectAllocationTracker;
|
||||||
class HeapObjectsFilter;
|
class HeapObjectsFilter;
|
||||||
@ -213,6 +212,8 @@ class Heap {
|
|||||||
EphemeronRememberedSet ephemeron_remembered_set_;
|
EphemeronRememberedSet ephemeron_remembered_set_;
|
||||||
enum FindMementoMode { kForRuntime, kForGC };
|
enum FindMementoMode { kForRuntime, kForGC };
|
||||||
|
|
||||||
|
enum class HeapGrowingMode { kSlow, kConservative, kMinimal, kDefault };
|
||||||
|
|
||||||
enum HeapState {
|
enum HeapState {
|
||||||
NOT_IN_GC,
|
NOT_IN_GC,
|
||||||
SCAVENGE,
|
SCAVENGE,
|
||||||
@ -1692,10 +1693,6 @@ class Heap {
|
|||||||
// Growing strategy. =========================================================
|
// Growing strategy. =========================================================
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|
||||||
HeapController* heap_controller() { return heap_controller_.get(); }
|
|
||||||
GlobalMemoryController* global_memory_controller() const {
|
|
||||||
return global_memory_controller_.get();
|
|
||||||
}
|
|
||||||
MemoryReducer* memory_reducer() { return memory_reducer_.get(); }
|
MemoryReducer* memory_reducer() { return memory_reducer_.get(); }
|
||||||
|
|
||||||
// For some webpages RAIL mode does not switch from PERFORMANCE_LOAD.
|
// For some webpages RAIL mode does not switch from PERFORMANCE_LOAD.
|
||||||
@ -1716,8 +1713,6 @@ class Heap {
|
|||||||
|
|
||||||
bool ShouldExpandOldGenerationOnSlowAllocation();
|
bool ShouldExpandOldGenerationOnSlowAllocation();
|
||||||
|
|
||||||
enum class HeapGrowingMode { kSlow, kConservative, kMinimal, kDefault };
|
|
||||||
|
|
||||||
HeapGrowingMode CurrentHeapGrowingMode();
|
HeapGrowingMode CurrentHeapGrowingMode();
|
||||||
|
|
||||||
enum class IncrementalMarkingLimit { kNoLimit, kSoftLimit, kHardLimit };
|
enum class IncrementalMarkingLimit { kNoLimit, kSoftLimit, kHardLimit };
|
||||||
@ -1729,6 +1724,8 @@ class Heap {
|
|||||||
|
|
||||||
size_t GlobalMemoryAvailable();
|
size_t GlobalMemoryAvailable();
|
||||||
|
|
||||||
|
void RecomputeLimits(GarbageCollector collector);
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
// Idle notification. ========================================================
|
// Idle notification. ========================================================
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
@ -1985,8 +1982,6 @@ class Heap {
|
|||||||
std::unique_ptr<ArrayBufferCollector> array_buffer_collector_;
|
std::unique_ptr<ArrayBufferCollector> array_buffer_collector_;
|
||||||
std::unique_ptr<MemoryAllocator> memory_allocator_;
|
std::unique_ptr<MemoryAllocator> memory_allocator_;
|
||||||
std::unique_ptr<StoreBuffer> store_buffer_;
|
std::unique_ptr<StoreBuffer> store_buffer_;
|
||||||
std::unique_ptr<HeapController> heap_controller_;
|
|
||||||
std::unique_ptr<GlobalMemoryController> global_memory_controller_;
|
|
||||||
std::unique_ptr<IncrementalMarking> incremental_marking_;
|
std::unique_ptr<IncrementalMarking> incremental_marking_;
|
||||||
std::unique_ptr<ConcurrentMarking> concurrent_marking_;
|
std::unique_ptr<ConcurrentMarking> concurrent_marking_;
|
||||||
std::unique_ptr<GCIdleTimeHandler> gc_idle_time_handler_;
|
std::unique_ptr<GCIdleTimeHandler> gc_idle_time_handler_;
|
||||||
@ -2086,9 +2081,6 @@ class Heap {
|
|||||||
friend class ConcurrentMarking;
|
friend class ConcurrentMarking;
|
||||||
friend class GCCallbacksScope;
|
friend class GCCallbacksScope;
|
||||||
friend class GCTracer;
|
friend class GCTracer;
|
||||||
friend class GlobalMemoryController;
|
|
||||||
friend class HeapController;
|
|
||||||
friend class MemoryController;
|
|
||||||
friend class HeapIterator;
|
friend class HeapIterator;
|
||||||
friend class IdleScavengeObserver;
|
friend class IdleScavengeObserver;
|
||||||
friend class IncrementalMarking;
|
friend class IncrementalMarking;
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
using HeapControllerTest = TestWithIsolate;
|
using MemoryControllerTest = TestWithIsolate;
|
||||||
|
|
||||||
double Round(double x) {
|
double Round(double x) {
|
||||||
// Round to three digits.
|
// Round to three digits.
|
||||||
@ -32,82 +32,81 @@ void CheckEqualRounded(double expected, double actual) {
|
|||||||
EXPECT_DOUBLE_EQ(expected, actual);
|
EXPECT_DOUBLE_EQ(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HeapControllerTest, HeapGrowingFactor) {
|
namespace {
|
||||||
HeapController heap_controller(i_isolate()->heap());
|
|
||||||
double min_factor = heap_controller.min_growing_factor_;
|
|
||||||
double max_factor = heap_controller.max_growing_factor_;
|
|
||||||
|
|
||||||
CheckEqualRounded(max_factor, heap_controller.GrowingFactor(34, 1, 4.0));
|
using V8Controller = MemoryController<V8HeapTrait>;
|
||||||
CheckEqualRounded(3.553, heap_controller.GrowingFactor(45, 1, 4.0));
|
|
||||||
CheckEqualRounded(2.830, heap_controller.GrowingFactor(50, 1, 4.0));
|
} // namespace
|
||||||
CheckEqualRounded(1.478, heap_controller.GrowingFactor(100, 1, 4.0));
|
|
||||||
CheckEqualRounded(1.193, heap_controller.GrowingFactor(200, 1, 4.0));
|
TEST_F(MemoryControllerTest, HeapGrowingFactor) {
|
||||||
CheckEqualRounded(1.121, heap_controller.GrowingFactor(300, 1, 4.0));
|
CheckEqualRounded(V8HeapTrait::kMaxGrowingFactor,
|
||||||
CheckEqualRounded(heap_controller.GrowingFactor(300, 1, 4.0),
|
V8Controller::DynamicGrowingFactor(34, 1, 4.0));
|
||||||
heap_controller.GrowingFactor(600, 2, 4.0));
|
CheckEqualRounded(3.553, V8Controller::DynamicGrowingFactor(45, 1, 4.0));
|
||||||
CheckEqualRounded(min_factor, heap_controller.GrowingFactor(400, 1, 4.0));
|
CheckEqualRounded(2.830, V8Controller::DynamicGrowingFactor(50, 1, 4.0));
|
||||||
|
CheckEqualRounded(1.478, V8Controller::DynamicGrowingFactor(100, 1, 4.0));
|
||||||
|
CheckEqualRounded(1.193, V8Controller::DynamicGrowingFactor(200, 1, 4.0));
|
||||||
|
CheckEqualRounded(1.121, V8Controller::DynamicGrowingFactor(300, 1, 4.0));
|
||||||
|
CheckEqualRounded(V8Controller::DynamicGrowingFactor(300, 1, 4.0),
|
||||||
|
V8Controller::DynamicGrowingFactor(600, 2, 4.0));
|
||||||
|
CheckEqualRounded(V8HeapTrait::kMinGrowingFactor,
|
||||||
|
V8Controller::DynamicGrowingFactor(400, 1, 4.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HeapControllerTest, MaxHeapGrowingFactor) {
|
TEST_F(MemoryControllerTest, MaxHeapGrowingFactor) {
|
||||||
HeapController heap_controller(i_isolate()->heap());
|
CheckEqualRounded(1.3,
|
||||||
|
V8Controller::MaxGrowingFactor(V8HeapTrait::kMinSize * MB));
|
||||||
CheckEqualRounded(
|
CheckEqualRounded(
|
||||||
1.3, heap_controller.MaxGrowingFactor(HeapController::kMinSize * MB));
|
1.600, V8Controller::MaxGrowingFactor(V8HeapTrait::kMaxSize / 2 * MB));
|
||||||
CheckEqualRounded(1.600, heap_controller.MaxGrowingFactor(
|
|
||||||
HeapController::kMaxSize / 2 * MB));
|
|
||||||
CheckEqualRounded(
|
CheckEqualRounded(
|
||||||
1.999, heap_controller.MaxGrowingFactor(
|
1.999, V8Controller::MaxGrowingFactor(
|
||||||
(HeapController::kMaxSize - Heap::kPointerMultiplier) * MB));
|
(V8HeapTrait::kMaxSize - Heap::kPointerMultiplier) * MB));
|
||||||
CheckEqualRounded(4.0,
|
CheckEqualRounded(4.0, V8Controller::MaxGrowingFactor(
|
||||||
heap_controller.MaxGrowingFactor(
|
static_cast<size_t>(V8HeapTrait::kMaxSize) * MB));
|
||||||
static_cast<size_t>(HeapController::kMaxSize) * MB));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HeapControllerTest, OldGenerationAllocationLimit) {
|
TEST_F(MemoryControllerTest, OldGenerationAllocationLimit) {
|
||||||
Heap* heap = i_isolate()->heap();
|
Heap* heap = i_isolate()->heap();
|
||||||
HeapController heap_controller(heap);
|
|
||||||
size_t old_gen_size = 128 * MB;
|
size_t old_gen_size = 128 * MB;
|
||||||
size_t max_old_generation_size = 512 * MB;
|
size_t max_old_generation_size = 512 * MB;
|
||||||
double gc_speed = 100;
|
double gc_speed = 100;
|
||||||
double mutator_speed = 1;
|
double mutator_speed = 1;
|
||||||
size_t new_space_capacity = 16 * MB;
|
size_t new_space_capacity = 16 * MB;
|
||||||
|
|
||||||
double max_factor = heap_controller.MaxGrowingFactor(max_old_generation_size);
|
double factor = V8Controller::GrowingFactor(heap, max_old_generation_size,
|
||||||
double factor =
|
gc_speed, mutator_speed);
|
||||||
heap_controller.GrowingFactor(gc_speed, mutator_speed, max_factor);
|
|
||||||
|
|
||||||
EXPECT_EQ(static_cast<size_t>(old_gen_size * factor + new_space_capacity),
|
EXPECT_EQ(static_cast<size_t>(old_gen_size * factor + new_space_capacity),
|
||||||
heap->heap_controller()->CalculateAllocationLimit(
|
V8Controller::CalculateAllocationLimit(
|
||||||
old_gen_size, max_old_generation_size, gc_speed, mutator_speed,
|
heap, old_gen_size, max_old_generation_size, new_space_capacity,
|
||||||
new_space_capacity, Heap::HeapGrowingMode::kDefault));
|
factor, Heap::HeapGrowingMode::kDefault));
|
||||||
|
|
||||||
factor = Min(factor, heap_controller.conservative_growing_factor_);
|
factor = Min(factor, V8HeapTrait::kConservativeGrowingFactor);
|
||||||
EXPECT_EQ(static_cast<size_t>(old_gen_size * factor + new_space_capacity),
|
EXPECT_EQ(static_cast<size_t>(old_gen_size * factor + new_space_capacity),
|
||||||
heap->heap_controller()->CalculateAllocationLimit(
|
V8Controller::CalculateAllocationLimit(
|
||||||
old_gen_size, max_old_generation_size, gc_speed, mutator_speed,
|
heap, old_gen_size, max_old_generation_size, new_space_capacity,
|
||||||
new_space_capacity, Heap::HeapGrowingMode::kSlow));
|
factor, Heap::HeapGrowingMode::kSlow));
|
||||||
|
|
||||||
factor = Min(factor, heap_controller.conservative_growing_factor_);
|
factor = Min(factor, V8HeapTrait::kConservativeGrowingFactor);
|
||||||
EXPECT_EQ(static_cast<size_t>(old_gen_size * factor + new_space_capacity),
|
EXPECT_EQ(static_cast<size_t>(old_gen_size * factor + new_space_capacity),
|
||||||
heap->heap_controller()->CalculateAllocationLimit(
|
V8Controller::CalculateAllocationLimit(
|
||||||
old_gen_size, max_old_generation_size, gc_speed, mutator_speed,
|
heap, old_gen_size, max_old_generation_size, new_space_capacity,
|
||||||
new_space_capacity, Heap::HeapGrowingMode::kConservative));
|
factor, Heap::HeapGrowingMode::kConservative));
|
||||||
|
|
||||||
factor = heap_controller.min_growing_factor_;
|
factor = V8HeapTrait::kMinGrowingFactor;
|
||||||
EXPECT_EQ(static_cast<size_t>(old_gen_size * factor + new_space_capacity),
|
EXPECT_EQ(static_cast<size_t>(old_gen_size * factor + new_space_capacity),
|
||||||
heap->heap_controller()->CalculateAllocationLimit(
|
V8Controller::CalculateAllocationLimit(
|
||||||
old_gen_size, max_old_generation_size, gc_speed, mutator_speed,
|
heap, old_gen_size, max_old_generation_size, new_space_capacity,
|
||||||
new_space_capacity, Heap::HeapGrowingMode::kMinimal));
|
factor, Heap::HeapGrowingMode::kMinimal));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(HeapControllerTest, MaxOldGenerationSize) {
|
TEST_F(MemoryControllerTest, MaxOldGenerationSize) {
|
||||||
HeapController heap_controller(i_isolate()->heap());
|
|
||||||
uint64_t configurations[][2] = {
|
uint64_t configurations[][2] = {
|
||||||
{0, HeapController::kMinSize},
|
{0, V8HeapTrait::kMinSize},
|
||||||
{512, HeapController::kMinSize},
|
{512, V8HeapTrait::kMinSize},
|
||||||
{1 * GB, 256 * Heap::kPointerMultiplier},
|
{1 * GB, 256 * Heap::kPointerMultiplier},
|
||||||
{2 * static_cast<uint64_t>(GB), 512 * Heap::kPointerMultiplier},
|
{2 * static_cast<uint64_t>(GB), 512 * Heap::kPointerMultiplier},
|
||||||
{4 * static_cast<uint64_t>(GB), HeapController::kMaxSize},
|
{4 * static_cast<uint64_t>(GB), V8HeapTrait::kMaxSize},
|
||||||
{8 * static_cast<uint64_t>(GB), HeapController::kMaxSize}};
|
{8 * static_cast<uint64_t>(GB), V8HeapTrait::kMaxSize}};
|
||||||
|
|
||||||
for (auto configuration : configurations) {
|
for (auto configuration : configurations) {
|
||||||
ASSERT_EQ(configuration[1],
|
ASSERT_EQ(configuration[1],
|
||||||
|
Loading…
Reference in New Issue
Block a user