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