// Copyright 2012 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #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, double gc_speed, double mutator_speed) { … } template <typename Trait> double MemoryController<Trait>::MaxGrowingFactor(size_t max_heap_size) { … } // 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 // achieve the target_mutator_utilization_ if the GC speed and the mutator speed // remain the same until the next GC. // // For a fixed time-frame T = TM + TG, the mutator utilization is the ratio // TM / (TM + TG), where TM is the time spent in the mutator and TG is the // time spent in the garbage collector. // // Let MU be target_mutator_utilization_, the desired mutator utilization for // the time-frame from the end of the current GC to the end of the next GC. // Based on the MU we can compute the heap growing factor F as // // F = R * (1 - MU) / (R * (1 - MU) - MU), where R = gc_speed / mutator_speed. // // This formula can be derived as follows. // // F = Limit / Live by definition, where the Limit is the allocation limit, // and the Live is size of live objects. // Let’s assume that we already know the Limit. Then: // TG = Limit / gc_speed // TM = (TM + TG) * MU, by definition of MU. // TM = TG * MU / (1 - MU) // TM = Limit * MU / (gc_speed * (1 - MU)) // On the other hand, if the allocation throughput remains constant: // Limit = Live + TM * allocation_throughput = Live + TM * mutator_speed // Solving it for TM, we get // TM = (Limit - Live) / mutator_speed // Combining the two equation for TM: // (Limit - Live) / mutator_speed = Limit * MU / (gc_speed * (1 - MU)) // (Limit - Live) = Limit * MU * mutator_speed / (gc_speed * (1 - MU)) // substitute R = gc_speed / mutator_speed // (Limit - Live) = Limit * MU / (R * (1 - MU)) // substitute F = Limit / Live // F - 1 = F * MU / (R * (1 - MU)) // F - F * 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) / (R * (1 - MU) - MU) template <typename Trait> double MemoryController<Trait>::DynamicGrowingFactor(double gc_speed, double mutator_speed, double max_factor) { … } template <typename Trait> size_t MemoryController<Trait>::MinimumAllocationLimitGrowingStep( Heap::HeapGrowingMode growing_mode) { … } template <typename Trait> size_t MemoryController<Trait>::CalculateAllocationLimit( Heap* heap, size_t current_size, size_t min_size, size_t max_size, size_t new_space_capacity, double factor, Heap::HeapGrowingMode growing_mode) { … } template class V8_EXPORT_PRIVATE MemoryController<V8HeapTrait>; template class V8_EXPORT_PRIVATE MemoryController<GlobalMemoryTrait>; } // namespace internal } // namespace v8