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

Unified Diff: content/renderer/p2p/ipc_socket_factory.cc

Issue 14559005: Replace send packet throttling with a scheme based on number of in-flight bytes in IpcPacketSocket. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/renderer/p2p/ipc_socket_factory.cc
diff --git a/content/renderer/p2p/ipc_socket_factory.cc b/content/renderer/p2p/ipc_socket_factory.cc
index 3fd0556a1881370425fd466b1c7dc43411b9f4dd..6aaa12b9ab00e155ab201d0323a39edbebcbf8f0 100644
--- a/content/renderer/p2p/ipc_socket_factory.cc
+++ b/content/renderer/p2p/ipc_socket_factory.cc
@@ -4,6 +4,8 @@
#include "content/renderer/p2p/ipc_socket_factory.h"
+#include <deque>
+
#include "base/compiler_specific.h"
#include "base/debug/trace_event.h"
#include "base/message_loop.h"
@@ -17,9 +19,8 @@ namespace content {
namespace {
-// TODO(hclam): This shouldn't be a pre-defined value. Bug: crbug.com/181321.
-const int kMaxPendingPackets = 32;
-const int kWritableSignalThreshold = 0;
+// TODO(miu): This probably needs tuning. http://crbug.com/237960
+const size_t kMaximumInFlightBytes = 256 << 10; // 256 KB
Alpha Left Google 2013/05/04 07:14:14 This limit should be small. M27 limit is 40KB. We
miu 2013/05/06 19:21:26 I agree with you. One problem, though: When sendi
// IpcPacketSocket implements talk_base::AsyncPacketSocket interface
// using P2PSocketClient that works over IPC-channel. It must be used
@@ -66,6 +67,15 @@ class IpcPacketSocket : public talk_base::AsyncPacketSocket,
IS_ERROR,
};
+ // Reset send throttling mechanism to initial (i.e., no packets in-flight)
+ // state.
+ void ResetSendThrottling();
+
+ // Update trace of send throttling internal state. This should be called
+ // immediately after any changes to |token_bucket_level_| and/or
+ // |in_flight_packet_sizes_|.
+ void TraceSendThrottlingState() const;
+
void InitAcceptedTcp(P2PSocketClient* client,
const talk_base::SocketAddress& local_address,
const talk_base::SocketAddress& remote_address);
@@ -89,9 +99,13 @@ class IpcPacketSocket : public talk_base::AsyncPacketSocket,
// Current state of the object.
InternalState state_;
- // Number which have been sent to the browser, but for which we haven't
- // received response.
- int send_packets_pending_;
+ // A token bucket of bytes is used to throttle the sending of packets to the
+ // browser process. As calls to OnSendComplete() return, the bucket is
+ // refilled. This allows short bursts of high-rate sending without dropping
+ // packets, but quickly restricts the client to a sustainable steady-state
+ // rate.
+ size_t token_bucket_level_;
+ std::deque<size_t> in_flight_packet_sizes_;
// Set to true once EWOULDBLOCK was returned from Send(). Indicates that the
// caller expects SignalWritable notification.
@@ -107,8 +121,6 @@ IpcPacketSocket::IpcPacketSocket()
: type_(P2P_SOCKET_UDP),
message_loop_(MessageLoop::current()),
state_(IS_UNINITIALIZED),
- send_packets_pending_(0),
- writable_signal_expected_(false),
error_(0) {
}
@@ -119,6 +131,20 @@ IpcPacketSocket::~IpcPacketSocket() {
}
}
+void IpcPacketSocket::ResetSendThrottling() {
+ COMPILE_ASSERT(kMaximumInFlightBytes > 0, would_send_at_zero_rate);
+ token_bucket_level_ = kMaximumInFlightBytes;
+ in_flight_packet_sizes_.clear();
+ TraceSendThrottlingState();
+ writable_signal_expected_ = false;
+}
+
+void IpcPacketSocket::TraceSendThrottlingState() const {
+ TRACE_COUNTER1("p2p", "P2PSendBytesAvailable", token_bucket_level_);
+ TRACE_COUNTER1("p2p", "P2PSendPacketsInFlight",
+ in_flight_packet_sizes_.size());
+}
+
bool IpcPacketSocket::Init(P2PSocketType type, P2PSocketClient* client,
const talk_base::SocketAddress& local_address,
const talk_base::SocketAddress& remote_address) {
@@ -158,6 +184,7 @@ void IpcPacketSocket::InitAcceptedTcp(
local_address_ = local_address;
remote_address_ = remote_address;
state_ = IS_OPEN;
+ ResetSendThrottling();
client_->set_delegate(this);
}
@@ -196,24 +223,29 @@ int IpcPacketSocket::SendTo(const void *data, size_t data_size,
break;
}
- if (send_packets_pending_ > kMaxPendingPackets) {
- TRACE_EVENT_INSTANT1("p2p", "MaxPendingPacketsWouldBlock",
+ if (data_size == 0)
+ return 0; // No-op.
+
+ if (data_size > token_bucket_level_) {
+ TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
TRACE_EVENT_SCOPE_THREAD, "id", client_->socket_id());
writable_signal_expected_ = true;
error_ = EWOULDBLOCK;
return -1;
}
- const char* data_char = reinterpret_cast<const char*>(data);
- std::vector<char> data_vector(data_char, data_char + data_size);
-
net::IPEndPoint address_chrome;
if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) {
NOTREACHED();
return -1;
}
- ++send_packets_pending_;
+ token_bucket_level_ -= data_size;
Alpha Left Google 2013/05/04 04:11:20 I'm not sure how this helps. data_size is always
Alpha Left Google 2013/05/04 07:14:14 An alternative is to do this decrement with a dela
miu 2013/05/06 19:21:26 Exactly. That's what I thought we had discussed o
miu 2013/05/06 19:21:26 The two are identical approaches, except that the
+ in_flight_packet_sizes_.push_back(data_size);
+ TraceSendThrottlingState();
+
+ const char* data_char = reinterpret_cast<const char*>(data);
+ std::vector<char> data_vector(data_char, data_char + data_size);
client_->Send(address_chrome, data_vector);
// Fake successful send. The caller ignores result anyway.
@@ -287,6 +319,7 @@ void IpcPacketSocket::OnOpen(const net::IPEndPoint& address) {
}
state_ = IS_OPEN;
+ ResetSendThrottling();
SignalAddressReady(this, local_address_);
if (type_ == P2P_SOCKET_TCP_CLIENT)
@@ -312,11 +345,21 @@ void IpcPacketSocket::OnIncomingTcpConnection(
void IpcPacketSocket::OnSendComplete() {
DCHECK_EQ(MessageLoop::current(), message_loop_);
- --send_packets_pending_;
- DCHECK_GE(send_packets_pending_, 0);
+ if (in_flight_packet_sizes_.empty()) {
+ NOTREACHED() << "Received SendComplete() with no known in-flight packets.";
+ // In production builds, auto-recover by resetting the throttling state.
Alpha Left Google 2013/05/04 04:11:20 How is it related to production builds?
miu 2013/05/06 19:21:26 Wrong wording on my part. I meant: s/production/r
+ const bool signal_expected = writable_signal_expected_;
+ ResetSendThrottling();
+ if (signal_expected)
+ SignalReadyToSend(this);
+ return;
+ }
+ token_bucket_level_ += in_flight_packet_sizes_.front();
+ DCHECK_LE(token_bucket_level_, kMaximumInFlightBytes);
+ in_flight_packet_sizes_.pop_front();
+ TraceSendThrottlingState();
- if (writable_signal_expected_ &&
- send_packets_pending_ <= kWritableSignalThreshold) {
+ if (writable_signal_expected_ && token_bucket_level_ > 0) {
SignalReadyToSend(this);
writable_signal_expected_ = false;
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698