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

Side by Side Diff: net/socket/client_socket_pool_base.cc

Issue 6990036: Deciding best connection to schedule requests on based on cwnd and idle time (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: addressing comments Created 9 years, 6 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/socket/client_socket_pool_base.h" 5 #include "net/socket/client_socket_pool_base.h"
6 6
7 #include <math.h>
8 #include <utility>
9 #include "base/command_line.h"
7 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
8 #include "base/format_macros.h" 11 #include "base/format_macros.h"
12 #include "base/logging.h"
9 #include "base/message_loop.h" 13 #include "base/message_loop.h"
10 #include "base/metrics/stats_counters.h" 14 #include "base/metrics/stats_counters.h"
11 #include "base/stl_util-inl.h" 15 #include "base/stl_util-inl.h"
16 #include "base/string_number_conversions.h"
12 #include "base/string_util.h" 17 #include "base/string_util.h"
13 #include "base/time.h" 18 #include "base/time.h"
14 #include "base/values.h" 19 #include "base/values.h"
15 #include "net/base/net_log.h" 20 #include "net/base/net_log.h"
16 #include "net/base/net_errors.h" 21 #include "net/base/net_errors.h"
17 #include "net/socket/client_socket_handle.h" 22 #include "net/socket/client_socket_handle.h"
18 23
19 using base::TimeDelta; 24 using base::TimeDelta;
20 25
21 namespace { 26 namespace {
22 27
23 // The timeout value, in seconds, used to clean up idle sockets that can't be 28 // The timeout value, in seconds, used to clean up idle sockets that can't be
24 // reused. 29 // reused.
25 // 30 //
26 // Note: It's important to close idle sockets that have received data as soon 31 // Note: It's important to close idle sockets that have received data as soon
27 // as possible because the received data may cause BSOD on Windows XP under 32 // as possible because the received data may cause BSOD on Windows XP under
28 // some conditions. See http://crbug.com/4606. 33 // some conditions. See http://crbug.com/4606.
29 const int kCleanupInterval = 10; // DO NOT INCREASE THIS TIMEOUT. 34 const int kCleanupInterval = 10; // DO NOT INCREASE THIS TIMEOUT.
30 35
31 // Indicate whether or not we should establish a new transport layer connection 36 // Indicate whether or not we should establish a new transport layer connection
32 // after a certain timeout has passed without receiving an ACK. 37 // after a certain timeout has passed without receiving an ACK.
33 bool g_connect_backup_jobs_enabled = true; 38 bool g_connect_backup_jobs_enabled = true;
34 39
40 // Decay coef.
41 double g_socket_reuse_policy_penalty_coef = -1;
42
35 } // namespace 43 } // namespace
36 44
37 namespace net { 45 namespace net {
38 46
39 ConnectJob::ConnectJob(const std::string& group_name, 47 ConnectJob::ConnectJob(const std::string& group_name,
40 base::TimeDelta timeout_duration, 48 base::TimeDelta timeout_duration,
41 Delegate* delegate, 49 Delegate* delegate,
42 const BoundNetLog& net_log) 50 const BoundNetLog& net_log)
43 : group_name_(group_name), 51 : group_name_(group_name),
44 timeout_duration_(timeout_duration), 52 timeout_duration_(timeout_duration),
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 } 364 }
357 } 365 }
358 366
359 return rv; 367 return rv;
360 } 368 }
361 369
362 bool ClientSocketPoolBaseHelper::AssignIdleSocketToGroup( 370 bool ClientSocketPoolBaseHelper::AssignIdleSocketToGroup(
363 const Request* request, Group* group) { 371 const Request* request, Group* group) {
364 std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets(); 372 std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets();
365 std::list<IdleSocket>::iterator idle_socket_it = idle_sockets->end(); 373 std::list<IdleSocket>::iterator idle_socket_it = idle_sockets->end();
374 double max_score = -1;
375 std::pair<int, int64> best_pair, current_pair;
376
377 std::string debug_log(request->handle()->group_name());
378 double rtt_ms = 0;
366 379
367 // Iterate through the idle sockets forwards (oldest to newest) 380 // Iterate through the idle sockets forwards (oldest to newest)
368 // * Delete any disconnected ones. 381 // * Delete any disconnected ones.
369 // * If we find a used idle socket, assign to |idle_socket|. At the end, 382 // * If we find a used idle socket, assign to |idle_socket|. At the end,
370 // the |idle_socket_it| will be set to the newest used idle socket. 383 // the |idle_socket_it| will be set to the newest used idle socket.
371 for (std::list<IdleSocket>::iterator it = idle_sockets->begin(); 384 for (std::list<IdleSocket>::iterator it = idle_sockets->begin();
372 it != idle_sockets->end();) { 385 it != idle_sockets->end();) {
373 if (!it->socket->IsConnectedAndIdle()) { 386 if (!it->socket->IsConnectedAndIdle()) {
374 DecrementIdleCount(); 387 DecrementIdleCount();
375 delete it->socket; 388 delete it->socket;
376 it = idle_sockets->erase(it); 389 it = idle_sockets->erase(it);
377 continue; 390 continue;
378 } 391 }
379 392
380 if (it->socket->WasEverUsed()) { 393 if (it->socket->WasEverUsed()) {
381 // We found one we can reuse! 394 // We found one we can reuse!
382 idle_socket_it = it; 395 double score = 0;
396 int64 bytes_read = it->socket->NumBytesRead();
397 double num_kb = static_cast<double>(bytes_read) / 1024.0;
398
399 int idle_time_sec = (base::TimeTicks::Now() - it->start_time).InSeconds();
400 idle_time_sec = std::max(1, idle_time_sec);
401
402 if (g_socket_reuse_policy_penalty_coef >= 0) {
403 score = num_kb / pow(idle_time_sec,
404 g_socket_reuse_policy_penalty_coef);
405
406 debug_log = StringPrintf("%s\n%f\t%d\t%f", debug_log.data(),
Mike Belshe 2011/06/12 22:10:35 please remove the debug logging
Gagan 2011/06/14 18:25:02 Done.
407 num_kb, idle_time_sec, score);
408 }
409
410 // Equality to prefer recently used connection.
411 if (score >= max_score) {
412 idle_socket_it = it;
Mike Belshe 2011/06/12 22:17:03 Note: This is basically a LIFO. The old algorith
Gagan 2011/06/13 03:52:47 Agreed, this behaves like LIFO when response sizes
413 max_score = score;
414 best_pair = std::make_pair(bytes_read, idle_time_sec);
415 rtt_ms = it->socket->GetConnectTimeMicros();
416 }
383 } 417 }
384 418
385 ++it; 419 ++it;
386 } 420 }
421 debug_log = StringPrintf("%s\nChose socket <%d %ld>\nRtt = %f",
422 debug_log.data(),
Mike Belshe 2011/06/12 22:10:35 please remove the debug logging.
Gagan 2011/06/14 18:25:02 Done.
423 best_pair.first, best_pair.second,
424 rtt_ms);
425 LOG(ERROR) << "\n\n----------------------------------------" << debug_log;
387 426
388 // If we haven't found an idle socket, that means there are no used idle 427 // If we haven't found an idle socket, that means there are no used idle
389 // sockets. Pick the oldest (first) idle socket (FIFO). 428 // sockets. Pick the oldest (first) idle socket (FIFO).
390 429
391 if (idle_socket_it == idle_sockets->end() && !idle_sockets->empty()) 430 if (idle_socket_it == idle_sockets->end() && !idle_sockets->empty())
392 idle_socket_it = idle_sockets->begin(); 431 idle_socket_it = idle_sockets->begin();
393 432
394 if (idle_socket_it != idle_sockets->end()) { 433 if (idle_socket_it != idle_sockets->end()) {
395 DecrementIdleCount(); 434 DecrementIdleCount();
396 base::TimeDelta idle_time = 435 base::TimeDelta idle_time =
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 return; 624 return;
586 625
587 // Current time value. Retrieving it once at the function start rather than 626 // Current time value. Retrieving it once at the function start rather than
588 // inside the inner loop, since it shouldn't change by any meaningful amount. 627 // inside the inner loop, since it shouldn't change by any meaningful amount.
589 base::TimeTicks now = base::TimeTicks::Now(); 628 base::TimeTicks now = base::TimeTicks::Now();
590 629
591 GroupMap::iterator i = group_map_.begin(); 630 GroupMap::iterator i = group_map_.begin();
592 while (i != group_map_.end()) { 631 while (i != group_map_.end()) {
593 Group* group = i->second; 632 Group* group = i->second;
594 633
595 std::list<IdleSocket>::iterator j = group->mutable_idle_sockets()->begin(); 634 std::list<IdleSocket>::iterator j = group->mutable_idle_sockets()->begin();
Mike Belshe 2011/06/12 22:17:03 BTW - do we need to clean out the socket with the
Gagan 2011/06/13 03:52:47 Didn't get you. the timeout for cleaning up socket
596 while (j != group->idle_sockets().end()) { 635 while (j != group->idle_sockets().end()) {
597 base::TimeDelta timeout = 636 base::TimeDelta timeout =
598 j->socket->WasEverUsed() ? 637 j->socket->WasEverUsed() ?
599 used_idle_socket_timeout_ : unused_idle_socket_timeout_; 638 used_idle_socket_timeout_ : unused_idle_socket_timeout_;
600 if (force || j->ShouldCleanup(now, timeout)) { 639 if (force || j->ShouldCleanup(now, timeout)) {
601 delete j->socket; 640 delete j->socket;
602 j = group->mutable_idle_sockets()->erase(j); 641 j = group->mutable_idle_sockets()->erase(j);
603 DecrementIdleCount(); 642 DecrementIdleCount();
604 } else { 643 } else {
605 ++j; 644 ++j;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 return g_connect_backup_jobs_enabled; 681 return g_connect_backup_jobs_enabled;
643 } 682 }
644 683
645 // static 684 // static
646 bool ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(bool enabled) { 685 bool ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(bool enabled) {
647 bool old_value = g_connect_backup_jobs_enabled; 686 bool old_value = g_connect_backup_jobs_enabled;
648 g_connect_backup_jobs_enabled = enabled; 687 g_connect_backup_jobs_enabled = enabled;
649 return old_value; 688 return old_value;
650 } 689 }
651 690
691 // static
692 double ClientSocketPoolBaseHelper::SetSocketReusePolicy(int policy) {
693 double old_value = g_socket_reuse_policy_penalty_coef;
694 g_socket_reuse_policy_penalty_coef =
695 policy == USE_WARMEST_SOCKET ? 0 :
696 (policy == USE_WARM_SOCKET ? 0.25 : -1);
697 DLOG(INFO) << "Setting g_socket_reuse_policy_penalty_coef = "
698 << g_socket_reuse_policy_penalty_coef;
699 // TODO(gagan): Remove this.
700 LOG(ERROR) << "Setting g_socket_reuse_policy_penalty_coef = "
701 << g_socket_reuse_policy_penalty_coef;
702 return old_value;
703 }
704
652 void ClientSocketPoolBaseHelper::EnableConnectBackupJobs() { 705 void ClientSocketPoolBaseHelper::EnableConnectBackupJobs() {
653 connect_backup_jobs_enabled_ = g_connect_backup_jobs_enabled; 706 connect_backup_jobs_enabled_ = g_connect_backup_jobs_enabled;
654 } 707 }
655 708
656 void ClientSocketPoolBaseHelper::IncrementIdleCount() { 709 void ClientSocketPoolBaseHelper::IncrementIdleCount() {
657 if (++idle_socket_count_ == 1) 710 if (++idle_socket_count_ == 1)
658 timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this, 711 timer_.Start(TimeDelta::FromSeconds(kCleanupInterval), this,
659 &ClientSocketPoolBaseHelper::OnCleanupTimerFired); 712 &ClientSocketPoolBaseHelper::OnCleanupTimerFired);
660 } 713 }
661 714
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 // Delete active jobs. 1134 // Delete active jobs.
1082 STLDeleteElements(&jobs_); 1135 STLDeleteElements(&jobs_);
1083 1136
1084 // Cancel pending backup job. 1137 // Cancel pending backup job.
1085 method_factory_.RevokeAll(); 1138 method_factory_.RevokeAll();
1086 } 1139 }
1087 1140
1088 } // namespace internal 1141 } // namespace internal
1089 1142
1090 } // namespace net 1143 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698