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

Side by Side Diff: chrome/browser/sync_file_system/sync_process_runner.cc

Issue 386523002: [SyncFS] Refine SyncProcessRunner's throttling algorithm for parallel task support (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/sync_file_system/sync_process_runner.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium 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 #include "chrome/browser/sync_file_system/sync_process_runner.h" 5 #include "chrome/browser/sync_file_system/sync_process_runner.h"
6 6
7 #include "base/format_macros.h" 7 #include "base/format_macros.h"
8 #include "chrome/browser/sync_file_system/logger.h" 8 #include "chrome/browser/sync_file_system/logger.h"
9 9
10 namespace sync_file_system { 10 namespace sync_file_system {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 SyncProcessRunner::SyncProcessRunner( 62 SyncProcessRunner::SyncProcessRunner(
63 const std::string& name, 63 const std::string& name,
64 Client* client, 64 Client* client,
65 scoped_ptr<TimerHelper> timer_helper, 65 scoped_ptr<TimerHelper> timer_helper,
66 int max_parallel_task) 66 int max_parallel_task)
67 : name_(name), 67 : name_(name),
68 client_(client), 68 client_(client),
69 max_parallel_task_(max_parallel_task), 69 max_parallel_task_(max_parallel_task),
70 running_tasks_(0), 70 running_tasks_(0),
71 timer_helper_(timer_helper.Pass()), 71 timer_helper_(timer_helper.Pass()),
72 current_delay_(0),
73 last_delay_(0),
74 pending_changes_(0), 72 pending_changes_(0),
75 factory_(this) { 73 factory_(this) {
76 DCHECK_LE(1, max_parallel_task_); 74 DCHECK_LE(1, max_parallel_task_);
77 75
78 DCHECK_EQ(1, max_parallel_task_) 76 DCHECK_EQ(1, max_parallel_task_)
79 << "Parellel task execution is not yet implemented."; 77 << "Parellel task execution is not yet implemented.";
80 if (!timer_helper_) 78 if (!timer_helper_)
81 timer_helper_.reset(new BaseTimerHelper); 79 timer_helper_.reset(new BaseTimerHelper);
82 } 80 }
83 81
84 SyncProcessRunner::~SyncProcessRunner() {} 82 SyncProcessRunner::~SyncProcessRunner() {}
85 83
86 void SyncProcessRunner::Schedule() { 84 void SyncProcessRunner::Schedule() {
85 if (running_tasks_ >= max_parallel_task_)
86 return;
87
87 int64 delay = kSyncDelayInMilliseconds; 88 int64 delay = kSyncDelayInMilliseconds;
88 if (pending_changes_ == 0) { 89 if (pending_changes_ == 0) {
89 ScheduleInternal(kSyncDelayMaxInMilliseconds); 90 ScheduleInternal(kSyncDelayMaxInMilliseconds);
90 return; 91 return;
91 } 92 }
92 switch (GetServiceState()) { 93 switch (GetServiceState()) {
93 case SYNC_SERVICE_RUNNING: 94 case SYNC_SERVICE_RUNNING:
95 ResetThrottling();
94 if (pending_changes_ > kPendingChangeThresholdForFastSync) 96 if (pending_changes_ > kPendingChangeThresholdForFastSync)
95 delay = kSyncDelayFastInMilliseconds; 97 ScheduleInternal(kSyncDelayFastInMilliseconds);
96 else 98 else
97 delay = kSyncDelayInMilliseconds; 99 ScheduleInternal(kSyncDelayInMilliseconds);
98 break; 100 return;
99 101
100 case SYNC_SERVICE_TEMPORARY_UNAVAILABLE: 102 case SYNC_SERVICE_TEMPORARY_UNAVAILABLE:
101 delay = kSyncDelaySlowInMilliseconds; 103 ThrottleSync(kSyncDelaySlowInMilliseconds);
102 if (last_delay_ >= kSyncDelaySlowInMilliseconds) 104 ScheduleInternal(kSyncDelaySlowInMilliseconds);
103 delay = last_delay_ * 2; 105 return;
104 if (delay >= kSyncDelayMaxInMilliseconds)
105 delay = kSyncDelayMaxInMilliseconds;
106 break;
107 106
108 case SYNC_SERVICE_AUTHENTICATION_REQUIRED: 107 case SYNC_SERVICE_AUTHENTICATION_REQUIRED:
109 case SYNC_SERVICE_DISABLED: 108 case SYNC_SERVICE_DISABLED:
110 delay = kSyncDelayMaxInMilliseconds; 109 ThrottleSync(kSyncDelaySlowInMilliseconds);
111 break; 110 ScheduleInternal(kSyncDelayMaxInMilliseconds);
111 return;
112 } 112 }
113 ScheduleInternal(delay); 113
114 NOTREACHED();
115 ScheduleInternal(kSyncDelayMaxInMilliseconds);
114 } 116 }
115 117
116 void SyncProcessRunner::ScheduleIfNotRunning() { 118 void SyncProcessRunner::ThrottleSync(int64 base_delay) {
117 if (!timer_helper_->IsRunning()) 119 base::TimeTicks now = timer_helper_->Now();
118 Schedule(); 120 base::TimeDelta elapsed = std::min(now, throttle_until_) - throttle_from_;
121 DCHECK(base::TimeDelta() <= elapsed);
122
123 throttle_from_ = now;
124 // Extend throttling duration by twice the elapsed time.
125 // That is, if the backoff repeats in a short period, the throttling period
126 // doesn't grow exponentially. If the backoff happens on the end of
127 // throttling period, it causes another throttling period that is twice as
128 // long as previous.
129 base::TimeDelta base_delay_delta =
130 base::TimeDelta::FromMilliseconds(base_delay);
131 const base::TimeDelta max_delay =
132 base::TimeDelta::FromMilliseconds(kSyncDelayMaxInMilliseconds);
133 throttle_until_ =
134 std::min(now + max_delay,
135 std::max(now + base_delay_delta, throttle_until_ + 2 * elapsed));
136 }
137
138 void SyncProcessRunner::ResetOldThrottling() {
nhiroki 2014/07/10 08:17:21 This is not used in this CL.
tzik 2014/07/11 06:00:48 I forgot to call this. Now it's used in Finished()
139 if (throttle_until_ < base::TimeTicks::Now())
140 ResetThrottling();
141 }
142
143 void SyncProcessRunner::ResetThrottling() {
144 throttle_from_ = base::TimeTicks();
145 throttle_until_ = base::TimeTicks();
119 } 146 }
120 147
121 void SyncProcessRunner::OnChangesUpdated( 148 void SyncProcessRunner::OnChangesUpdated(
122 int64 pending_changes) { 149 int64 pending_changes) {
123 DCHECK_GE(pending_changes, 0); 150 DCHECK_GE(pending_changes, 0);
124 int64 old_pending_changes = pending_changes_; 151 int64 old_pending_changes = pending_changes_;
125 pending_changes_ = pending_changes; 152 pending_changes_ = pending_changes;
126 if (old_pending_changes != pending_changes) { 153 if (old_pending_changes != pending_changes) {
127 if (pending_changes == 0) 154 if (pending_changes == 0)
128 client_->OnSyncIdle(); 155 client_->OnSyncIdle();
(...skipping 11 matching lines...) Expand all
140 SyncServiceState SyncProcessRunner::GetServiceState() { 167 SyncServiceState SyncProcessRunner::GetServiceState() {
141 return client_->GetSyncServiceState(); 168 return client_->GetSyncServiceState();
142 } 169 }
143 170
144 void SyncProcessRunner::Finished(const base::TimeTicks& start_time, 171 void SyncProcessRunner::Finished(const base::TimeTicks& start_time,
145 SyncStatusCode status) { 172 SyncStatusCode status) {
146 DCHECK_LT(0, running_tasks_); 173 DCHECK_LT(0, running_tasks_);
147 DCHECK_LE(running_tasks_, max_parallel_task_); 174 DCHECK_LE(running_tasks_, max_parallel_task_);
148 --running_tasks_; 175 --running_tasks_;
149 util::Log(logging::LOG_VERBOSE, FROM_HERE, 176 util::Log(logging::LOG_VERBOSE, FROM_HERE,
150 "[%s] * Finished (elapsed: %" PRId64 " sec)", 177 "[%s] * Finished (elapsed: %" PRId64 " ms)", name_.c_str(),
151 name_.c_str(), 178 (timer_helper_->Now() - start_time).InMilliseconds());
152 (timer_helper_->Now() - start_time).InSeconds()); 179
153 if (status == SYNC_STATUS_NO_CHANGE_TO_SYNC || 180 if (status == SYNC_STATUS_NO_CHANGE_TO_SYNC ||
154 status == SYNC_STATUS_FILE_BUSY) 181 status == SYNC_STATUS_FILE_BUSY) {
155 ScheduleInternal(kSyncDelayMaxInMilliseconds); 182 ScheduleInternal(kSyncDelayMaxInMilliseconds);
156 else if (!WasSuccessfulSync(status) && 183 return;
157 GetServiceState() == SYNC_SERVICE_RUNNING) 184 }
158 ScheduleInternal(kSyncDelayWithSyncError); 185
159 else 186 if (!WasSuccessfulSync(status) &&
160 Schedule(); 187 GetServiceState() == SYNC_SERVICE_RUNNING) {
188 ThrottleSync(kSyncDelayWithSyncError);
189 }
190
191 Schedule();
161 } 192 }
162 193
163 void SyncProcessRunner::Run() { 194 void SyncProcessRunner::Run() {
164 if (running_tasks_ >= max_parallel_task_) 195 if (running_tasks_ >= max_parallel_task_)
165 return; 196 return;
166 ++running_tasks_; 197 ++running_tasks_;
167 last_scheduled_ = timer_helper_->Now(); 198 last_scheduled_ = timer_helper_->Now();
168 last_delay_ = current_delay_; 199 last_delay_ = current_delay_;
169 200
170 util::Log(logging::LOG_VERBOSE, FROM_HERE, 201 util::Log(logging::LOG_VERBOSE, FROM_HERE,
171 "[%s] * Started", name_.c_str()); 202 "[%s] * Started", name_.c_str());
172 203
173 StartSync(base::Bind(&SyncProcessRunner::Finished, factory_.GetWeakPtr(), 204 StartSync(base::Bind(&SyncProcessRunner::Finished, factory_.GetWeakPtr(),
174 last_scheduled_)); 205 last_scheduled_));
206 Schedule();
175 } 207 }
176 208
177 void SyncProcessRunner::ScheduleInternal(int64 delay) { 209 void SyncProcessRunner::ScheduleInternal(int64 delay) {
178 base::TimeDelta time_to_next = base::TimeDelta::FromMilliseconds(delay); 210 base::TimeDelta time_to_next = base::TimeDelta::FromMilliseconds(delay);
211 base::TimeTicks now = timer_helper_->Now();
179 212
180 if (timer_helper_->IsRunning()) { 213 if (timer_helper_->IsRunning()) {
181 if (current_delay_ == delay) 214 if (current_delay_ == delay)
182 return; 215 return;
183 216
184 base::TimeDelta elapsed = timer_helper_->Now() - last_scheduled_; 217 base::TimeDelta elapsed = now - last_scheduled_;
185 if (elapsed < time_to_next) { 218 if (elapsed < time_to_next) {
186 time_to_next = time_to_next - elapsed; 219 time_to_next = time_to_next - elapsed;
187 } else { 220 } else {
188 time_to_next = base::TimeDelta::FromMilliseconds( 221 time_to_next = base::TimeDelta::FromMilliseconds(
189 kSyncDelayFastInMilliseconds); 222 kSyncDelayFastInMilliseconds);
190 } 223 }
191 } 224 }
192 225
226 if (now + time_to_next < throttle_until_)
227 time_to_next = throttle_until_ - now;
228
193 if (current_delay_ != delay) { 229 if (current_delay_ != delay) {
194 util::Log(logging::LOG_VERBOSE, FROM_HERE, 230 util::Log(logging::LOG_VERBOSE, FROM_HERE,
195 "[%s] Scheduling task in %" PRId64 " secs", 231 "[%s] Scheduling task in %" PRId64 " secs",
196 name_.c_str(), time_to_next.InSeconds()); 232 name_.c_str(), time_to_next.InSeconds());
197 } 233 }
198 current_delay_ = delay; 234 current_delay_ = delay;
199 235
200 timer_helper_->Start( 236 timer_helper_->Start(
201 FROM_HERE, time_to_next, 237 FROM_HERE, time_to_next,
202 base::Bind(&SyncProcessRunner::Run, base::Unretained(this))); 238 base::Bind(&SyncProcessRunner::Run, base::Unretained(this)));
203 } 239 }
204 240
205 } // namespace sync_file_system 241 } // namespace sync_file_system
OLDNEW
« no previous file with comments | « chrome/browser/sync_file_system/sync_process_runner.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698