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

Generated by: LCOV version 1.10