diff options
author | jar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-25 20:29:45 +0000 |
---|---|---|
committer | jar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-25 20:29:45 +0000 |
commit | 9b5614aec311bc0d04416b1fa279e496cca84714 (patch) | |
tree | ef89c857a897d45a8540aa0a84252a4a9329b83a /net | |
parent | 4055f9a6cd7de30e99288aa1f51b42276a93e705 (diff) | |
download | chromium_src-9b5614aec311bc0d04416b1fa279e496cca84714.zip chromium_src-9b5614aec311bc0d04416b1fa279e496cca84714.tar.gz chromium_src-9b5614aec311bc0d04416b1fa279e496cca84714.tar.bz2 |
Gather preconnection use vs waste statistics
I now gather statistics only in the transport socket
classes TcpClientSocket*. All other socket classes
forward significant data (that they are used in
a speculation) to their transport class, where
this data is stored, and then dumped when the
TCP socket is closed.
This CL also repaired a slight miscount in bytes
read and written on Windows, as error codes
were mistakenly accumulated as byte counts.
This CL repaired a significant undercounting
in linux/mac via StatsCounter (the logging counter
appears correct).
Libjingle support is minimal (NOTREACHED), but
I don't know that there are subresources that will
be speculatively preconnected from that class (and
it is less obvious how the class uses underlying
sockets, if at all).
BUG=42694
r=willchan
Review URL: http://codereview.chromium.org/3163033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57377 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
23 files changed, 265 insertions, 82 deletions
diff --git a/net/http/http_proxy_client_socket.cc b/net/http/http_proxy_client_socket.cc index 76882fa..16f6e28 100644 --- a/net/http/http_proxy_client_socket.cc +++ b/net/http/http_proxy_client_socket.cc @@ -174,6 +174,22 @@ bool HttpProxyClientSocket::IsConnectedAndIdle() const { transport_->socket()->IsConnectedAndIdle(); } +void HttpProxyClientSocket::SetSubresourceSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetSubresourceSpeculation(); + } else { + NOTREACHED(); + } +} + +void HttpProxyClientSocket::SetOmniboxSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetOmniboxSpeculation(); + } else { + NOTREACHED(); + } +} + int HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len, CompletionCallback* callback) { DCHECK(!user_callback_); diff --git a/net/http/http_proxy_client_socket.h b/net/http/http_proxy_client_socket.h index 93afafa..488fbdc 100644 --- a/net/http/http_proxy_client_socket.h +++ b/net/http/http_proxy_client_socket.h @@ -65,6 +65,8 @@ class HttpProxyClientSocket : public ClientSocket { virtual bool IsConnected() const; virtual bool IsConnectedAndIdle() const; virtual const BoundNetLog& NetLog() const { return net_log_; } + virtual void SetSubresourceSpeculation(); + virtual void SetOmniboxSpeculation(); // Socket methods: virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); diff --git a/net/socket/client_socket.cc b/net/socket/client_socket.cc index 7722c64..aba0366 100644 --- a/net/socket/client_socket.cc +++ b/net/socket/client_socket.cc @@ -9,17 +9,18 @@ namespace net { -ClientSocket::ClientSocket() +ClientSocket::UseHistory::UseHistory() : was_ever_connected_(false), + was_used_to_convey_data_(false), omnibox_speculation_(false), - subresource_speculation_(false), - was_used_to_transmit_data_(false) {} + subresource_speculation_(false) { +} -ClientSocket::~ClientSocket() { +ClientSocket::UseHistory::~UseHistory() { EmitPreconnectionHistograms(); } -void ClientSocket::EmitPreconnectionHistograms() const { +void ClientSocket::UseHistory::EmitPreconnectionHistograms() const { DCHECK(!subresource_speculation_ || !omnibox_speculation_); // 0 ==> non-speculative, never connected. // 1 ==> non-speculative never used (but connected). @@ -31,7 +32,7 @@ void ClientSocket::EmitPreconnectionHistograms() const { // 7 ==> subresource_speculative never used (but connected). // 8 ==> subresource_speculative and used. int result; - if (was_used_to_transmit_data_) + if (was_used_to_convey_data_) result = 2; else if (was_ever_connected_) result = 1; @@ -42,37 +43,55 @@ void ClientSocket::EmitPreconnectionHistograms() const { result += 3; else if (subresource_speculation_) result += 6; + UMA_HISTOGRAM_ENUMERATION("Net.PreconnectUtilization2", result, 9); static const bool connect_backup_jobs_fieldtrial = FieldTrialList::Find("ConnnectBackupJobs") && !FieldTrialList::Find("ConnnectBackupJobs")->group_name().empty(); if (connect_backup_jobs_fieldtrial) { UMA_HISTOGRAM_ENUMERATION( - FieldTrial::MakeName("Net.PreconnectUtilization", "ConnnectBackupJobs"), + FieldTrial::MakeName("Net.PreconnectUtilization2", + "ConnnectBackupJobs"), result, 9); } } -void ClientSocket::SetSubresourceSpeculation() { - if (was_used_to_transmit_data_) +void ClientSocket::UseHistory::set_was_ever_connected() { + DCHECK(!was_used_to_convey_data_); + was_ever_connected_ = true; +} + +void ClientSocket::UseHistory::set_was_used_to_convey_data() { + DCHECK(was_ever_connected_); + was_used_to_convey_data_ = true; +} + + +void ClientSocket::UseHistory::set_subresource_speculation() { + DCHECK(was_ever_connected_); + // TODO(jar): We should transition to marking a socket (or stream) at + // construction time as being created for speculative reasons. This current + // approach of trying to track use of a socket to convey data can make + // mistakes when other sockets (such as ones sitting in the pool for a long + // time) are issued. Unused sockets can be left over when a when a set of + // connections to a host are made, and one is "unlucky" and takes so long to + // complete a connection, that another socket is used, and recycled before a + // second connection comes available. Similarly, re-try connections can leave + // an original (slow to connect socket) in the pool, and that can be issued + // to a speculative requester. In any cases such old sockets will fail when an + // attempt is made to used them!... and then it will look like a speculative + // socket was discarded without any user!?!?! + if (was_used_to_convey_data_) return; subresource_speculation_ = true; } -void ClientSocket::SetOmniboxSpeculation() { - if (was_used_to_transmit_data_) +void ClientSocket::UseHistory::set_omnibox_speculation() { + DCHECK(was_ever_connected_); + if (was_used_to_convey_data_) return; omnibox_speculation_ = true; } -void ClientSocket::UpdateConnectivityState(bool is_reused) { - // Record if this connection has every actually connected successfully. - // Note that IsConnected() won't be defined at destruction time, so we need - // to record this data now, while the derived class is present. - was_ever_connected_ |= IsConnected(); - // A socket is_reused only after it has transmitted some data. - was_used_to_transmit_data_ |= is_reused; -} - } // namespace net diff --git a/net/socket/client_socket.h b/net/socket/client_socket.h index 44ee085..6a4fb31 100644 --- a/net/socket/client_socket.h +++ b/net/socket/client_socket.h @@ -15,25 +15,7 @@ class BoundNetLog; class ClientSocket : public Socket { public: - ClientSocket(); - - // Destructor emits statistics for this socket's lifetime. - virtual ~ClientSocket(); - - // Set the annotation to indicate this socket was created for speculative - // reasons. Note that if the socket was used before calling this method, then - // the call will be ignored (no annotation will be added). - void SetSubresourceSpeculation(); - void SetOmniboxSpeculation(); - - // Establish values of was_ever_connected_ and was_used_to_transmit_data_. - // The argument indicates if the socket's state, as reported by a - // ClientSocketHandle::is_reused(), should show that the socket has already - // been used to transmit data. - // This is typically called when a transaction finishes, and - // ClientSocketHandle is being destroyed. Calling at that point it allows us - // to aggregates the impact of that connect job into this instance. - void UpdateConnectivityState(bool is_reused); + virtual ~ClientSocket() {} // Called to establish a connection. Returns OK if the connection could be // established synchronously. Otherwise, ERR_IO_PENDING is returned and the @@ -75,23 +57,47 @@ class ClientSocket : public Socket { // Gets the NetLog for this socket. virtual const BoundNetLog& NetLog() const = 0; - private: - // Publish histogram to help evaluate preconnection utilization. - void EmitPreconnectionHistograms() const; - - // Indicate if any ClientSocketHandle that used this socket was connected as - // would be indicated by the IsConnected() method. This variable set by a - // ClientSocketHandle before releasing this ClientSocket. - bool was_ever_connected_; - - // Indicate if this socket was first created for speculative use, and identify - // the motivation. - bool omnibox_speculation_; - bool subresource_speculation_; - - // Indicate if this socket was ever used. This state is set by a - // ClientSocketHandle before releasing this ClientSocket. - bool was_used_to_transmit_data_; + // Set the annotation to indicate this socket was created for speculative + // reasons. This call is generally fowarded to a basic TCPClientSocket*, + // where a UseHistory can be updated. + virtual void SetSubresourceSpeculation() = 0; + virtual void SetOmniboxSpeculation() = 0; + + protected: + // The following class is only used to gather statistics about the history of + // a socket. It is only instantiated and used in basic sockets, such as + // TCPClientSocket* instances. Other classes that are derived from + // ClientSocket should forward any potential settings to their underlying + // transport sockets. + class UseHistory { + public: + UseHistory(); + ~UseHistory(); + + void set_was_ever_connected(); + void set_was_used_to_convey_data(); + + // The next two setters only have any impact if the socket has not yet been + // used to transmit data. If called later, we assume that the socket was + // reused from the pool, and was NOT constructed to service a speculative + // request. + void set_subresource_speculation(); + void set_omnibox_speculation(); + + private: + // Summarize the statistics for this socket. + void EmitPreconnectionHistograms() const; + // Indicate if this was ever connected. + bool was_ever_connected_; + // Indicate if this socket was ever used to transmit or receive data. + bool was_used_to_convey_data_; + + // Indicate if this socket was first created for speculative use, and + // identify the motivation. + bool omnibox_speculation_; + bool subresource_speculation_; + DISALLOW_COPY_AND_ASSIGN(UseHistory); + }; }; } // namespace net diff --git a/net/socket/client_socket_handle.cc b/net/socket/client_socket_handle.cc index ee7c233..d9ccbd5 100644 --- a/net/socket/client_socket_handle.cc +++ b/net/socket/client_socket_handle.cc @@ -22,7 +22,6 @@ ClientSocketHandle::ClientSocketHandle() ClientSocketHandle::~ClientSocketHandle() { Reset(); - UpdateConnectivityStateForSocket(); } void ClientSocketHandle::Reset() { diff --git a/net/socket/client_socket_handle.h b/net/socket/client_socket_handle.h index c9d636b..e3e6cfb 100644 --- a/net/socket/client_socket_handle.h +++ b/net/socket/client_socket_handle.h @@ -132,10 +132,7 @@ class ClientSocketHandle { const std::string& group_name() const { return group_name_; } int id() const { return pool_id_; } ClientSocket* socket() { return socket_.get(); } - ClientSocket* release_socket() { - UpdateConnectivityStateForSocket(); - return socket_.release(); - } + ClientSocket* release_socket() { return socket_.release(); } bool is_reused() const { return is_reused_; } base::TimeDelta idle_time() const { return idle_time_; } SocketReuseType reuse_type() const { @@ -164,15 +161,6 @@ class ClientSocketHandle { // Resets the supplemental error state. void ResetErrorState(); - // Update the base class to record things like whether we've ever transmitted - // data, and whether the connection was able to be established. We use this - // data to construct histograms indicating whether a speculative connection - // was ever used, etc., when the ClientSocket is eventually discarded. - void UpdateConnectivityStateForSocket() const { - if (socket_.get()) - socket_->UpdateConnectivityState(is_reused()); - } - bool is_initialized_; scoped_refptr<ClientSocketPool> pool_; scoped_ptr<ClientSocket> socket_; diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc index 89db61d..2a78fb1 100644 --- a/net/socket/client_socket_pool_base_unittest.cc +++ b/net/socket/client_socket_pool_base_unittest.cc @@ -76,6 +76,9 @@ class MockClientSocket : public ClientSocket { return net_log_; } + virtual void SetSubresourceSpeculation() {} + virtual void SetOmniboxSpeculation() {} + private: bool connected_; BoundNetLog net_log_; diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 31bbea2..b712215 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h @@ -516,6 +516,8 @@ class MockClientSocket : public net::SSLClientSocket { virtual bool IsConnectedAndIdle() const; virtual int GetPeerAddress(AddressList* address) const; virtual const BoundNetLog& NetLog() const { return net_log_;} + virtual void SetSubresourceSpeculation() {} + virtual void SetOmniboxSpeculation() {} // SSLClientSocket methods: virtual void GetSSLInfo(net::SSLInfo* ssl_info); diff --git a/net/socket/socks5_client_socket.cc b/net/socket/socks5_client_socket.cc index 9c9ecbe..0af7b9b 100644 --- a/net/socket/socks5_client_socket.cc +++ b/net/socket/socks5_client_socket.cc @@ -106,6 +106,22 @@ bool SOCKS5ClientSocket::IsConnectedAndIdle() const { return completed_handshake_ && transport_->socket()->IsConnectedAndIdle(); } +void SOCKS5ClientSocket::SetSubresourceSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetSubresourceSpeculation(); + } else { + NOTREACHED(); + } +} + +void SOCKS5ClientSocket::SetOmniboxSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetOmniboxSpeculation(); + } else { + NOTREACHED(); + } +} + // Read is called by the transport layer above to read. This can only be done // if the SOCKS handshake is complete. int SOCKS5ClientSocket::Read(IOBuffer* buf, int buf_len, diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h index c2a1793..ac0dd74 100644 --- a/net/socket/socks5_client_socket.h +++ b/net/socket/socks5_client_socket.h @@ -56,6 +56,8 @@ class SOCKS5ClientSocket : public ClientSocket { virtual bool IsConnected() const; virtual bool IsConnectedAndIdle() const; virtual const BoundNetLog& NetLog() const { return net_log_; } + virtual void SetSubresourceSpeculation(); + virtual void SetOmniboxSpeculation(); // Socket methods: virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); diff --git a/net/socket/socks_client_socket.cc b/net/socket/socks_client_socket.cc index 2000754..c38021f 100644 --- a/net/socket/socks_client_socket.cc +++ b/net/socket/socks_client_socket.cc @@ -141,6 +141,22 @@ bool SOCKSClientSocket::IsConnectedAndIdle() const { return completed_handshake_ && transport_->socket()->IsConnectedAndIdle(); } +void SOCKSClientSocket::SetSubresourceSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetSubresourceSpeculation(); + } else { + NOTREACHED(); + } +} + +void SOCKSClientSocket::SetOmniboxSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetOmniboxSpeculation(); + } else { + NOTREACHED(); + } +} + // Read is called by the transport layer above to read. This can only be done // if the SOCKS handshake is complete. int SOCKSClientSocket::Read(IOBuffer* buf, int buf_len, diff --git a/net/socket/socks_client_socket.h b/net/socket/socks_client_socket.h index 515f337..af28574 100644 --- a/net/socket/socks_client_socket.h +++ b/net/socket/socks_client_socket.h @@ -53,6 +53,8 @@ class SOCKSClientSocket : public ClientSocket { virtual bool IsConnected() const; virtual bool IsConnectedAndIdle() const; virtual const BoundNetLog& NetLog() const { return net_log_; } + virtual void SetSubresourceSpeculation(); + virtual void SetOmniboxSpeculation(); // Socket methods: virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); diff --git a/net/socket/ssl_client_socket_mac.cc b/net/socket/ssl_client_socket_mac.cc index 4ee9c23..63e8171 100644 --- a/net/socket/ssl_client_socket_mac.cc +++ b/net/socket/ssl_client_socket_mac.cc @@ -591,6 +591,22 @@ int SSLClientSocketMac::GetPeerAddress(AddressList* address) const { return transport_->socket()->GetPeerAddress(address); } +void SSLClientSocketMac::SetSubresourceSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetSubresourceSpeculation(); + } else { + NOTREACHED(); + } +} + +void SSLClientSocketMac::SetOmniboxSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetOmniboxSpeculation(); + } else { + NOTREACHED(); + } +} + int SSLClientSocketMac::Read(IOBuffer* buf, int buf_len, CompletionCallback* callback) { DCHECK(completed_handshake_); diff --git a/net/socket/ssl_client_socket_mac.h b/net/socket/ssl_client_socket_mac.h index 5166b33..26a270c 100644 --- a/net/socket/ssl_client_socket_mac.h +++ b/net/socket/ssl_client_socket_mac.h @@ -47,6 +47,8 @@ class SSLClientSocketMac : public SSLClientSocket { virtual bool IsConnectedAndIdle() const; virtual int GetPeerAddress(AddressList* address) const; virtual const BoundNetLog& NetLog() const { return net_log_; } + virtual void SetSubresourceSpeculation(); + virtual void SetOmniboxSpeculation(); // Socket methods: virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 7b23b26..44b5e1f 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -658,6 +658,22 @@ int SSLClientSocketNSS::GetPeerAddress(AddressList* address) const { return transport_->socket()->GetPeerAddress(address); } +void SSLClientSocketNSS::SetSubresourceSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetSubresourceSpeculation(); + } else { + NOTREACHED(); + } +} + +void SSLClientSocketNSS::SetOmniboxSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetOmniboxSpeculation(); + } else { + NOTREACHED(); + } +} + int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len, CompletionCallback* callback) { EnterFunction(buf_len); diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h index 8e1e68d..315e142 100644 --- a/net/socket/ssl_client_socket_nss.h +++ b/net/socket/ssl_client_socket_nss.h @@ -54,6 +54,8 @@ class SSLClientSocketNSS : public SSLClientSocket { virtual bool IsConnectedAndIdle() const; virtual int GetPeerAddress(AddressList* address) const; virtual const BoundNetLog& NetLog() const { return net_log_; } + virtual void SetSubresourceSpeculation(); + virtual void SetOmniboxSpeculation(); // Socket methods: virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); diff --git a/net/socket/ssl_client_socket_win.cc b/net/socket/ssl_client_socket_win.cc index 38bdfce..cb6e91e 100644 --- a/net/socket/ssl_client_socket_win.cc +++ b/net/socket/ssl_client_socket_win.cc @@ -629,6 +629,22 @@ int SSLClientSocketWin::GetPeerAddress(AddressList* address) const { return transport_->socket()->GetPeerAddress(address); } +void SSLClientSocketWin::SetSubresourceSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetSubresourceSpeculation(); + } else { + NOTREACHED(); + } +} + +void SSLClientSocketWin::SetOmniboxSpeculation() { + if (transport_.get() && transport_->socket()) { + transport_->socket()->SetOmniboxSpeculation(); + } else { + NOTREACHED(); + } +} + int SSLClientSocketWin::Read(IOBuffer* buf, int buf_len, CompletionCallback* callback) { DCHECK(completed_handshake()); diff --git a/net/socket/ssl_client_socket_win.h b/net/socket/ssl_client_socket_win.h index a44dca7..44a5374 100644 --- a/net/socket/ssl_client_socket_win.h +++ b/net/socket/ssl_client_socket_win.h @@ -51,6 +51,8 @@ class SSLClientSocketWin : public SSLClientSocket { virtual bool IsConnectedAndIdle() const; virtual int GetPeerAddress(AddressList* address) const; virtual const BoundNetLog& NetLog() const { return net_log_; } + virtual void SetSubresourceSpeculation(); + virtual void SetOmniboxSpeculation(); // Socket methods: virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); diff --git a/net/socket/tcp_client_socket_libevent.cc b/net/socket/tcp_client_socket_libevent.cc index 55c4190..a63528b 100644 --- a/net/socket/tcp_client_socket_libevent.cc +++ b/net/socket/tcp_client_socket_libevent.cc @@ -233,8 +233,10 @@ int TCPClientSocketLibevent::DoConnectComplete(int result) { write_socket_watcher_.StopWatchingFileDescriptor(); - if (result == OK) + if (result == OK) { + use_history_.set_was_ever_connected(); return OK; // Done! + } // Close whatever partially connected socket we currently have. DoDisconnect(); @@ -320,7 +322,8 @@ int TCPClientSocketLibevent::Read(IOBuffer* buf, if (nread >= 0) { static StatsCounter read_bytes("tcp.read_bytes"); read_bytes.Add(nread); - + if (nread > 0) + use_history_.set_was_used_to_convey_data(); net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, new NetLogIntegerParameter("num_bytes", nread)); return nread; @@ -358,6 +361,8 @@ int TCPClientSocketLibevent::Write(IOBuffer* buf, if (nwrite >= 0) { static StatsCounter write_bytes("tcp.write_bytes"); write_bytes.Add(nwrite); + if (nwrite > 0) + use_history_.set_was_used_to_convey_data(); net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_SENT, new NetLogIntegerParameter("num_bytes", nwrite)); return nwrite; @@ -474,6 +479,10 @@ void TCPClientSocketLibevent::DidCompleteRead() { int result; if (bytes_transferred >= 0) { result = bytes_transferred; + static StatsCounter read_bytes("tcp.read_bytes"); + read_bytes.Add(bytes_transferred); + if (bytes_transferred > 0) + use_history_.set_was_used_to_convey_data(); net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, new NetLogIntegerParameter("num_bytes", result)); } else { @@ -497,6 +506,10 @@ void TCPClientSocketLibevent::DidCompleteWrite() { int result; if (bytes_transferred >= 0) { result = bytes_transferred; + static StatsCounter write_bytes("tcp.write_bytes"); + write_bytes.Add(bytes_transferred); + if (bytes_transferred > 0) + use_history_.set_was_used_to_convey_data(); net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_SENT, new NetLogIntegerParameter("num_bytes", result)); } else { @@ -520,4 +533,12 @@ int TCPClientSocketLibevent::GetPeerAddress(AddressList* address) const { return OK; } +void TCPClientSocketLibevent::SetSubresourceSpeculation() { + use_history_.set_subresource_speculation(); +} + +void TCPClientSocketLibevent::SetOmniboxSpeculation() { + use_history_.set_subresource_speculation(); +} + } // namespace net diff --git a/net/socket/tcp_client_socket_libevent.h b/net/socket/tcp_client_socket_libevent.h index ec4b5aa..8d68bff 100644 --- a/net/socket/tcp_client_socket_libevent.h +++ b/net/socket/tcp_client_socket_libevent.h @@ -40,6 +40,8 @@ class TCPClientSocketLibevent : public ClientSocket, NonThreadSafe { virtual bool IsConnectedAndIdle() const; virtual int GetPeerAddress(AddressList* address) const; virtual const BoundNetLog& NetLog() const { return net_log_; } + virtual void SetSubresourceSpeculation(); + virtual void SetOmniboxSpeculation(); // Socket methods: // Multiple outstanding requests are not supported. @@ -162,6 +164,10 @@ class TCPClientSocketLibevent : public ClientSocket, NonThreadSafe { BoundNetLog net_log_; + // Record of connectivity and transmissions, for use in speculative connection + // histograms. + UseHistory use_history_; + DISALLOW_COPY_AND_ASSIGN(TCPClientSocketLibevent); }; diff --git a/net/socket/tcp_client_socket_pool_unittest.cc b/net/socket/tcp_client_socket_pool_unittest.cc index 7c2df9a..5bcf7e1 100644 --- a/net/socket/tcp_client_socket_pool_unittest.cc +++ b/net/socket/tcp_client_socket_pool_unittest.cc @@ -50,6 +50,9 @@ class MockClientSocket : public ClientSocket { return net_log_; } + virtual void SetSubresourceSpeculation() {} + virtual void SetOmniboxSpeculation() {} + // Socket methods: virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback) { @@ -91,6 +94,9 @@ class MockFailingClientSocket : public ClientSocket { return net_log_; } + virtual void SetSubresourceSpeculation() {} + virtual void SetOmniboxSpeculation() {} + // Socket methods: virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback) { @@ -145,6 +151,9 @@ class MockPendingClientSocket : public ClientSocket { return net_log_; } + virtual void SetSubresourceSpeculation() {} + virtual void SetOmniboxSpeculation() {} + // Socket methods: virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback) { diff --git a/net/socket/tcp_client_socket_win.cc b/net/socket/tcp_client_socket_win.cc index d2f7e04..ed2cccb 100644 --- a/net/socket/tcp_client_socket_win.cc +++ b/net/socket/tcp_client_socket_win.cc @@ -414,8 +414,10 @@ int TCPClientSocketWin::DoConnectComplete(int result) { params = new NetLogIntegerParameter("os_error", os_error); net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, params); - if (result == OK) + if (result == OK) { + use_history_.set_was_ever_connected(); return OK; // Done! + } // Close whatever partially connected socket we currently have. DoDisconnect(); @@ -514,6 +516,14 @@ int TCPClientSocketWin::GetPeerAddress(AddressList* address) const { return OK; } +void TCPClientSocketWin::SetSubresourceSpeculation() { + use_history_.set_subresource_speculation(); +} + +void TCPClientSocketWin::SetOmniboxSpeculation() { + use_history_.set_subresource_speculation(); +} + int TCPClientSocketWin::Read(IOBuffer* buf, int buf_len, CompletionCallback* callback) { @@ -544,6 +554,8 @@ int TCPClientSocketWin::Read(IOBuffer* buf, base::MemoryDebug::MarkAsInitialized(core_->read_buffer_.buf, num); static StatsCounter read_bytes("tcp.read_bytes"); read_bytes.Add(num); + if (num > 0) + use_history_.set_was_used_to_convey_data(); net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, new NetLogIntegerParameter("num_bytes", num)); return static_cast<int>(num); @@ -570,8 +582,8 @@ int TCPClientSocketWin::Write(IOBuffer* buf, DCHECK_GT(buf_len, 0); DCHECK(!core_->write_iobuffer_); - static StatsCounter reads("tcp.writes"); - reads.Increment(); + static StatsCounter writes("tcp.writes"); + writes.Increment(); core_->write_buffer_.len = buf_len; core_->write_buffer_.buf = buf->data(); @@ -594,6 +606,8 @@ int TCPClientSocketWin::Write(IOBuffer* buf, } static StatsCounter write_bytes("tcp.write_bytes"); write_bytes.Add(rv); + if (rv > 0) + use_history_.set_was_used_to_convey_data(); net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_SENT, new NetLogIntegerParameter("num_bytes", rv)); return rv; @@ -698,9 +712,6 @@ void TCPClientSocketWin::DoReadCallback(int rv) { DCHECK_NE(rv, ERR_IO_PENDING); DCHECK(read_callback_); - static StatsCounter read_bytes("tcp.read_bytes"); - read_bytes.Add(rv); - // since Run may result in Read being called, clear read_callback_ up front. CompletionCallback* c = read_callback_; read_callback_ = NULL; @@ -711,9 +722,6 @@ void TCPClientSocketWin::DoWriteCallback(int rv) { DCHECK_NE(rv, ERR_IO_PENDING); DCHECK(write_callback_); - static StatsCounter write_bytes("tcp.write_bytes"); - write_bytes.Add(rv); - // since Run may result in Write being called, clear write_callback_ up front. CompletionCallback* c = write_callback_; write_callback_ = NULL; @@ -757,6 +765,10 @@ void TCPClientSocketWin::DidCompleteRead() { waiting_read_ = false; core_->read_iobuffer_ = NULL; if (ok) { + static StatsCounter read_bytes("tcp.read_bytes"); + read_bytes.Add(num_bytes); + if (num_bytes > 0) + use_history_.set_was_used_to_convey_data(); net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_RECEIVED, new NetLogIntegerParameter("num_bytes", num_bytes)); } @@ -784,6 +796,10 @@ void TCPClientSocketWin::DidCompleteWrite() { << " bytes reported."; rv = ERR_WINSOCK_UNEXPECTED_WRITTEN_BYTES; } else { + static StatsCounter write_bytes("tcp.write_bytes"); + write_bytes.Add(num_bytes); + if (num_bytes > 0) + use_history_.set_was_used_to_convey_data(); net_log_.AddEvent(NetLog::TYPE_SOCKET_BYTES_SENT, new NetLogIntegerParameter("num_bytes", rv)); } diff --git a/net/socket/tcp_client_socket_win.h b/net/socket/tcp_client_socket_win.h index 8940978..bd31960 100644 --- a/net/socket/tcp_client_socket_win.h +++ b/net/socket/tcp_client_socket_win.h @@ -28,7 +28,7 @@ class TCPClientSocketWin : public ClientSocket, NonThreadSafe { net::NetLog* net_log, const net::NetLog::Source& source); - ~TCPClientSocketWin(); + virtual ~TCPClientSocketWin(); // ClientSocket methods: virtual int Connect(CompletionCallback* callback); @@ -37,6 +37,8 @@ class TCPClientSocketWin : public ClientSocket, NonThreadSafe { virtual bool IsConnectedAndIdle() const; virtual int GetPeerAddress(AddressList* address) const; virtual const BoundNetLog& NetLog() const { return net_log_; } + virtual void SetSubresourceSpeculation(); + virtual void SetOmniboxSpeculation(); // Socket methods: // Multiple outstanding requests are not supported. @@ -114,6 +116,10 @@ class TCPClientSocketWin : public ClientSocket, NonThreadSafe { BoundNetLog net_log_; + // Record of connectivity and transmissions, for use in speculative connection + // histograms. + UseHistory use_history_; + DISALLOW_COPY_AND_ASSIGN(TCPClientSocketWin); }; |