| Index: src/heap/memory-reducer.h
|
| diff --git a/src/heap/memory-reducer.h b/src/heap/memory-reducer.h
|
| index 3d281d302edba94cddcd9f518ea41bb2fae3f0e9..c96005380cd030841b07cf30830999538a5aa6ea 100644
|
| --- a/src/heap/memory-reducer.h
|
| +++ b/src/heap/memory-reducer.h
|
| @@ -22,69 +22,78 @@ class Heap;
|
| // The class implements an automaton with the following states and transitions.
|
| //
|
| // States:
|
| -// - DONE
|
| -// - WAIT <started_gcs> <next_gc_start_ms>
|
| -// - RUN <started_gcs>
|
| +// - DONE <last_gc_time_ms>
|
| +// - WAIT <started_gcs> <next_gc_start_ms> <last_gc_time_ms>
|
| +// - RUN <started_gcs> <last_gc_time_ms>
|
| // The <started_gcs> is an integer in range from 0..kMaxNumberOfGCs that stores
|
| // the number of GCs initiated by the MemoryReducer since it left the DONE
|
| // state.
|
| // The <next_gc_start_ms> is a double that stores the earliest time the next GC
|
| // can be initiated by the MemoryReducer.
|
| +// The <last_gc_start_ms> is a double that stores the time of the last full GC.
|
| // The DONE state means that the MemoryReducer is not active.
|
| // The WAIT state means that the MemoryReducer is waiting for mutator allocation
|
| // rate to drop. The check for the allocation rate happens in the timer task
|
| -// callback.
|
| +// callback. If the allocation rate does not drop in watchdog_delay_ms since
|
| +// the last GC then transition to the RUN state is forced.
|
| // The RUN state means that the MemoryReducer started incremental marking and is
|
| // waiting for it to finish. Incremental marking steps are performed as usual
|
| // in the idle notification and in the mutator.
|
| //
|
| // Transitions:
|
| -// DONE -> WAIT 0 (now_ms + long_delay_ms) happens:
|
| -// - on context disposal,
|
| +// DONE t -> WAIT 0 (now_ms + long_delay_ms) t' happens:
|
| +// - on context disposal.
|
| // - at the end of mark-compact GC initiated by the mutator.
|
| // This signals that there is potential garbage to be collected.
|
| //
|
| -// WAIT n x -> WAIT n (now_ms + long_delay_ms) happens:
|
| +// WAIT n x t -> WAIT n (now_ms + long_delay_ms) t' happens:
|
| // - on mark-compact GC initiated by the mutator,
|
| // - in the timer callback if the mutator allocation rate is high or
|
| -// incremental GC is in progress.
|
| +// incremental GC is in progress or (now_ms - t < watchdog_delay_ms)
|
| //
|
| -// WAIT n x -> WAIT (n+1) happens:
|
| +// WAIT n x t -> WAIT (n+1) t happens:
|
| // - on background idle notification, which signals that we can start
|
| // incremental marking even if the allocation rate is high.
|
| // The MemoryReducer starts incremental marking on this transition but still
|
| // has a pending timer task.
|
| //
|
| -// WAIT n x -> DONE happens:
|
| +// WAIT n x t -> DONE t happens:
|
| // - in the timer callback if n >= kMaxNumberOfGCs.
|
| //
|
| -// WAIT n x -> RUN (n+1) happens:
|
| +// WAIT n x t -> RUN (n+1) t happens:
|
| // - in the timer callback if the mutator allocation rate is low
|
| // and now_ms >= x and there is no incremental GC in progress.
|
| +// - in the timer callback if (now_ms - t > watchdog_delay_ms) and
|
| +// and now_ms >= x and there is no incremental GC in progress.
|
| // The MemoryReducer starts incremental marking on this transition.
|
| //
|
| -// RUN n -> DONE happens:
|
| +// RUN n t -> DONE now_ms happens:
|
| // - at end of the incremental GC initiated by the MemoryReducer if
|
| // (n > 1 and there is no more garbage to be collected) or
|
| // n == kMaxNumberOfGCs.
|
| -// RUN n -> WAIT n (now_ms + short_delay_ms) happens:
|
| +// RUN n t -> WAIT n (now_ms + short_delay_ms) now_ms happens:
|
| // - at end of the incremental GC initiated by the MemoryReducer if
|
| // (n == 1 or there is more garbage to be collected) and
|
| // n < kMaxNumberOfGCs.
|
| //
|
| -// now_ms is the current time, long_delay_ms and short_delay_ms are constants.
|
| +// now_ms is the current time,
|
| +// t' is t if the current event is not a GC event and is now_ms otherwise,
|
| +// long_delay_ms, short_delay_ms, and watchdog_delay_ms are constants.
|
| class MemoryReducer {
|
| public:
|
| enum Action { kDone, kWait, kRun };
|
|
|
| struct State {
|
| - State(Action action, int started_gcs, double next_gc_start_ms)
|
| + State(Action action, int started_gcs, double next_gc_start_ms,
|
| + double last_gc_time_ms)
|
| : action(action),
|
| started_gcs(started_gcs),
|
| - next_gc_start_ms(next_gc_start_ms) {}
|
| + next_gc_start_ms(next_gc_start_ms),
|
| + last_gc_time_ms(last_gc_time_ms) {}
|
| Action action;
|
| int started_gcs;
|
| double next_gc_start_ms;
|
| + double last_gc_time_ms;
|
| };
|
|
|
| enum EventType {
|
| @@ -102,7 +111,8 @@ class MemoryReducer {
|
| bool can_start_incremental_gc;
|
| };
|
|
|
| - explicit MemoryReducer(Heap* heap) : heap_(heap), state_(kDone, 0, 0.0) {}
|
| + explicit MemoryReducer(Heap* heap)
|
| + : heap_(heap), state_(kDone, 0, 0.0, 0.0) {}
|
| // Callbacks.
|
| void NotifyMarkCompact(const Event& event);
|
| void NotifyContextDisposed(const Event& event);
|
| @@ -115,6 +125,7 @@ class MemoryReducer {
|
| void TearDown();
|
| static const int kLongDelayMs;
|
| static const int kShortDelayMs;
|
| + static const int kWatchdogDelayMs;
|
| static const int kMaxNumberOfGCs;
|
|
|
| Heap* heap() { return heap_; }
|
| @@ -133,9 +144,10 @@ class MemoryReducer {
|
|
|
| void NotifyTimer(const Event& event);
|
|
|
| + static bool WatchdogGC(const State& state, const Event& event);
|
| +
|
| Heap* heap_;
|
| State state_;
|
| -
|
| DISALLOW_COPY_AND_ASSIGN(MemoryReducer);
|
| };
|
|
|
|
|