#include "src/heap/heap-controller.h"
#include "src/execution/isolate-inl.h"
#include "src/heap/spaces.h"
#include "src/tracing/trace-event.h"
namespace v8 {
namespace internal {
template <typename Trait>
double MemoryController<Trait>::GrowingFactor(
Heap* heap, size_t max_heap_size, std::optional<double> gc_speed,
double mutator_speed, Heap::HeapGrowingMode growing_mode) {
const double max_factor =
MaxGrowingFactor(heap->physical_memory(), max_heap_size);
double factor = DynamicGrowingFactor(gc_speed, mutator_speed, max_factor);
switch (growing_mode) {
case Heap::HeapGrowingMode::kConservative:
case Heap::HeapGrowingMode::kSlow:
factor = std::min({factor, Trait::kConservativeGrowingFactor});
break;
case Heap::HeapGrowingMode::kMinimal:
factor = Trait::kMinGrowingFactor;
break;
case Heap::HeapGrowingMode::kDefault:
break;
}
if (v8_flags.heap_growing_percent > 0) {
factor = 1.0 + v8_flags.heap_growing_percent / 100.0;
}
if (V8_UNLIKELY(v8_flags.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.value_or(0) / mutator_speed, gc_speed.value_or(0),
mutator_speed);
}
return factor;
}
template <typename Trait>
double MemoryController<Trait>::MaxGrowingFactor(uint64_t physical_memory,
size_t max_heap_size) {
constexpr double kMinSmallFactor = 1.3;
constexpr double kMaxSmallFactor = 2.0;
constexpr double kHighFactor = 4.0;
if (max_heap_size >= Heap::DefaultMaxHeapSize(physical_memory)) {
return kHighFactor;
}
size_t max_size =
std::max({max_heap_size, Heap::DefaultMinHeapSize(physical_memory)});
DCHECK_GE(max_size, Heap::DefaultMinHeapSize(physical_memory));
DCHECK_LT(max_size, Heap::DefaultMaxHeapSize(physical_memory));
double factor = kMinSmallFactor +
(kMaxSmallFactor - kMinSmallFactor) *
(max_size - Heap::DefaultMinHeapSize(physical_memory)) /
(Heap::DefaultMaxHeapSize(physical_memory) -
Heap::DefaultMinHeapSize(physical_memory));
return factor;
}
template <typename Trait>
double MemoryController<Trait>::DynamicGrowingFactor(
std::optional<double> gc_speed, double mutator_speed, double max_factor) {
DCHECK_LE(Trait::kMinGrowingFactor, max_factor);
DCHECK_GE(Trait::kMaxGrowingFactor, max_factor);
if (!gc_speed || mutator_speed == 0) return max_factor;
const double speed_ratio = *gc_speed / mutator_speed;
const double a = speed_ratio * (1 - Trait::kTargetMutatorUtilization);
const double b = speed_ratio * (1 - Trait::kTargetMutatorUtilization) -
Trait::kTargetMutatorUtilization;
double factor = (a < b * max_factor) ? a / b : max_factor;
DCHECK_LE(factor, max_factor);
factor = std::max({factor, Trait::kMinGrowingFactor});
return factor;
}
template <typename Trait>
size_t MemoryController<Trait>::MinimumAllocationLimitGrowingStep(
Heap::HeapGrowingMode growing_mode) {
const size_t kRegularAllocationLimitGrowingStep = 8;
const size_t kLowMemoryAllocationLimitGrowingStep = 2;
size_t limit = (PageMetadata::kPageSize > MB ? PageMetadata::kPageSize : MB);
return limit * (growing_mode == Heap::HeapGrowingMode::kConservative
? kLowMemoryAllocationLimitGrowingStep
: kRegularAllocationLimitGrowingStep);
}
template <typename Trait>
size_t MemoryController<Trait>::BoundAllocationLimit(
Heap* heap, size_t current_size, uint64_t limit, size_t min_size,
size_t max_size, size_t new_space_capacity,
Heap::HeapGrowingMode growing_mode) {
CHECK_LT(0, current_size);
limit = std::max(limit, 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 uint64_t limit_or_halfway =
std::min<uint64_t>(limit, halfway_to_the_max);
const size_t result =
static_cast<size_t>(std::max<uint64_t>(limit_or_halfway, min_size));
if (V8_UNLIKELY(v8_flags.trace_gc_verbose)) {
Isolate::FromHeap(heap)->PrintWithTimestamp(
"[%s] Limit: old size: %zu KB, new limit: %zu KB\n", Trait::kName,
current_size / KB, result / KB);
}
return result;
}
template class V8_EXPORT_PRIVATE MemoryController<V8HeapTrait>;
template class V8_EXPORT_PRIVATE MemoryController<GlobalMemoryTrait>;
}
}