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

Unified Diff: webrtc/p2p/base/p2ptransportchannel.cc

Issue 2369963004: Ping the premier connection on each network with higher priority. (Closed)
Patch Set: Add TODO for re-thinking prioritizing connections for ping requests. Created 4 years, 2 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
Index: webrtc/p2p/base/p2ptransportchannel.cc
diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc
index 6bcf0d7d2bfb09e9548501dccfde4e2ba249a5bd..99d81c40e033a83581bfeccde2cdb6b1599ce968 100644
--- a/webrtc/p2p/base/p2ptransportchannel.cc
+++ b/webrtc/p2p/base/p2ptransportchannel.cc
@@ -66,6 +66,8 @@ namespace cricket {
// well on a 28.8K modem, which is the slowest connection on which the voice
// quality is reasonable at all.
static const int PING_PACKET_SIZE = 60 * 8;
+
+// The next two ping intervals are at the channel level.
// STRONG_PING_INTERVAL (480ms) is applied when the selected connection is both
// writable and receiving.
static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000;
@@ -73,11 +75,13 @@ static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000;
// not writable or not receiving.
const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000;
-// Writable connections are pinged at a faster rate while stabilizing.
-const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms
-
-// Writable connections are pinged at a slower rate once stabilized.
-const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms
+// The next two ping intervals are at the connection level.
+// Writable connections are pinged at a faster rate while the connections are
+// stabilizing or the channel is weak.
+const int WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms
+// Writable connections are pinged at a slower rate once they are stabilized and
+// the channel is strongly connected.
+const int STRONG_AND_STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms
static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms
@@ -116,7 +120,7 @@ P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
DEFAULT_BACKUP_CONNECTION_PING_INTERVAL,
GATHER_ONCE /* continual_gathering_policy */,
false /* prioritize_most_likely_candidate_pairs */,
- STABLE_WRITABLE_CONNECTION_PING_INTERVAL,
+ STRONG_AND_STABLE_WRITABLE_CONNECTION_PING_INTERVAL,
true /* presume_writable_when_fully_relayed */,
DEFAULT_REGATHER_ON_FAILED_NETWORKS_INTERVAL,
RECEIVING_SWITCHING_DELAY) {
@@ -1305,6 +1309,24 @@ void P2PTransportChannel::SortConnectionsAndUpdateState() {
MaybeStartPinging();
}
+std::map<rtc::Network*, Connection*>
pthatcher1 2016/10/24 20:49:05 You don't need to return a map. You could instead
honghaiz3 2016/10/24 23:35:08 I wonder what was the concern about using a map. A
pthatcher1 2016/10/25 17:00:06 I thought it might be more readable. But what you
+P2PTransportChannel::GetPremierConnectionsByNetwork() const {
pthatcher1 2016/10/24 20:49:05 I'm not really a fan of the word "premier", since
honghaiz3 2016/10/24 23:35:08 Done. Changed Premier to best.
+ // |connections_| has been sorted, so the first one in the list on a given
+ // network is the premier connection, except that the selected connection
+ // is always the premier connection on the network.
+ std::map<rtc::Network*, Connection*> premier_connections_by_network;
+ if (selected_connection_) {
+ premier_connections_by_network[selected_connection_->port()->Network()] =
+ selected_connection_;
+ }
+ for (Connection* conn : connections_) {
+ rtc::Network* network = conn->port()->Network();
+ // This only inserts when the network does not exist in the map.
+ premier_connections_by_network.insert(std::make_pair(network, conn));
pthatcher1 2016/10/24 20:49:05 Instead of inserting in the map, you could just it
+ }
+ return premier_connections_by_network;
+}
+
void P2PTransportChannel::PruneConnections() {
// We can prune any connection for which there is a connected, writable
// connection on the same network with better or equal priority. We leave
@@ -1315,25 +1337,15 @@ void P2PTransportChannel::PruneConnections() {
// switch. If the |premier| connection is not connected, we may be
// reconnecting a TCP connection and temporarily do not prune connections in
// this network. See the big comment in CompareConnectionStates.
-
- // Get a list of the networks that we are using.
- std::set<rtc::Network*> networks;
- for (const Connection* conn : connections_) {
- networks.insert(conn->port()->Network());
- }
- for (rtc::Network* network : networks) {
- Connection* premier = GetBestConnectionOnNetwork(network);
- // Do not prune connections if the current selected connection is weak on
+ auto premier_connections_by_network = GetPremierConnectionsByNetwork();
+ for (Connection* conn : connections_) {
+ // Do not prune connections if the current premier connection is weak on
// this network. Otherwise, it may delete connections prematurely.
- if (!premier || premier->weak()) {
- continue;
- }
-
- for (Connection* conn : connections_) {
- if ((conn != premier) && (conn->port()->Network() == network) &&
- (CompareConnectionCandidates(premier, conn) >= 0)) {
- conn->Prune();
- }
+ Connection* premier =
+ premier_connections_by_network[conn->port()->Network()];
pthatcher1 2016/10/24 20:49:05 If GetBestConnectionForEachNetwork returns a vecto
honghaiz3 2016/10/24 23:35:09 Actually that is not enough. We will need to find
pthatcher1 2016/10/25 17:00:06 OK, I see the logic now.
+ if (premier && conn != premier && !premier->weak() &&
+ CompareConnectionCandidates(premier, conn) >= 0) {
+ conn->Prune();
}
}
}
@@ -1471,26 +1483,6 @@ bool P2PTransportChannel::ReadyToSend(Connection* connection) const {
PresumedWritable(connection));
}
-// If we have a selected connection, return it, otherwise return top one in the
-// list (later we will mark it best).
-Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
- rtc::Network* network) const {
- // If the selected connection is on this network, then it wins.
- if (selected_connection_ &&
- (selected_connection_->port()->Network() == network)) {
- return selected_connection_;
- }
-
- // Otherwise, we return the top-most in sorted order.
- for (size_t i = 0; i < connections_.size(); ++i) {
- if (connections_[i]->port()->Network() == network) {
- return connections_[i];
- }
- }
-
- return NULL;
-}
-
// Handle any queued up requests
void P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
switch (pmsg->message_id) {
@@ -1596,14 +1588,50 @@ bool P2PTransportChannel::IsPingable(const Connection* conn,
return (now >= conn->last_ping_sent() + ping_interval);
}
-bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) {
- if (!selected_connection_ || !selected_connection_->connected() ||
- !selected_connection_->writable()) {
+// TODO(honghaiz): Re-thinking the way of prioritizing connections for ping
+// requests.
+Connection* P2PTransportChannel::FindBestPremierConnectionToPing(int64_t now) {
pthatcher1 2016/10/24 20:49:05 Why not just put all of this logic into FindNextPi
honghaiz3 2016/10/24 23:35:09 Done.
+ // If the selected connection is pingable, select it to ping.
+ if (IsPremierConnectionPingable(selected_connection_, now)) {
+ return selected_connection_;
+ }
+ // If the selected connection is strongly connected, don't bother to ping
pthatcher1 2016/10/24 20:49:05 bother to ping => bother pinging
honghaiz3 2016/10/24 23:35:08 Done.
+ // premier connections on other networks at a higher priority. This prevents
+ // a few premier connections from saturating all transmission slots for ping
+ // and also prevents the backup connections from being pinged frequently.
+ if (!weak()) {
+ return nullptr;
+ }
+
+ // Otherwise, find the premier connection that has not been pinged for the
+ // longest time.
+ auto premier_connections_by_network = GetPremierConnectionsByNetwork();
+ Connection* oldest_pingable_premier_connection = nullptr;
+ for (auto kv : premier_connections_by_network) {
pthatcher1 2016/10/24 20:49:05 If GetBestConnectionForEachNetwork returned a vect
+ Connection* conn = kv.second;
+ if (conn == nullptr || conn == selected_connection_) {
+ continue;
+ }
+ if (IsPremierConnectionPingable(conn, now) &&
+ (!oldest_pingable_premier_connection ||
+ conn->last_ping_sent() <
+ oldest_pingable_premier_connection->last_ping_sent())) {
+ oldest_pingable_premier_connection = conn;
+ }
+ }
+ return oldest_pingable_premier_connection;
+}
+
+bool P2PTransportChannel::IsPremierConnectionPingable(
pthatcher1 2016/10/24 20:49:05 Can't this just be IsConnectionPingable?
honghaiz3 2016/10/24 23:35:09 No. In this method, it is critical to ping connect
pthatcher1 2016/10/25 17:00:06 What I mean is that since you're already passing i
Taylor Brandstetter 2016/10/25 18:29:28 Except there's a completely different method, "IsP
honghaiz3 2016/10/25 22:01:24 IsPremierConnectionPingable (now it is called IsPe
pthatcher1 2016/10/26 22:37:50 I agree with Taylor that this is confusing. IsPin
honghaiz3 2016/10/27 19:20:58 FindNextPingableConnection has the following steps
Taylor Brandstetter 2016/10/27 21:04:54 I had an idea similar to the "ping score" concept.
honghaiz3 2016/10/27 21:45:09 Note a few details: 1. The eligibility of a connec
+ Connection* premier_connection,
+ int64_t now) {
+ if (!premier_connection || !premier_connection->connected() ||
+ !premier_connection->writable()) {
return false;
}
- int interval = CalculateActiveWritablePingInterval(selected_connection_, now);
- return selected_connection_->last_ping_sent() + interval <= now;
+ int interval = CalculateActiveWritablePingInterval(premier_connection, now);
+ return premier_connection->last_ping_sent() + interval <= now;
}
int P2PTransportChannel::CalculateActiveWritablePingInterval(
@@ -1616,10 +1644,12 @@ int P2PTransportChannel::CalculateActiveWritablePingInterval(
}
int stable_interval = config_.stable_writable_connection_ping_interval;
- int stablizing_interval =
- std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL);
-
- return conn->stable(now) ? stable_interval : stablizing_interval;
+ int weak_or_stablizing_interval = std::min(
+ stable_interval, WEAK_OR_STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL);
+ // If the channel is weak or the connection is not stable yet, use the
+ // weak_or_stablizing_interval.
+ return (!weak() && conn->stable(now)) ? stable_interval
+ : weak_or_stablizing_interval;
}
// Returns the next pingable connection to ping. This will be the oldest
@@ -1631,10 +1661,8 @@ int P2PTransportChannel::CalculateActiveWritablePingInterval(
// CompareConnectionStates.
Connection* P2PTransportChannel::FindNextPingableConnection() {
int64_t now = rtc::TimeMillis();
- Connection* conn_to_ping = nullptr;
- if (IsSelectedConnectionPingable(now)) {
- conn_to_ping = selected_connection_;
- } else {
+ Connection* conn_to_ping = FindBestPremierConnectionToPing(now);
+ if (!conn_to_ping) {
conn_to_ping = FindConnectionToPing(now);
}
return conn_to_ping;
@@ -1749,8 +1777,9 @@ void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
unpinged_connections_.erase(*iter);
connections_.erase(iter);
- LOG_J(LS_INFO, this) << "Removed connection ("
- << static_cast<int>(connections_.size()) << " remaining)";
+ LOG_J(LS_INFO, this) << "Removed connection " << std::hex << connection
+ << std::dec << " (" << connections_.size()
+ << " remaining)";
// If this is currently the selected connection, then we need to pick a new
// one. The call to SortConnectionsAndUpdateState will pick a new one. It
@@ -1878,7 +1907,7 @@ void P2PTransportChannel::OnReadyToSend(Connection* connection) {
// Find "triggered checks". We ping first those connections that have
// received a ping but have not sent a ping since receiving it
-// (last_received_ping > last_sent_ping). But we shouldn't do
+// (last_ping_received > last_ping_sent). But we shouldn't do
// triggered checks if the connection is already writable.
Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck(
int64_t now) {

Powered by Google App Engine
This is Rietveld 408576698