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

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: fix 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
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), 72 service_state_(SYNC_SERVICE_RUNNING),
73 last_delay_(0),
74 pending_changes_(0), 73 pending_changes_(0),
75 factory_(this) { 74 factory_(this) {
76 DCHECK_LE(1, max_parallel_task_); 75 DCHECK_LE(1, max_parallel_task_);
77
78 DCHECK_EQ(1, max_parallel_task_)
79 << "Parellel task execution is not yet implemented.";
80 if (!timer_helper_) 76 if (!timer_helper_)
81 timer_helper_.reset(new BaseTimerHelper); 77 timer_helper_.reset(new BaseTimerHelper);
82 } 78 }
83 79
84 SyncProcessRunner::~SyncProcessRunner() {} 80 SyncProcessRunner::~SyncProcessRunner() {}
85 81
86 void SyncProcessRunner::Schedule() { 82 void SyncProcessRunner::Schedule() {
87 int64 delay = kSyncDelayInMilliseconds;
88 if (pending_changes_ == 0) { 83 if (pending_changes_ == 0) {
89 ScheduleInternal(kSyncDelayMaxInMilliseconds); 84 ScheduleInternal(kSyncDelayMaxInMilliseconds);
90 return; 85 return;
91 } 86 }
92 switch (GetServiceState()) { 87
88 SyncServiceState last_service_state = service_state_;
89 service_state_ = GetServiceState();
90
91 switch (service_state_) {
93 case SYNC_SERVICE_RUNNING: 92 case SYNC_SERVICE_RUNNING:
93 ResetThrottling();
94 if (pending_changes_ > kPendingChangeThresholdForFastSync) 94 if (pending_changes_ > kPendingChangeThresholdForFastSync)
95 delay = kSyncDelayFastInMilliseconds; 95 ScheduleInternal(kSyncDelayFastInMilliseconds);
96 else 96 else
97 delay = kSyncDelayInMilliseconds; 97 ScheduleInternal(kSyncDelayInMilliseconds);
98 break; 98 return;
99 99
100 case SYNC_SERVICE_TEMPORARY_UNAVAILABLE: 100 case SYNC_SERVICE_TEMPORARY_UNAVAILABLE:
101 delay = kSyncDelaySlowInMilliseconds; 101 if (last_service_state != service_state_)
102 if (last_delay_ >= kSyncDelaySlowInMilliseconds) 102 ThrottleSync(kSyncDelaySlowInMilliseconds);
103 delay = last_delay_ * 2; 103 ScheduleInternal(kSyncDelaySlowInMilliseconds);
104 if (delay >= kSyncDelayMaxInMilliseconds) 104 return;
105 delay = kSyncDelayMaxInMilliseconds;
106 break;
107 105
108 case SYNC_SERVICE_AUTHENTICATION_REQUIRED: 106 case SYNC_SERVICE_AUTHENTICATION_REQUIRED:
109 case SYNC_SERVICE_DISABLED: 107 case SYNC_SERVICE_DISABLED:
110 delay = kSyncDelayMaxInMilliseconds; 108 if (last_service_state != service_state_)
111 break; 109 ThrottleSync(kSyncDelaySlowInMilliseconds);
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() {
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
186 if (WasSuccessfulSync(status))
187 ResetOldThrottling();
159 else 188 else
160 Schedule(); 189 ThrottleSync(kSyncDelayWithSyncError);
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 base::TimeTicks now = timer_helper_->Now();
168 last_delay_ = current_delay_; 199 last_run_ = now;
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 now));
206 if (running_tasks_ < max_parallel_task_)
207 Schedule();
175 } 208 }
176 209
177 void SyncProcessRunner::ScheduleInternal(int64 delay) { 210 void SyncProcessRunner::ScheduleInternal(int64 delay) {
178 base::TimeDelta time_to_next = base::TimeDelta::FromMilliseconds(delay); 211 base::TimeTicks now = timer_helper_->Now();
212 base::TimeTicks next_scheduled;
179 213
180 if (timer_helper_->IsRunning()) { 214 if (timer_helper_->IsRunning()) {
181 if (current_delay_ == delay) 215 next_scheduled = last_run_ + base::TimeDelta::FromMilliseconds(delay);
182 return; 216 if (next_scheduled < now) {
183 217 next_scheduled =
184 base::TimeDelta elapsed = timer_helper_->Now() - last_scheduled_; 218 now + base::TimeDelta::FromMilliseconds(kSyncDelayFastInMilliseconds);
185 if (elapsed < time_to_next) {
186 time_to_next = time_to_next - elapsed;
187 } else {
188 time_to_next = base::TimeDelta::FromMilliseconds(
189 kSyncDelayFastInMilliseconds);
190 } 219 }
220 } else {
221 next_scheduled = now + base::TimeDelta::FromMilliseconds(delay);
191 } 222 }
192 223
193 if (current_delay_ != delay) { 224 if (next_scheduled < throttle_until_)
194 util::Log(logging::LOG_VERBOSE, FROM_HERE, 225 next_scheduled = throttle_until_;
195 "[%s] Scheduling task in %" PRId64 " secs", 226
196 name_.c_str(), time_to_next.InSeconds()); 227 if (timer_helper_->IsRunning() && last_scheduled_ == next_scheduled)
197 } 228 return;
198 current_delay_ = delay; 229
230 util::Log(logging::LOG_VERBOSE, FROM_HERE,
231 "[%s] Scheduling task in %" PRId64 " ms",
232 name_.c_str(), (next_scheduled - now).InMilliseconds());
233
234 last_scheduled_ = next_scheduled;
199 235
200 timer_helper_->Start( 236 timer_helper_->Start(
201 FROM_HERE, time_to_next, 237 FROM_HERE, next_scheduled - now,
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

Powered by Google App Engine
This is Rietveld 408576698