| OLD | NEW | 
|    1 // Copyright 2015 the V8 project authors. All rights reserved. |    1 // Copyright 2015 the V8 project authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #ifndef V8_HEAP_memory_reducer_H |    5 #ifndef V8_HEAP_memory_reducer_H | 
|    6 #define V8_HEAP_memory_reducer_H |    6 #define V8_HEAP_memory_reducer_H | 
|    7  |    7  | 
|    8 #include "include/v8-platform.h" |    8 #include "include/v8-platform.h" | 
|    9 #include "src/base/macros.h" |    9 #include "src/base/macros.h" | 
|   10 #include "src/cancelable-task.h" |   10 #include "src/cancelable-task.h" | 
|   11  |   11  | 
|   12 namespace v8 { |   12 namespace v8 { | 
|   13 namespace internal { |   13 namespace internal { | 
|   14  |   14  | 
|   15 class Heap; |   15 class Heap; | 
|   16  |   16  | 
|   17  |   17  | 
|   18 // The goal of the MemoryReducer class is to detect transition of the mutator |   18 // The goal of the MemoryReducer class is to detect transition of the mutator | 
|   19 // from high allocation phase to low allocation phase and to collect potential |   19 // from high allocation phase to low allocation phase and to collect potential | 
|   20 // garbage created in the high allocation phase. |   20 // garbage created in the high allocation phase. | 
|   21 // |   21 // | 
|   22 // The class implements an automaton with the following states and transitions. |   22 // The class implements an automaton with the following states and transitions. | 
|   23 // |   23 // | 
|   24 // States: |   24 // States: | 
|   25 // - DONE |   25 // - DONE <last_gc_time_ms> | 
|   26 // - WAIT <started_gcs> <next_gc_start_ms> |   26 // - WAIT <started_gcs> <next_gc_start_ms> <last_gc_time_ms> | 
|   27 // - RUN <started_gcs> |   27 // - RUN <started_gcs> <last_gc_time_ms> | 
|   28 // The <started_gcs> is an integer in range from 0..kMaxNumberOfGCs that stores |   28 // The <started_gcs> is an integer in range from 0..kMaxNumberOfGCs that stores | 
|   29 // the number of GCs initiated by the MemoryReducer since it left the DONE |   29 // the number of GCs initiated by the MemoryReducer since it left the DONE | 
|   30 // state. |   30 // state. | 
|   31 // The <next_gc_start_ms> is a double that stores the earliest time the next GC |   31 // The <next_gc_start_ms> is a double that stores the earliest time the next GC | 
|   32 // can be initiated by the MemoryReducer. |   32 // can be initiated by the MemoryReducer. | 
 |   33 // The <last_gc_start_ms> is a double that stores the time of the last full GC. | 
|   33 // The DONE state means that the MemoryReducer is not active. |   34 // The DONE state means that the MemoryReducer is not active. | 
|   34 // The WAIT state means that the MemoryReducer is waiting for mutator allocation |   35 // The WAIT state means that the MemoryReducer is waiting for mutator allocation | 
|   35 // rate to drop. The check for the allocation rate happens in the timer task |   36 // rate to drop. The check for the allocation rate happens in the timer task | 
|   36 // callback. |   37 // callback. If the allocation rate does not drop in watchdog_delay_ms since | 
 |   38 // the last GC then transition to the RUN state is forced. | 
|   37 // The RUN state means that the MemoryReducer started incremental marking and is |   39 // The RUN state means that the MemoryReducer started incremental marking and is | 
|   38 // waiting for it to finish. Incremental marking steps are performed as usual |   40 // waiting for it to finish. Incremental marking steps are performed as usual | 
|   39 // in the idle notification and in the mutator. |   41 // in the idle notification and in the mutator. | 
|   40 // |   42 // | 
|   41 // Transitions: |   43 // Transitions: | 
|   42 // DONE -> WAIT 0 (now_ms + long_delay_ms) happens: |   44 // DONE t -> WAIT 0 (now_ms + long_delay_ms) t' happens: | 
|   43 //     - on context disposal, |   45 //     - on context disposal. | 
|   44 //     - at the end of mark-compact GC initiated by the mutator. |   46 //     - at the end of mark-compact GC initiated by the mutator. | 
|   45 // This signals that there is potential garbage to be collected. |   47 // This signals that there is potential garbage to be collected. | 
|   46 // |   48 // | 
|   47 // WAIT n x -> WAIT n (now_ms + long_delay_ms) happens: |   49 // WAIT n x t -> WAIT n (now_ms + long_delay_ms) t' happens: | 
|   48 //     - on mark-compact GC initiated by the mutator, |   50 //     - on mark-compact GC initiated by the mutator, | 
|   49 //     - in the timer callback if the mutator allocation rate is high or |   51 //     - in the timer callback if the mutator allocation rate is high or | 
|   50 //       incremental GC is in progress. |   52 //       incremental GC is in progress or (now_ms - t < watchdog_delay_ms) | 
|   51 // |   53 // | 
|   52 // WAIT n x -> WAIT (n+1) happens: |   54 // WAIT n x t -> WAIT (n+1) t happens: | 
|   53 //     - on background idle notification, which signals that we can start |   55 //     - on background idle notification, which signals that we can start | 
|   54 //       incremental marking even if the allocation rate is high. |   56 //       incremental marking even if the allocation rate is high. | 
|   55 // The MemoryReducer starts incremental marking on this transition but still |   57 // The MemoryReducer starts incremental marking on this transition but still | 
|   56 // has a pending timer task. |   58 // has a pending timer task. | 
|   57 // |   59 // | 
|   58 // WAIT n x -> DONE happens: |   60 // WAIT n x t -> DONE t happens: | 
|   59 //     - in the timer callback if n >= kMaxNumberOfGCs. |   61 //     - in the timer callback if n >= kMaxNumberOfGCs. | 
|   60 // |   62 // | 
|   61 // WAIT n x -> RUN (n+1) happens: |   63 // WAIT n x t -> RUN (n+1) t happens: | 
|   62 //     - in the timer callback if the mutator allocation rate is low |   64 //     - in the timer callback if the mutator allocation rate is low | 
|   63 //       and now_ms >= x and there is no incremental GC in progress. |   65 //       and now_ms >= x and there is no incremental GC in progress. | 
 |   66 //     - in the timer callback if (now_ms - t > watchdog_delay_ms) and | 
 |   67 //       and now_ms >= x and there is no incremental GC in progress. | 
|   64 // The MemoryReducer starts incremental marking on this transition. |   68 // The MemoryReducer starts incremental marking on this transition. | 
|   65 // |   69 // | 
|   66 // RUN n -> DONE happens: |   70 // RUN n t -> DONE now_ms happens: | 
|   67 //     - at end of the incremental GC initiated by the MemoryReducer if |   71 //     - at end of the incremental GC initiated by the MemoryReducer if | 
|   68 //       (n > 1 and there is no more garbage to be collected) or |   72 //       (n > 1 and there is no more garbage to be collected) or | 
|   69 //       n == kMaxNumberOfGCs. |   73 //       n == kMaxNumberOfGCs. | 
|   70 // RUN n -> WAIT n (now_ms + short_delay_ms) happens: |   74 // RUN n t -> WAIT n (now_ms + short_delay_ms) now_ms happens: | 
|   71 //     - at end of the incremental GC initiated by the MemoryReducer if |   75 //     - at end of the incremental GC initiated by the MemoryReducer if | 
|   72 //       (n == 1 or there is more garbage to be collected) and |   76 //       (n == 1 or there is more garbage to be collected) and | 
|   73 //       n < kMaxNumberOfGCs. |   77 //       n < kMaxNumberOfGCs. | 
|   74 // |   78 // | 
|   75 // now_ms is the current time, long_delay_ms and short_delay_ms are constants. |   79 // now_ms is the current time, | 
 |   80 // t' is t if the current event is not a GC event and is now_ms otherwise, | 
 |   81 // long_delay_ms, short_delay_ms, and watchdog_delay_ms are constants. | 
|   76 class MemoryReducer { |   82 class MemoryReducer { | 
|   77  public: |   83  public: | 
|   78   enum Action { kDone, kWait, kRun }; |   84   enum Action { kDone, kWait, kRun }; | 
|   79  |   85  | 
|   80   struct State { |   86   struct State { | 
|   81     State(Action action, int started_gcs, double next_gc_start_ms) |   87     State(Action action, int started_gcs, double next_gc_start_ms, | 
 |   88           double last_gc_time_ms) | 
|   82         : action(action), |   89         : action(action), | 
|   83           started_gcs(started_gcs), |   90           started_gcs(started_gcs), | 
|   84           next_gc_start_ms(next_gc_start_ms) {} |   91           next_gc_start_ms(next_gc_start_ms), | 
 |   92           last_gc_time_ms(last_gc_time_ms) {} | 
|   85     Action action; |   93     Action action; | 
|   86     int started_gcs; |   94     int started_gcs; | 
|   87     double next_gc_start_ms; |   95     double next_gc_start_ms; | 
 |   96     double last_gc_time_ms; | 
|   88   }; |   97   }; | 
|   89  |   98  | 
|   90   enum EventType { |   99   enum EventType { | 
|   91     kTimer, |  100     kTimer, | 
|   92     kMarkCompact, |  101     kMarkCompact, | 
|   93     kContextDisposed, |  102     kContextDisposed, | 
|   94     kBackgroundIdleNotification |  103     kBackgroundIdleNotification | 
|   95   }; |  104   }; | 
|   96  |  105  | 
|   97   struct Event { |  106   struct Event { | 
|   98     EventType type; |  107     EventType type; | 
|   99     double time_ms; |  108     double time_ms; | 
|  100     bool low_allocation_rate; |  109     bool low_allocation_rate; | 
|  101     bool next_gc_likely_to_collect_more; |  110     bool next_gc_likely_to_collect_more; | 
|  102     bool can_start_incremental_gc; |  111     bool can_start_incremental_gc; | 
|  103   }; |  112   }; | 
|  104  |  113  | 
|  105   explicit MemoryReducer(Heap* heap) : heap_(heap), state_(kDone, 0, 0.0) {} |  114   explicit MemoryReducer(Heap* heap) | 
 |  115       : heap_(heap), state_(kDone, 0, 0.0, 0.0) {} | 
|  106   // Callbacks. |  116   // Callbacks. | 
|  107   void NotifyMarkCompact(const Event& event); |  117   void NotifyMarkCompact(const Event& event); | 
|  108   void NotifyContextDisposed(const Event& event); |  118   void NotifyContextDisposed(const Event& event); | 
|  109   void NotifyBackgroundIdleNotification(const Event& event); |  119   void NotifyBackgroundIdleNotification(const Event& event); | 
|  110   // The step function that computes the next state from the current state and |  120   // The step function that computes the next state from the current state and | 
|  111   // the incoming event. |  121   // the incoming event. | 
|  112   static State Step(const State& state, const Event& event); |  122   static State Step(const State& state, const Event& event); | 
|  113   // Posts a timer task that will call NotifyTimer after the given delay. |  123   // Posts a timer task that will call NotifyTimer after the given delay. | 
|  114   void ScheduleTimer(double delay_ms); |  124   void ScheduleTimer(double delay_ms); | 
|  115   void TearDown(); |  125   void TearDown(); | 
|  116   static const int kLongDelayMs; |  126   static const int kLongDelayMs; | 
|  117   static const int kShortDelayMs; |  127   static const int kShortDelayMs; | 
 |  128   static const int kWatchdogDelayMs; | 
|  118   static const int kMaxNumberOfGCs; |  129   static const int kMaxNumberOfGCs; | 
|  119  |  130  | 
|  120   Heap* heap() { return heap_; } |  131   Heap* heap() { return heap_; } | 
|  121  |  132  | 
|  122  private: |  133  private: | 
|  123   class TimerTask : public v8::internal::CancelableTask { |  134   class TimerTask : public v8::internal::CancelableTask { | 
|  124    public: |  135    public: | 
|  125     explicit TimerTask(MemoryReducer* memory_reducer); |  136     explicit TimerTask(MemoryReducer* memory_reducer); | 
|  126  |  137  | 
|  127    private: |  138    private: | 
|  128     // v8::internal::CancelableTask overrides. |  139     // v8::internal::CancelableTask overrides. | 
|  129     void RunInternal() override; |  140     void RunInternal() override; | 
|  130     MemoryReducer* memory_reducer_; |  141     MemoryReducer* memory_reducer_; | 
|  131     DISALLOW_COPY_AND_ASSIGN(TimerTask); |  142     DISALLOW_COPY_AND_ASSIGN(TimerTask); | 
|  132   }; |  143   }; | 
|  133  |  144  | 
|  134   void NotifyTimer(const Event& event); |  145   void NotifyTimer(const Event& event); | 
|  135  |  146  | 
 |  147   static bool WatchdogGC(const State& state, const Event& event); | 
 |  148  | 
|  136   Heap* heap_; |  149   Heap* heap_; | 
|  137   State state_; |  150   State state_; | 
|  138  |  | 
|  139   DISALLOW_COPY_AND_ASSIGN(MemoryReducer); |  151   DISALLOW_COPY_AND_ASSIGN(MemoryReducer); | 
|  140 }; |  152 }; | 
|  141  |  153  | 
|  142 }  // namespace internal |  154 }  // namespace internal | 
|  143 }  // namespace v8 |  155 }  // namespace v8 | 
|  144  |  156  | 
|  145 #endif  // V8_HEAP_memory_reducer_H |  157 #endif  // V8_HEAP_memory_reducer_H | 
| OLD | NEW |