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

Side by Side Diff: net/url_request/url_request_throttler_entry.cc

Issue 6696023: Remove minidump analysis aides from URLRequestThrottlerManager. New (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 9 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 (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 "net/url_request/url_request_throttler_entry.h" 5 #include "net/url_request/url_request_throttler_entry.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/rand_util.h" 10 #include "base/rand_util.h"
11 #include "base/string_number_conversions.h" 11 #include "base/string_number_conversions.h"
12 #include "net/url_request/url_request_throttler_header_interface.h" 12 #include "net/url_request/url_request_throttler_header_interface.h"
13 13
14 namespace net { 14 namespace net {
15 15
16 const int URLRequestThrottlerEntry::kDefaultSlidingWindowPeriodMs = 2000; 16 const int URLRequestThrottlerEntry::kDefaultSlidingWindowPeriodMs = 2000;
17 const int URLRequestThrottlerEntry::kDefaultMaxSendThreshold = 20; 17 const int URLRequestThrottlerEntry::kDefaultMaxSendThreshold = 20;
18 const int URLRequestThrottlerEntry::kDefaultInitialBackoffMs = 700; 18 const int URLRequestThrottlerEntry::kDefaultInitialBackoffMs = 700;
19 const int URLRequestThrottlerEntry::kDefaultAdditionalConstantMs = 100;
20 const double URLRequestThrottlerEntry::kDefaultMultiplyFactor = 1.4; 19 const double URLRequestThrottlerEntry::kDefaultMultiplyFactor = 1.4;
21 const double URLRequestThrottlerEntry::kDefaultJitterFactor = 0.4; 20 const double URLRequestThrottlerEntry::kDefaultJitterFactor = 0.4;
22 const int URLRequestThrottlerEntry::kDefaultMaximumBackoffMs = 60 * 60 * 1000; 21 const int URLRequestThrottlerEntry::kDefaultMaximumBackoffMs = 60 * 60 * 1000;
23 const int URLRequestThrottlerEntry::kDefaultEntryLifetimeMs = 120000; 22 const int URLRequestThrottlerEntry::kDefaultEntryLifetimeMs = 120000;
24 const char URLRequestThrottlerEntry::kRetryHeaderName[] = "X-Retry-After"; 23 const char URLRequestThrottlerEntry::kRetryHeaderName[] = "X-Retry-After";
25 24
26 URLRequestThrottlerEntry::URLRequestThrottlerEntry() 25 URLRequestThrottlerEntry::URLRequestThrottlerEntry()
27 : sliding_window_period_( 26 : sliding_window_period_(
28 base::TimeDelta::FromMilliseconds(kDefaultSlidingWindowPeriodMs)), 27 base::TimeDelta::FromMilliseconds(kDefaultSlidingWindowPeriodMs)),
29 max_send_threshold_(kDefaultMaxSendThreshold), 28 max_send_threshold_(kDefaultMaxSendThreshold),
30 initial_backoff_ms_(kDefaultInitialBackoffMs), 29 backoff_entry_(&backoff_policy_) {
31 additional_constant_ms_(kDefaultAdditionalConstantMs),
32 multiply_factor_(kDefaultMultiplyFactor),
33 jitter_factor_(kDefaultJitterFactor),
34 maximum_backoff_ms_(kDefaultMaximumBackoffMs),
35 entry_lifetime_ms_(kDefaultEntryLifetimeMs) {
36 Initialize(); 30 Initialize();
37 } 31 }
38 32
39 URLRequestThrottlerEntry::URLRequestThrottlerEntry( 33 URLRequestThrottlerEntry::URLRequestThrottlerEntry(
40 int sliding_window_period_ms, 34 int sliding_window_period_ms,
41 int max_send_threshold, 35 int max_send_threshold,
42 int initial_backoff_ms, 36 int initial_backoff_ms,
43 int additional_constant_ms,
44 double multiply_factor, 37 double multiply_factor,
45 double jitter_factor, 38 double jitter_factor,
46 int maximum_backoff_ms) 39 int maximum_backoff_ms)
47 : sliding_window_period_( 40 : sliding_window_period_(
48 base::TimeDelta::FromMilliseconds(sliding_window_period_ms)), 41 base::TimeDelta::FromMilliseconds(sliding_window_period_ms)),
49 max_send_threshold_(max_send_threshold), 42 max_send_threshold_(max_send_threshold),
50 initial_backoff_ms_(initial_backoff_ms), 43 backoff_entry_(&backoff_policy_) {
51 additional_constant_ms_(additional_constant_ms),
52 multiply_factor_(multiply_factor),
53 jitter_factor_(jitter_factor),
54 maximum_backoff_ms_(maximum_backoff_ms),
55 entry_lifetime_ms_(-1) {
56 DCHECK_GT(sliding_window_period_ms, 0); 44 DCHECK_GT(sliding_window_period_ms, 0);
57 DCHECK_GT(max_send_threshold_, 0); 45 DCHECK_GT(max_send_threshold_, 0);
58 DCHECK_GE(initial_backoff_ms_, 0); 46 DCHECK_GE(initial_backoff_ms, 0);
59 DCHECK_GE(additional_constant_ms_, 0); 47 DCHECK_GT(multiply_factor, 0);
60 DCHECK_GT(multiply_factor_, 0); 48 DCHECK_GE(jitter_factor, 0.0);
61 DCHECK_GE(jitter_factor_, 0); 49 DCHECK_LT(jitter_factor, 1.0);
62 DCHECK_LT(jitter_factor_, 1); 50 DCHECK_GE(maximum_backoff_ms, 0);
63 DCHECK_GE(maximum_backoff_ms_, 0);
64 51
65 Initialize(); 52 Initialize();
53 backoff_policy_.initial_backoff_ms_ = initial_backoff_ms;
54 backoff_policy_.multiply_factor_ = multiply_factor;
55 backoff_policy_.jitter_factor_ = jitter_factor;
56 backoff_policy_.maximum_backoff_ms_ = maximum_backoff_ms;
57 backoff_policy_.entry_lifetime_ms_ = -1;
66 } 58 }
67 59
68 bool URLRequestThrottlerEntry::IsEntryOutdated() const { 60 bool URLRequestThrottlerEntry::IsEntryOutdated() const {
69 CHECK(this); // to help track crbug.com/71721 61 return GetBackoffEntry()->CanDiscard();
70 if (entry_lifetime_ms_ == -1)
71 return false;
72
73 base::TimeTicks now = GetTimeNow();
74
75 // If there are send events in the sliding window period, we still need this
76 // entry.
77 if (!send_log_.empty() &&
78 send_log_.back() + sliding_window_period_ > now) {
79 return false;
80 }
81
82 int64 unused_since_ms =
83 (now - exponential_backoff_release_time_).InMilliseconds();
84
85 // Release time is further than now, we are managing it.
86 if (unused_since_ms < 0)
87 return false;
88
89 // latest_response_was_failure_ is true indicates that the latest one or
90 // more requests encountered server errors or had malformed response bodies.
91 // In that case, we don't want to collect the entry unless it hasn't been used
92 // for longer than the maximum allowed back-off.
93 if (latest_response_was_failure_)
94 return unused_since_ms > std::max(maximum_backoff_ms_, entry_lifetime_ms_);
95
96 // Otherwise, consider the entry is outdated if it hasn't been used for the
97 // specified lifetime period.
98 return unused_since_ms > entry_lifetime_ms_;
99 } 62 }
100 63
101 bool URLRequestThrottlerEntry::IsDuringExponentialBackoff() const { 64 bool URLRequestThrottlerEntry::IsDuringExponentialBackoff() const {
102 return exponential_backoff_release_time_ > GetTimeNow(); 65 return GetBackoffEntry()->ShouldRejectRequest();
103 } 66 }
104 67
105 int64 URLRequestThrottlerEntry::ReserveSendingTimeForNextRequest( 68 int64 URLRequestThrottlerEntry::ReserveSendingTimeForNextRequest(
106 const base::TimeTicks& earliest_time) { 69 const base::TimeTicks& earliest_time) {
107 base::TimeTicks now = GetTimeNow(); 70 base::TimeTicks now = GetTimeNow();
71
108 // If a lot of requests were successfully made recently, 72 // If a lot of requests were successfully made recently,
109 // sliding_window_release_time_ may be greater than 73 // sliding_window_release_time_ may be greater than
110 // exponential_backoff_release_time_. 74 // exponential_backoff_release_time_.
111 base::TimeTicks recommended_sending_time = 75 base::TimeTicks recommended_sending_time =
112 std::max(std::max(now, earliest_time), 76 std::max(std::max(now, earliest_time),
113 std::max(exponential_backoff_release_time_, 77 std::max(GetBackoffEntry()->GetReleaseTime(),
114 sliding_window_release_time_)); 78 sliding_window_release_time_));
115 79
116 DCHECK(send_log_.empty() || 80 DCHECK(send_log_.empty() ||
117 recommended_sending_time >= send_log_.back()); 81 recommended_sending_time >= send_log_.back());
118 // Log the new send event. 82 // Log the new send event.
119 send_log_.push(recommended_sending_time); 83 send_log_.push(recommended_sending_time);
120 84
121 sliding_window_release_time_ = recommended_sending_time; 85 sliding_window_release_time_ = recommended_sending_time;
122 86
123 // Drop the out-of-date events in the event list. 87 // Drop the out-of-date events in the event list.
124 // We don't need to worry that the queue may become empty during this 88 // We don't need to worry that the queue may become empty during this
125 // operation, since the last element is sliding_window_release_time_. 89 // operation, since the last element is sliding_window_release_time_.
126 while ((send_log_.front() + sliding_window_period_ <= 90 while ((send_log_.front() + sliding_window_period_ <=
127 sliding_window_release_time_) || 91 sliding_window_release_time_) ||
128 send_log_.size() > static_cast<unsigned>(max_send_threshold_)) { 92 send_log_.size() > static_cast<unsigned>(max_send_threshold_)) {
129 send_log_.pop(); 93 send_log_.pop();
130 } 94 }
131 95
132 // Check if there are too many send events in recent time. 96 // Check if there are too many send events in recent time.
133 if (send_log_.size() == static_cast<unsigned>(max_send_threshold_)) 97 if (send_log_.size() == static_cast<unsigned>(max_send_threshold_))
134 sliding_window_release_time_ = send_log_.front() + sliding_window_period_; 98 sliding_window_release_time_ = send_log_.front() + sliding_window_period_;
135 99
136 return (recommended_sending_time - now).InMillisecondsRoundedUp(); 100 return (recommended_sending_time - now).InMillisecondsRoundedUp();
137 } 101 }
138 102
139 base::TimeTicks 103 base::TimeTicks
140 URLRequestThrottlerEntry::GetExponentialBackoffReleaseTime() const { 104 URLRequestThrottlerEntry::GetExponentialBackoffReleaseTime() const {
141 return exponential_backoff_release_time_; 105 return GetBackoffEntry()->GetReleaseTime();
142 } 106 }
143 107
144 void URLRequestThrottlerEntry::UpdateWithResponse( 108 void URLRequestThrottlerEntry::UpdateWithResponse(
145 const URLRequestThrottlerHeaderInterface* response) { 109 const URLRequestThrottlerHeaderInterface* response) {
146 if (response->GetResponseCode() >= 500) { 110 if (response->GetResponseCode() >= 500) {
147 failure_count_++; 111 GetBackoffEntry()->InformOfRequest(false);
148 latest_response_was_failure_ = true;
149 exponential_backoff_release_time_ =
150 CalculateExponentialBackoffReleaseTime();
151 } else { 112 } else {
152 // We slowly decay the number of times delayed instead of resetting it to 0 113 GetBackoffEntry()->InformOfRequest(true);
153 // in order to stay stable if we received lots of requests with
154 // malformed bodies at the same time.
155 if (failure_count_ > 0)
156 failure_count_--;
157
158 latest_response_was_failure_ = false;
159
160 // The reason why we are not just cutting the release time to GetTimeNow()
161 // is on the one hand, it would unset delay put by our custom retry-after
162 // header and on the other we would like to push every request up to our
163 // "horizon" when dealing with multiple in-flight requests. Ex: If we send
164 // three requests and we receive 2 failures and 1 success. The success that
165 // follows those failures will not reset the release time, further requests
166 // will then need to wait the delay caused by the 2 failures.
167 exponential_backoff_release_time_ = std::max(
168 GetTimeNow(), exponential_backoff_release_time_);
169 114
170 std::string retry_header = response->GetNormalizedValue(kRetryHeaderName); 115 std::string retry_header = response->GetNormalizedValue(kRetryHeaderName);
171 if (!retry_header.empty()) 116 if (!retry_header.empty())
172 HandleCustomRetryAfter(retry_header); 117 HandleCustomRetryAfter(retry_header);
173 } 118 }
174 } 119 }
175 120
176 void URLRequestThrottlerEntry::ReceivedContentWasMalformed() { 121 void URLRequestThrottlerEntry::ReceivedContentWasMalformed() {
177 // For any response that is marked as malformed now, we have probably 122 // We keep this simple and just count it as an error.
178 // considered it as a success when receiving it and decreased the failure 123 GetBackoffEntry()->InformOfRequest(false);
179 // count by 1. As a result, we increase the failure count by 2 here to undo
180 // the effect and record a failure.
181 //
182 // Please note that this may lead to a larger failure count than expected,
183 // because we don't decrease the failure count for successful responses when
184 // it has already reached 0.
185 failure_count_ += 2;
186 latest_response_was_failure_ = true;
187 exponential_backoff_release_time_ = CalculateExponentialBackoffReleaseTime();
188 }
189
190 void URLRequestThrottlerEntry::SetEntryLifetimeMsForTest(int lifetime_ms) {
191 entry_lifetime_ms_ = lifetime_ms;
192 } 124 }
193 125
194 URLRequestThrottlerEntry::~URLRequestThrottlerEntry() { 126 URLRequestThrottlerEntry::~URLRequestThrottlerEntry() {
195 } 127 }
196 128
197 void URLRequestThrottlerEntry::Initialize() { 129 void URLRequestThrottlerEntry::Initialize() {
198 // Since this method is called by the constructors, GetTimeNow() (a virtual
199 // method) is not used.
200 exponential_backoff_release_time_ = base::TimeTicks::Now();
201 failure_count_ = 0;
202 latest_response_was_failure_ = false;
203
204 sliding_window_release_time_ = base::TimeTicks::Now(); 130 sliding_window_release_time_ = base::TimeTicks::Now();
205 } 131 backoff_policy_.num_errors_to_ignore_ = 0;
206 132 backoff_policy_.initial_backoff_ms_ = kDefaultInitialBackoffMs;
207 base::TimeTicks 133 backoff_policy_.multiply_factor_ = kDefaultMultiplyFactor;
208 URLRequestThrottlerEntry::CalculateExponentialBackoffReleaseTime() { 134 backoff_policy_.jitter_factor_ = kDefaultJitterFactor;
209 double delay = initial_backoff_ms_; 135 backoff_policy_.maximum_backoff_ms_ = kDefaultMaximumBackoffMs;
210 delay *= pow(multiply_factor_, failure_count_); 136 backoff_policy_.entry_lifetime_ms_ = kDefaultEntryLifetimeMs;
211 delay += additional_constant_ms_;
212 delay -= base::RandDouble() * jitter_factor_ * delay;
213
214 // Ensure that we do not exceed maximum delay.
215 int64 delay_int = static_cast<int64>(delay + 0.5);
216 delay_int = std::min(delay_int, static_cast<int64>(maximum_backoff_ms_));
217
218 return std::max(GetTimeNow() + base::TimeDelta::FromMilliseconds(delay_int),
219 exponential_backoff_release_time_);
220 } 137 }
221 138
222 base::TimeTicks URLRequestThrottlerEntry::GetTimeNow() const { 139 base::TimeTicks URLRequestThrottlerEntry::GetTimeNow() const {
223 return base::TimeTicks::Now(); 140 return base::TimeTicks::Now();
224 } 141 }
225 142
226 void URLRequestThrottlerEntry::HandleCustomRetryAfter( 143 void URLRequestThrottlerEntry::HandleCustomRetryAfter(
227 const std::string& header_value) { 144 const std::string& header_value) {
228 // Input parameter is the number of seconds to wait in a floating point value. 145 // Input parameter is the number of seconds to wait in a floating point value.
229 double time_in_sec = 0; 146 double time_in_sec = 0;
230 bool conversion_is_ok = base::StringToDouble(header_value, &time_in_sec); 147 bool conversion_is_ok = base::StringToDouble(header_value, &time_in_sec);
231 148
232 // Conversion of custom retry-after header value failed. 149 // Conversion of custom retry-after header value failed.
233 if (!conversion_is_ok) 150 if (!conversion_is_ok)
234 return; 151 return;
235 152
236 // We must use an int value later so we transform this in milliseconds. 153 // We must use an int value later so we transform this in milliseconds.
237 int64 value_ms = static_cast<int64>(0.5 + time_in_sec * 1000); 154 int64 value_ms = static_cast<int64>(0.5 + time_in_sec * 1000);
238 155
239 if (maximum_backoff_ms_ < value_ms || value_ms < 0) 156 // We do not check for an upper bound; the server can set any Retry-After it
157 // desires. Recovery from error would involve restarting the browser.
158 if (value_ms < 0)
240 return; 159 return;
241 160
242 exponential_backoff_release_time_ = std::max( 161 GetBackoffEntry()->SetCustomReleaseTime(
243 (GetTimeNow() + base::TimeDelta::FromMilliseconds(value_ms)), 162 GetTimeNow() + base::TimeDelta::FromMilliseconds(value_ms));
244 exponential_backoff_release_time_); 163 }
164
165 const BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() const {
166 return &backoff_entry_;
167 }
168
169 BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() {
170 return &backoff_entry_;
245 } 171 }
246 172
247 } // namespace net 173 } // namespace net
OLDNEW
« no previous file with comments | « net/url_request/url_request_throttler_entry.h ('k') | net/url_request/url_request_throttler_entry_interface.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698