Warmth of a connection (cwnd) is estimated by the amount of data written to the socket. 
Choosing the warmest connection would mean faster resource load times. 

idle time is the time a socket has remained idle (no http requests being served on it). 
Probability of server resetting a connection increases with idle time duration. 

Using a cost function that takes into account bytes transferred and idle time to pick best connection to schedule http requests on.

CODEREVIEW done in http://codereview.chromium.org/6990036/

Contributed by [email protected]

Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=90373

Reverted: http://codereview.chromium.org/7255002 :(

Have fixed 2 things since:
1. Removed LOG(ERROR) from http_basic_stream.cc that was causing layout tests to fail.
2. Initialized class variables in http_basic_stream.cc that was causing uninitialized memory bugs in valgrind: http://code.google.com/p/chromium/issues/detail?id=87423

Review URL: http://codereview.chromium.org/7251004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90601 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index ddcbba6..d39890b 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -4,11 +4,14 @@
 
 #include "net/socket/client_socket_pool_base.h"
 
+#include <math.h>
 #include "base/compiler_specific.h"
 #include "base/format_macros.h"
+#include "base/logging.h"
 #include "base/message_loop.h"
 #include "base/metrics/stats_counters.h"
 #include "base/stl_util-inl.h"
+#include "base/string_number_conversions.h"
 #include "base/string_util.h"
 #include "base/time.h"
 #include "base/values.h"
@@ -32,10 +35,33 @@
 // after a certain timeout has passed without receiving an ACK.
 bool g_connect_backup_jobs_enabled = true;
 
+double g_socket_reuse_policy_penalty_exponent = -1;
+int g_socket_reuse_policy = -1;
+
 }  // namespace
 
 namespace net {
 
+int GetSocketReusePolicy() {
+  return g_socket_reuse_policy;
+}
+
+void SetSocketReusePolicy(int policy) {
+  DCHECK_GE(policy, 0);
+  DCHECK_LE(policy, 2);
+  if (policy > 2 || policy < 0) {
+    LOG(ERROR) << "Invalid socket reuse policy";
+    return;
+  }
+
+  double exponents[] = { 0, 0.25, -1 };
+  g_socket_reuse_policy_penalty_exponent = exponents[policy];
+  g_socket_reuse_policy = policy;
+
+  VLOG(1) << "Setting g_socket_reuse_policy_penalty_exponent = "
+          << g_socket_reuse_policy_penalty_exponent;
+}
+
 ConnectJob::ConnectJob(const std::string& group_name,
                        base::TimeDelta timeout_duration,
                        Delegate* delegate,
@@ -363,6 +389,7 @@
     const Request* request, Group* group) {
   std::list<IdleSocket>* idle_sockets = group->mutable_idle_sockets();
   std::list<IdleSocket>::iterator idle_socket_it = idle_sockets->end();
+  double max_score = -1;
 
   // Iterate through the idle sockets forwards (oldest to newest)
   //   * Delete any disconnected ones.
@@ -379,7 +406,22 @@
 
     if (it->socket->WasEverUsed()) {
       // We found one we can reuse!
-      idle_socket_it = it;
+      double score = 0;
+      int64 bytes_read = it->socket->NumBytesRead();
+      double num_kb = static_cast<double>(bytes_read) / 1024.0;
+      int idle_time_sec = (base::TimeTicks::Now() - it->start_time).InSeconds();
+      idle_time_sec = std::max(1, idle_time_sec);
+
+      if (g_socket_reuse_policy_penalty_exponent >= 0 && num_kb >= 0) {
+        score = num_kb / pow(idle_time_sec,
+                             g_socket_reuse_policy_penalty_exponent);
+      }
+
+      // Equality to prefer recently used connection.
+      if (score >= max_score) {
+        idle_socket_it = it;
+        max_score = score;
+      }
     }
 
     ++it;