LCOV - code coverage report
Current view: top level - src/heap - heap-controller.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 34 40 85.0 %
Date: 2019-04-19 Functions: 5 5 100.0 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/heap/heap-controller.h"
       6             : 
       7             : #include "src/heap/spaces.h"
       8             : #include "src/isolate-inl.h"
       9             : 
      10             : namespace v8 {
      11             : namespace internal {
      12             : 
      13             : // Given GC speed in bytes per ms, the allocation throughput in bytes per ms
      14             : // (mutator speed), this function returns the heap growing factor that will
      15             : // achieve the target_mutator_utilization_ if the GC speed and the mutator speed
      16             : // remain the same until the next GC.
      17             : //
      18             : // For a fixed time-frame T = TM + TG, the mutator utilization is the ratio
      19             : // TM / (TM + TG), where TM is the time spent in the mutator and TG is the
      20             : // time spent in the garbage collector.
      21             : //
      22             : // Let MU be target_mutator_utilization_, the desired mutator utilization for
      23             : // the time-frame from the end of the current GC to the end of the next GC.
      24             : // Based on the MU we can compute the heap growing factor F as
      25             : //
      26             : // F = R * (1 - MU) / (R * (1 - MU) - MU), where R = gc_speed / mutator_speed.
      27             : //
      28             : // This formula can be derived as follows.
      29             : //
      30             : // F = Limit / Live by definition, where the Limit is the allocation limit,
      31             : // and the Live is size of live objects.
      32             : // Let’s assume that we already know the Limit. Then:
      33             : //   TG = Limit / gc_speed
      34             : //   TM = (TM + TG) * MU, by definition of MU.
      35             : //   TM = TG * MU / (1 - MU)
      36             : //   TM = Limit *  MU / (gc_speed * (1 - MU))
      37             : // On the other hand, if the allocation throughput remains constant:
      38             : //   Limit = Live + TM * allocation_throughput = Live + TM * mutator_speed
      39             : // Solving it for TM, we get
      40             : //   TM = (Limit - Live) / mutator_speed
      41             : // Combining the two equation for TM:
      42             : //   (Limit - Live) / mutator_speed = Limit * MU / (gc_speed * (1 - MU))
      43             : //   (Limit - Live) = Limit * MU * mutator_speed / (gc_speed * (1 - MU))
      44             : // substitute R = gc_speed / mutator_speed
      45             : //   (Limit - Live) = Limit * MU  / (R * (1 - MU))
      46             : // substitute F = Limit / Live
      47             : //   F - 1 = F * MU  / (R * (1 - MU))
      48             : //   F - F * MU / (R * (1 - MU)) = 1
      49             : //   F * (1 - MU / (R * (1 - MU))) = 1
      50             : //   F * (R * (1 - MU) - MU) / (R * (1 - MU)) = 1
      51             : //   F = R * (1 - MU) / (R * (1 - MU) - MU)
      52          10 : double MemoryController::GrowingFactor(double gc_speed, double mutator_speed,
      53             :                                        double max_factor) {
      54             :   DCHECK_LE(min_growing_factor_, max_factor);
      55             :   DCHECK_GE(max_growing_factor_, max_factor);
      56       69941 :   if (gc_speed == 0 || mutator_speed == 0) return max_factor;
      57             : 
      58       54627 :   const double speed_ratio = gc_speed / mutator_speed;
      59             : 
      60       54627 :   const double a = speed_ratio * (1 - target_mutator_utilization_);
      61             :   const double b = speed_ratio * (1 - target_mutator_utilization_) -
      62       54627 :                    target_mutator_utilization_;
      63             : 
      64             :   // The factor is a / b, but we need to check for small b first.
      65       54627 :   double factor = (a < b * max_factor) ? a / b : max_factor;
      66             :   factor = Min(factor, max_factor);
      67       54627 :   factor = Max(factor, min_growing_factor_);
      68          10 :   return factor;
      69             : }
      70             : 
      71       69931 : size_t MemoryController::CalculateAllocationLimit(
      72             :     size_t curr_size, size_t max_size, double max_factor, double gc_speed,
      73             :     double mutator_speed, size_t new_space_capacity,
      74             :     Heap::HeapGrowingMode growing_mode) {
      75             :   double factor = GrowingFactor(gc_speed, mutator_speed, max_factor);
      76             : 
      77       69931 :   if (FLAG_trace_gc_verbose) {
      78           0 :     Isolate::FromHeap(heap_)->PrintWithTimestamp(
      79             :         "%s factor %.1f based on mu=%.3f, speed_ratio=%.f "
      80             :         "(gc=%.f, mutator=%.f)\n",
      81           0 :         ControllerName(), factor, target_mutator_utilization_,
      82           0 :         gc_speed / mutator_speed, gc_speed, mutator_speed);
      83             :   }
      84             : 
      85       69931 :   if (growing_mode == Heap::HeapGrowingMode::kConservative ||
      86             :       growing_mode == Heap::HeapGrowingMode::kSlow) {
      87          68 :     factor = Min(factor, conservative_growing_factor_);
      88             :   }
      89             : 
      90       69931 :   if (growing_mode == Heap::HeapGrowingMode::kMinimal) {
      91        7310 :     factor = min_growing_factor_;
      92             :   }
      93             : 
      94       69931 :   if (FLAG_heap_growing_percent > 0) {
      95           0 :     factor = 1.0 + FLAG_heap_growing_percent / 100.0;
      96             :   }
      97             : 
      98       69931 :   CHECK_LT(1.0, factor);
      99       69931 :   CHECK_LT(0, curr_size);
     100       69931 :   uint64_t limit = static_cast<uint64_t>(curr_size * factor);
     101       69931 :   limit = Max(limit, static_cast<uint64_t>(curr_size) +
     102             :                          MinimumAllocationLimitGrowingStep(growing_mode));
     103       69931 :   limit += new_space_capacity;
     104             :   uint64_t halfway_to_the_max =
     105       69931 :       (static_cast<uint64_t>(curr_size) + max_size) / 2;
     106             :   size_t result = static_cast<size_t>(Min(limit, halfway_to_the_max));
     107             : 
     108       69931 :   if (FLAG_trace_gc_verbose) {
     109           0 :     Isolate::FromHeap(heap_)->PrintWithTimestamp(
     110             :         "%s Limit: old size: %" PRIuS " KB, new limit: %" PRIuS " KB (%.1f)\n",
     111           0 :         ControllerName(), curr_size / KB, result / KB, factor);
     112             :   }
     113             : 
     114       69931 :   return result;
     115             : }
     116             : 
     117        8291 : size_t MemoryController::MinimumAllocationLimitGrowingStep(
     118             :     Heap::HeapGrowingMode growing_mode) {
     119             :   const size_t kRegularAllocationLimitGrowingStep = 8;
     120             :   const size_t kLowMemoryAllocationLimitGrowingStep = 2;
     121             :   size_t limit = (Page::kPageSize > MB ? Page::kPageSize : MB);
     122       78222 :   return limit * (growing_mode == Heap::HeapGrowingMode::kConservative
     123             :                       ? kLowMemoryAllocationLimitGrowingStep
     124       78222 :                       : kRegularAllocationLimitGrowingStep);
     125             : }
     126             : 
     127       69932 : double HeapController::MaxGrowingFactor(size_t curr_max_size) {
     128             :   const double min_small_factor = 1.3;
     129             :   const double max_small_factor = 2.0;
     130             :   const double high_factor = 4.0;
     131             : 
     132       69932 :   size_t max_size_in_mb = curr_max_size / MB;
     133             :   max_size_in_mb = Max(max_size_in_mb, kMinSize);
     134             : 
     135             :   // If we are on a device with lots of memory, we allow a high heap
     136             :   // growing factor.
     137       69932 :   if (max_size_in_mb >= kMaxSize) {
     138             :     return high_factor;
     139             :   }
     140             : 
     141             :   DCHECK_GE(max_size_in_mb, kMinSize);
     142             :   DCHECK_LT(max_size_in_mb, kMaxSize);
     143             : 
     144             :   // On smaller devices we linearly scale the factor: (X-A)/(B-A)*(D-C)+C
     145       22719 :   double factor = (max_size_in_mb - kMinSize) *
     146       22719 :                       (max_small_factor - min_small_factor) /
     147             :                       (kMaxSize - kMinSize) +
     148       22719 :                   min_small_factor;
     149       22719 :   return factor;
     150             : }
     151             : 
     152             : }  // namespace internal
     153      122036 : }  // namespace v8

Generated by: LCOV version 1.10