Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(966)

Side by Side Diff: src/heap/cleanup-gc.cc

Issue 1218863002: Replace reduce-memory mode in idle notification with delayed clean-up GC. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Allow to start GC if fragmentation is high even Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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/flags.h"
6 #include "src/heap/cleanup-gc.h"
7 #include "src/heap/heap.h"
8 #include "src/utils.h"
9 #include "src/v8.h"
10
11 namespace v8 {
12 namespace internal {
13
14 const int CleanupGC::kLongDelayMs = 5000;
15 const int CleanupGC::kShortDelayMs = 500;
16 const int CleanupGC::kMaxNumberOfGCs = 3;
17
18
19 void CleanupGC::TimerTask::Run() {
20 Heap* heap = cleanup_gc_->heap();
21 Event event;
22 event.type = kTimer;
23 event.time_ms = heap->MonotonicallyIncreasingTimeInMs();
24 event.high_fragmentation = heap->HasHighFragmentation();
25 event.low_allocation_rate = heap->HasLowAllocationRate();
26 event.incremental_gc_in_progress = !heap->incremental_marking()->IsStopped();
27 cleanup_gc_->NotifyTimer(event);
28 }
29
30
31 void CleanupGC::NotifyTimer(const Event& event) {
32 DCHECK_EQ(kTimer, event.type);
33 DCHECK_EQ(kWait, state_.action);
34 state_ = Step(state_, event);
35 if (state_.action == kRun) {
36 DCHECK(heap()->incremental_marking()->IsStopped());
37 DCHECK(FLAG_incremental_marking);
38 heap()->incremental_marking()->Start(Heap::kReduceMemoryFootprintMask);
39 if (FLAG_trace_gc_verbose) {
40 PrintIsolate(heap()->isolate(), "Clean-up GC: started #%d\n",
41 state_.started_gcs);
42 }
43 } else if (state_.action == kWait) {
44 // Re-schedule the timer.
45 ScheduleTimer(state_.next_gc_start_ms - event.time_ms);
46 if (FLAG_trace_gc_verbose) {
47 PrintIsolate(heap()->isolate(), "Clean-up GC: wait for %.f ms",
48 state_.next_gc_start_ms - event.time_ms);
49 }
50 }
51 }
52
53
54 void CleanupGC::NotifyMarkCompact(const Event& event) {
55 DCHECK_EQ(kMarkCompact, event.type);
56 Action old_action = state_.action;
57 state_ = Step(state_, event);
58 if (old_action != kWait && state_.action == kWait) {
59 // If we are transitioning to the WAIT state, start the timer.
60 ScheduleTimer(state_.next_gc_start_ms - event.time_ms);
61 }
62 if (old_action == kRun) {
63 if (FLAG_trace_gc_verbose) {
64 PrintIsolate(heap()->isolate(), "Clean-up GC: finished #%d (%s)\n",
65 state_.started_gcs,
66 state_.action == kWait ? "will do more" : "done");
67 }
68 }
69 }
70
71
72 void CleanupGC::NotifyScavenge(const Event& event) {
73 DCHECK_EQ(kScavenge, event.type);
74 state_ = Step(state_, event);
75 }
76
77
78 void CleanupGC::NotifyContextDisposed(const Event& event) {
79 DCHECK_EQ(kContextDisposed, event.type);
80 Action old_action = state_.action;
81 state_ = Step(state_, event);
82 if (old_action != kWait && state_.action == kWait) {
83 // If we are transitioning to the WAIT state, start the timer.
84 ScheduleTimer(state_.next_gc_start_ms - event.time_ms);
85 }
86 }
87
88
89 // For specification of this function see the comment for CleanupGC class.
90 CleanupGC::State CleanupGC::Step(const State& state, const Event& event) {
91 if (!FLAG_incremental_marking) {
92 return State(kDone, 0, 0);
93 }
94 switch (state.action) {
95 case kDone:
96 if (event.type == kScavenge || event.type == kTimer) {
97 return state;
98 } else {
99 DCHECK(event.type == kContextDisposed || event.type == kMarkCompact);
100 return State(kWait, 0, event.time_ms + kLongDelayMs);
101 }
102 case kWait:
103 if (event.type == kContextDisposed) {
104 return state;
105 } else if (event.type == kTimer && !event.incremental_gc_in_progress &&
106 (event.low_allocation_rate || event.high_fragmentation)) {
107 if (state.next_gc_start_ms <= event.time_ms) {
108 return State(kRun, state.started_gcs + 1, 0.0);
109 } else {
110 return state;
111 }
112 } else {
113 return State(kWait, state.started_gcs, event.time_ms + kLongDelayMs);
114 }
115 case kRun:
116 if (event.type != kMarkCompact) {
117 return state;
118 } else {
119 if (state.started_gcs < kMaxNumberOfGCs &&
120 (event.next_gc_likely_to_collect_more || state.started_gcs == 1)) {
121 return State(kWait, state.started_gcs, event.time_ms + kShortDelayMs);
122 } else {
123 return State(kDone, 0, 0.0);
124 }
125 }
126 }
127 UNREACHABLE();
128 return State(kDone, 0, 0); // Make the compiler happy.
129 }
130
131
132 void CleanupGC::ScheduleTimer(double delay_ms) {
Hannes Payer (out of office) 2015/07/01 12:03:16 Can we DCHECK that delay_ms is always positive.
ulan 2015/07/01 12:51:48 Done.
133 // Leave some room for precision error in task scheduler.
134 const double kSlackMs = 100;
135 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap()->isolate());
136 V8::GetCurrentPlatform()->CallDelayedOnForegroundThread(
137 isolate, new CleanupGC::TimerTask(this), (delay_ms + kSlackMs) / 1000.0);
Hannes Payer (out of office) 2015/07/01 12:03:16 where is the delete?
ulan 2015/07/01 12:51:48 Platform will delete it.
138 }
139
140 } // internal
141 } // v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698