| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/net/websocket_experiment/websocket_experiment_runner.h" | 5 #include "chrome/browser/net/websocket_experiment/websocket_experiment_runner.h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/histogram.h" | 8 #include "base/histogram.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/task.h" | 10 #include "base/task.h" |
| 11 #include "chrome/browser/chrome_thread.h" | 11 #include "chrome/browser/chrome_thread.h" |
| 12 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
| 13 | 13 |
| 14 namespace chrome_browser_net_websocket_experiment { | 14 namespace chrome_browser_net_websocket_experiment { |
| 15 | 15 |
| 16 static const char *kExperimentHost = "websocket-experiment.chromium.org"; | 16 static const char *kExperimentHost = "websocket-experiment.chromium.org"; |
| 17 static const int kAlternativePort = 61985; | 17 static const int kAlternativePort = 61985; |
| 18 | 18 |
| 19 static const char kLastStateName[] = "LastState"; | |
| 20 static const char kUrlFetchName[] = "UrlFetch"; | |
| 21 static const char kWebSocketConnectName[] = "WebSocketConnect"; | |
| 22 static const char kWebSocketEchoName[] = "WebSocketEcho"; | |
| 23 static const char kWebSocketIdleName[] = "WebSocketIdle"; | |
| 24 static const char kWebSocketTotalName[] = "WebSocketTotal"; | |
| 25 static const int kUrlFetchDeadlineSec = 10; | 19 static const int kUrlFetchDeadlineSec = 10; |
| 26 static const int kWebSocketConnectDeadlineSec = 10; | 20 static const int kWebSocketConnectDeadlineSec = 10; |
| 27 static const int kWebSocketEchoDeadlineSec = 5; | 21 static const int kWebSocketEchoDeadlineSec = 5; |
| 28 static const int kWebSocketIdleSec = 1; | 22 static const int kWebSocketIdleSec = 1; |
| 29 static const int kWebSocketPushDeadlineSec = 1; | 23 static const int kWebSocketPushDeadlineSec = 1; |
| 30 static const int kWebSocketByeDeadlineSec = 10; | 24 static const int kWebSocketByeDeadlineSec = 10; |
| 31 static const int kWebSocketCloseDeadlineSec = 5; | 25 static const int kWebSocketCloseDeadlineSec = 5; |
| 32 static const int kWebSocketTimeSec = 10; | 26 static const int kWebSocketTimeSec = 10; |
| 27 static const int kTimeBucketCount = 50; |
| 28 |
| 29 // TODO(ukai): Use new thread-safe-reference-counted Histograms. |
| 30 #define UPDATE_HISTOGRAM(name, sample, min, max, bucket_count) do { \ |
| 31 switch (task_state_) { \ |
| 32 case STATE_RUN_WS: \ |
| 33 { \ |
| 34 static LinearHistogram counter( \ |
| 35 "WebSocketExperiment.Basic." name, min, max, bucket_count); \ |
| 36 counter.SetFlags(kUmaTargetedHistogramFlag); \ |
| 37 counter.Add(sample); \ |
| 38 } \ |
| 39 break; \ |
| 40 case STATE_RUN_WSS: \ |
| 41 { \ |
| 42 static LinearHistogram counter( \ |
| 43 "WebSocketExperiment.Secure." name, min, max, bucket_count); \ |
| 44 counter.SetFlags(kUmaTargetedHistogramFlag); \ |
| 45 counter.Add(sample); \ |
| 46 } \ |
| 47 break; \ |
| 48 case STATE_RUN_WS_NODEFAULT_PORT: \ |
| 49 { \ |
| 50 static LinearHistogram counter( \ |
| 51 "WebSocketExperiment.NoDefaultPort." name, \ |
| 52 min, max, bucket_count); \ |
| 53 counter.SetFlags(kUmaTargetedHistogramFlag); \ |
| 54 counter.Add(sample); \ |
| 55 } \ |
| 56 break; \ |
| 57 default: \ |
| 58 NOTREACHED(); \ |
| 59 break; \ |
| 60 } \ |
| 61 } while (0) |
| 62 |
| 63 #define UPDATE_HISTOGRAM_TIMES(name, sample, min, max, bucket_count) do { \ |
| 64 switch (task_state_) { \ |
| 65 case STATE_RUN_WS: \ |
| 66 { \ |
| 67 static Histogram counter( \ |
| 68 "WebSocketExperiment.Basic." name, min, max, bucket_count); \ |
| 69 counter.SetFlags(kUmaTargetedHistogramFlag); \ |
| 70 counter.AddTime(sample); \ |
| 71 } \ |
| 72 break; \ |
| 73 case STATE_RUN_WSS: \ |
| 74 { \ |
| 75 static Histogram counter( \ |
| 76 "WebSocketExperiment.Secure." name, min, max, bucket_count); \ |
| 77 counter.SetFlags(kUmaTargetedHistogramFlag); \ |
| 78 counter.AddTime(sample); \ |
| 79 } \ |
| 80 break; \ |
| 81 case STATE_RUN_WS_NODEFAULT_PORT: \ |
| 82 { \ |
| 83 static Histogram counter( \ |
| 84 "WebSocketExperiment.NoDefaultPort." name, \ |
| 85 min, max, bucket_count); \ |
| 86 counter.SetFlags(kUmaTargetedHistogramFlag); \ |
| 87 counter.AddTime(sample); \ |
| 88 } \ |
| 89 break; \ |
| 90 default: \ |
| 91 NOTREACHED(); \ |
| 92 break; \ |
| 93 } \ |
| 94 } while (0); |
| 33 | 95 |
| 34 // Hold reference while experiment is running. | 96 // Hold reference while experiment is running. |
| 35 static scoped_refptr<WebSocketExperimentRunner> runner; | 97 static scoped_refptr<WebSocketExperimentRunner> runner; |
| 36 | 98 |
| 37 /* static */ | 99 /* static */ |
| 38 void WebSocketExperimentRunner::Start() { | 100 void WebSocketExperimentRunner::Start() { |
| 39 DCHECK(!runner.get()); | 101 DCHECK(!runner.get()); |
| 40 runner = new WebSocketExperimentRunner; | 102 runner = new WebSocketExperimentRunner; |
| 41 runner->Run(); | 103 runner->Run(); |
| 42 } | 104 } |
| 43 | 105 |
| 44 /* static */ | 106 /* static */ |
| 45 void WebSocketExperimentRunner::Stop() { | 107 void WebSocketExperimentRunner::Stop() { |
| 46 if (runner.get()) | 108 if (runner.get()) |
| 47 runner->Cancel(); | 109 runner->Cancel(); |
| 48 runner = NULL; | 110 runner = NULL; |
| 49 } | 111 } |
| 50 | 112 |
| 51 WebSocketExperimentRunner::WebSocketExperimentRunner() | 113 WebSocketExperimentRunner::WebSocketExperimentRunner() |
| 52 : next_state_(STATE_NONE), | 114 : next_state_(STATE_NONE), |
| 53 task_state_(STATE_NONE), | 115 task_state_(STATE_NONE), |
| 54 ALLOW_THIS_IN_INITIALIZER_LIST( | 116 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 55 task_callback_(this, &WebSocketExperimentRunner::OnTaskCompleted)) { | 117 task_callback_(this, &WebSocketExperimentRunner::OnTaskCompleted)) { |
| 56 InitConfig(); | 118 InitConfig(); |
| 57 InitHistograms(); | |
| 58 } | 119 } |
| 59 | 120 |
| 60 WebSocketExperimentRunner::~WebSocketExperimentRunner() { | 121 WebSocketExperimentRunner::~WebSocketExperimentRunner() { |
| 61 DLOG(INFO) << "WebSocketExperimentRunner deleted"; | 122 DLOG(INFO) << "WebSocketExperimentRunner deleted"; |
| 62 DCHECK(!task_.get()); | 123 DCHECK(!task_.get()); |
| 63 } | 124 } |
| 64 | 125 |
| 65 void WebSocketExperimentRunner::Run() { | 126 void WebSocketExperimentRunner::Run() { |
| 66 DCHECK_EQ(next_state_, STATE_NONE); | 127 DCHECK_EQ(next_state_, STATE_NONE); |
| 67 next_state_ = STATE_RUN_WS; | 128 next_state_ = STATE_RUN_WS; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 GURL(StringPrintf("ws://%s:%d/live_exp", | 185 GURL(StringPrintf("ws://%s:%d/live_exp", |
| 125 kExperimentHost, kAlternativePort)); | 186 kExperimentHost, kAlternativePort)); |
| 126 config_.ws_nondefault_config.ws_location = | 187 config_.ws_nondefault_config.ws_location = |
| 127 StringPrintf("ws://%s:%d/live_exp", | 188 StringPrintf("ws://%s:%d/live_exp", |
| 128 kExperimentHost, kAlternativePort); | 189 kExperimentHost, kAlternativePort); |
| 129 config_.ws_nondefault_config.http_url = | 190 config_.ws_nondefault_config.http_url = |
| 130 GURL(StringPrintf("http://%s:%d/", | 191 GURL(StringPrintf("http://%s:%d/", |
| 131 kExperimentHost, kAlternativePort)); | 192 kExperimentHost, kAlternativePort)); |
| 132 } | 193 } |
| 133 | 194 |
| 134 void WebSocketExperimentRunner::InitHistograms() { | |
| 135 InitHistogram<LinearHistogram, Histogram::Sample>( | |
| 136 kLastStateName, 1, WebSocketExperimentTask::NUM_STATES, | |
| 137 WebSocketExperimentTask::NUM_STATES + 1); | |
| 138 | |
| 139 InitHistogram<Histogram, base::TimeDelta>( | |
| 140 kUrlFetchName, base::TimeDelta::FromMilliseconds(1), | |
| 141 base::TimeDelta::FromSeconds(kUrlFetchDeadlineSec), 50); | |
| 142 | |
| 143 InitHistogram<Histogram, base::TimeDelta>( | |
| 144 kWebSocketConnectName, base::TimeDelta::FromMilliseconds(1), | |
| 145 base::TimeDelta::FromSeconds(kWebSocketConnectDeadlineSec), 50); | |
| 146 | |
| 147 InitHistogram<Histogram, base::TimeDelta>( | |
| 148 kWebSocketEchoName, base::TimeDelta::FromMilliseconds(1), | |
| 149 base::TimeDelta::FromSeconds(kWebSocketEchoDeadlineSec), 50); | |
| 150 | |
| 151 InitHistogram<Histogram, base::TimeDelta>( | |
| 152 kWebSocketIdleName, base::TimeDelta::FromMilliseconds(1), | |
| 153 base::TimeDelta::FromSeconds( | |
| 154 kWebSocketIdleSec + kWebSocketPushDeadlineSec), 50); | |
| 155 | |
| 156 InitHistogram<Histogram, base::TimeDelta>( | |
| 157 kWebSocketTotalName, base::TimeDelta::FromMilliseconds(1), | |
| 158 base::TimeDelta::FromSeconds(kWebSocketTimeSec), 50); | |
| 159 } | |
| 160 | |
| 161 void WebSocketExperimentRunner::DoLoop() { | 195 void WebSocketExperimentRunner::DoLoop() { |
| 162 if (next_state_ == STATE_NONE) { | 196 if (next_state_ == STATE_NONE) { |
| 163 if (task_.get()) { | 197 if (task_.get()) { |
| 164 AddRef(); // Release in OnTaskCompleted. | 198 AddRef(); // Release in OnTaskCompleted. |
| 165 task_->Cancel(); | 199 task_->Cancel(); |
| 166 } | 200 } |
| 167 return; | 201 return; |
| 168 } | 202 } |
| 169 | 203 |
| 170 State state = next_state_; | 204 State state = next_state_; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 << " url_fetch=" << task_result.url_fetch.InSecondsF() | 269 << " url_fetch=" << task_result.url_fetch.InSecondsF() |
| 236 << " websocket_connect=" | 270 << " websocket_connect=" |
| 237 << task_result.websocket_connect.InSecondsF() | 271 << task_result.websocket_connect.InSecondsF() |
| 238 << " websocket_echo=" | 272 << " websocket_echo=" |
| 239 << task_result.websocket_echo.InSecondsF() | 273 << task_result.websocket_echo.InSecondsF() |
| 240 << " websocket_idle=" | 274 << " websocket_idle=" |
| 241 << task_result.websocket_idle.InSecondsF() | 275 << task_result.websocket_idle.InSecondsF() |
| 242 << " websocket_total=" | 276 << " websocket_total=" |
| 243 << task_result.websocket_total.InSecondsF(); | 277 << task_result.websocket_total.InSecondsF(); |
| 244 | 278 |
| 279 UPDATE_HISTOGRAM("LastState", task_result.last_state, |
| 280 1, WebSocketExperimentTask::NUM_STATES, |
| 281 WebSocketExperimentTask::NUM_STATES + 1); |
| 245 | 282 |
| 246 Histogram* last_state = GetHistogram(kLastStateName); | 283 UPDATE_HISTOGRAM_TIMES("UrlFetch", task_result.url_fetch, |
| 247 DCHECK(last_state); | 284 base::TimeDelta::FromMilliseconds(1), |
| 248 last_state->Add(task_result.last_state); | 285 base::TimeDelta::FromSeconds(kUrlFetchDeadlineSec), |
| 249 | 286 kTimeBucketCount); |
| 250 Histogram* url_fetch = GetHistogram(kUrlFetchName); | |
| 251 DCHECK(url_fetch); | |
| 252 url_fetch->AddTime(task_result.url_fetch); | |
| 253 | 287 |
| 254 if (task_result.last_state < | 288 if (task_result.last_state < |
| 255 WebSocketExperimentTask::STATE_WEBSOCKET_CONNECT_COMPLETE) | 289 WebSocketExperimentTask::STATE_WEBSOCKET_CONNECT_COMPLETE) |
| 256 return; | 290 return; |
| 257 | 291 |
| 258 Histogram* websocket_connect = GetHistogram(kWebSocketConnectName); | 292 UPDATE_HISTOGRAM_TIMES("WebSocketConnect", task_result.websocket_connect, |
| 259 DCHECK(websocket_connect); | 293 base::TimeDelta::FromMilliseconds(1), |
| 260 websocket_connect->AddTime(task_result.websocket_connect); | 294 base::TimeDelta::FromSeconds( |
| 295 kWebSocketConnectDeadlineSec), |
| 296 kTimeBucketCount); |
| 261 | 297 |
| 262 if (task_result.last_state < | 298 if (task_result.last_state < |
| 263 WebSocketExperimentTask::STATE_WEBSOCKET_RECV_HELLO) | 299 WebSocketExperimentTask::STATE_WEBSOCKET_RECV_HELLO) |
| 264 return; | 300 return; |
| 265 | 301 |
| 266 Histogram* websocket_echo = GetHistogram(kWebSocketEchoName); | 302 UPDATE_HISTOGRAM_TIMES("WebSocketEcho", task_result.websocket_echo, |
| 267 DCHECK(websocket_echo); | 303 base::TimeDelta::FromMilliseconds(1), |
| 268 websocket_echo->AddTime(task_result.websocket_echo); | 304 base::TimeDelta::FromSeconds( |
| 305 kWebSocketEchoDeadlineSec), |
| 306 kTimeBucketCount); |
| 269 | 307 |
| 270 if (task_result.last_state < | 308 if (task_result.last_state < |
| 271 WebSocketExperimentTask::STATE_WEBSOCKET_KEEP_IDLE) | 309 WebSocketExperimentTask::STATE_WEBSOCKET_KEEP_IDLE) |
| 272 return; | 310 return; |
| 273 | 311 |
| 274 Histogram* websocket_idle = GetHistogram(kWebSocketIdleName); | 312 UPDATE_HISTOGRAM_TIMES("WebSocketIdle", task_result.websocket_idle, |
| 275 DCHECK(websocket_idle); | 313 base::TimeDelta::FromMilliseconds(1), |
| 276 websocket_idle->AddTime(task_result.websocket_idle); | 314 base::TimeDelta::FromSeconds( |
| 315 kWebSocketIdleSec + kWebSocketPushDeadlineSec), |
| 316 kTimeBucketCount); |
| 277 | 317 |
| 278 if (task_result.last_state < | 318 if (task_result.last_state < |
| 279 WebSocketExperimentTask::STATE_WEBSOCKET_CLOSE_COMPLETE) | 319 WebSocketExperimentTask::STATE_WEBSOCKET_CLOSE_COMPLETE) |
| 280 return; | 320 return; |
| 281 | 321 |
| 282 Histogram* websocket_total = GetHistogram(kWebSocketTotalName); | 322 UPDATE_HISTOGRAM_TIMES("WebSocketTotal", task_result.websocket_total, |
| 283 DCHECK(websocket_total); | 323 base::TimeDelta::FromMilliseconds(1), |
| 284 websocket_total->AddTime(task_result.websocket_total); | 324 base::TimeDelta::FromSeconds(kWebSocketTimeSec), |
| 285 } | 325 kTimeBucketCount); |
| 286 | |
| 287 template<class HistogramType, typename HistogramSample> | |
| 288 void WebSocketExperimentRunner::InitHistogram( | |
| 289 const char* type_name, | |
| 290 HistogramSample min, HistogramSample max, size_t bucket_count) { | |
| 291 static std::string name = StringPrintf( | |
| 292 "WebSocketExperiment.Basic.%s", type_name); | |
| 293 HistogramType* counter = new HistogramType(name.c_str(), | |
| 294 min, max, bucket_count); | |
| 295 counter->SetFlags(kUmaTargetedHistogramFlag); | |
| 296 ws_histograms_[type_name] = linked_ptr<Histogram>(counter); | |
| 297 | |
| 298 name = StringPrintf("WebSocketExperiment.Secure.%s", type_name); | |
| 299 counter = new HistogramType(name.c_str(), min, max, bucket_count); | |
| 300 counter->SetFlags(kUmaTargetedHistogramFlag); | |
| 301 wss_histograms_[type_name] = linked_ptr<Histogram>(counter); | |
| 302 | |
| 303 name = StringPrintf("WebSocketExperiment.NoDefaultPort.%s", type_name); | |
| 304 counter = new HistogramType(name.c_str(), min, max, bucket_count); | |
| 305 counter->SetFlags(kUmaTargetedHistogramFlag); | |
| 306 ws_nondefault_histograms_[type_name] = linked_ptr<Histogram>(counter); | |
| 307 } | |
| 308 | |
| 309 Histogram* WebSocketExperimentRunner::GetHistogram( | |
| 310 const std::string& type_name) const { | |
| 311 const HistogramMap* histogram_map = NULL; | |
| 312 switch (task_state_) { | |
| 313 case STATE_RUN_WS: | |
| 314 histogram_map = &ws_histograms_; | |
| 315 break; | |
| 316 case STATE_RUN_WSS: | |
| 317 histogram_map = &wss_histograms_; | |
| 318 break; | |
| 319 case STATE_RUN_WS_NODEFAULT_PORT: | |
| 320 histogram_map = &ws_nondefault_histograms_; | |
| 321 break; | |
| 322 default: | |
| 323 NOTREACHED(); | |
| 324 return NULL; | |
| 325 } | |
| 326 DCHECK(histogram_map); | |
| 327 HistogramMap::const_iterator found = histogram_map->find(type_name); | |
| 328 DCHECK(found != histogram_map->end()); | |
| 329 return found->second.get(); | |
| 330 } | 326 } |
| 331 | 327 |
| 332 } // namespace chrome_browser_net_websocket_experiment | 328 } // namespace chrome_browser_net_websocket_experiment |
| OLD | NEW |