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

Side by Side Diff: content/renderer/p2p/ipc_socket_factory.cc

Issue 677473002: Implement UMA and internal data structure for tracking EWOULDBLOCK. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/renderer/p2p/ipc_socket_factory.h" 5 #include "content/renderer/p2p/ipc_socket_factory.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <deque> 8 #include <deque>
9 9
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/debug/trace_event.h" 11 #include "base/debug/trace_event.h"
12 #include "base/message_loop/message_loop.h" 12 #include "base/message_loop/message_loop.h"
13 #include "base/message_loop/message_loop_proxy.h" 13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/metrics/histogram.h"
14 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
15 #include "base/threading/non_thread_safe.h" 16 #include "base/threading/non_thread_safe.h"
16 #include "content/renderer/media/webrtc_logging.h" 17 #include "content/renderer/media/webrtc_logging.h"
17 #include "content/renderer/p2p/host_address_request.h" 18 #include "content/renderer/p2p/host_address_request.h"
18 #include "content/renderer/p2p/socket_client_delegate.h" 19 #include "content/renderer/p2p/socket_client_delegate.h"
19 #include "content/renderer/p2p/socket_client_impl.h" 20 #include "content/renderer/p2p/socket_client_impl.h"
20 #include "content/renderer/p2p/socket_dispatcher.h" 21 #include "content/renderer/p2p/socket_dispatcher.h"
21 #include "jingle/glue/utils.h" 22 #include "jingle/glue/utils.h"
22 #include "third_party/webrtc/base/asyncpacketsocket.h" 23 #include "third_party/webrtc/base/asyncpacketsocket.h"
23 24
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 108
108 private: 109 private:
109 enum InternalState { 110 enum InternalState {
110 IS_UNINITIALIZED, 111 IS_UNINITIALIZED,
111 IS_OPENING, 112 IS_OPENING,
112 IS_OPEN, 113 IS_OPEN,
113 IS_CLOSED, 114 IS_CLOSED,
114 IS_ERROR, 115 IS_ERROR,
115 }; 116 };
116 117
118 void IncrementDiscardCounters(uint32 size);
Alexei Svitkine (slow) 2014/10/27 17:45:21 This should have a comment. What is |size|?
guoweis2 2014/10/27 18:07:07 Done.
119
117 // Update trace of send throttling internal state. This should be called 120 // Update trace of send throttling internal state. This should be called
118 // immediately after any changes to |send_bytes_available_| and/or 121 // immediately after any changes to |send_bytes_available_| and/or
119 // |in_flight_packet_sizes_|. 122 // |in_flight_packet_sizes_|.
120 void TraceSendThrottlingState() const; 123 void TraceSendThrottlingState() const;
121 124
122 void InitAcceptedTcp(P2PSocketClient* client, 125 void InitAcceptedTcp(P2PSocketClient* client,
123 const rtc::SocketAddress& local_address, 126 const rtc::SocketAddress& local_address,
124 const rtc::SocketAddress& remote_address); 127 const rtc::SocketAddress& remote_address);
125 128
126 int DoSetOption(P2PSocketOption option, int value); 129 int DoSetOption(P2PSocketOption option, int value);
(...skipping 27 matching lines...) Expand all
154 std::deque<size_t> in_flight_packet_sizes_; 157 std::deque<size_t> in_flight_packet_sizes_;
155 158
156 // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the 159 // Set to true once EWOULDBLOCK was returned from Send(). Indicates that the
157 // caller expects SignalWritable notification. 160 // caller expects SignalWritable notification.
158 bool writable_signal_expected_; 161 bool writable_signal_expected_;
159 162
160 // Current error code. Valid when state_ == IS_ERROR. 163 // Current error code. Valid when state_ == IS_ERROR.
161 int error_; 164 int error_;
162 int options_[P2P_SOCKET_OPT_MAX]; 165 int options_[P2P_SOCKET_OPT_MAX];
163 166
167 // Track the maximum & current consecutive bytes discarded due to not enough
168 // send_bytes_available_.
169 uint32 max_discard_bytes_sequence_;
170 uint32 cur_discard_bytes_sequence_;
171
172 // Track total count of packet drops and attempt of packet sends.
173 uint32 packets_discarded_;
174 uint32 total_packets_;
175
164 DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket); 176 DISALLOW_COPY_AND_ASSIGN(IpcPacketSocket);
165 }; 177 };
166 178
167 // Simple wrapper around P2PAsyncAddressResolver. The main purpose of this 179 // Simple wrapper around P2PAsyncAddressResolver. The main purpose of this
168 // class is to send SignalDone, after OnDone callback from 180 // class is to send SignalDone, after OnDone callback from
169 // P2PAsyncAddressResolver. Libjingle sig slots are not thread safe. In case 181 // P2PAsyncAddressResolver. Libjingle sig slots are not thread safe. In case
170 // of MT sig slots clients must call disconnect. This class is to make sure 182 // of MT sig slots clients must call disconnect. This class is to make sure
171 // we destruct from the same thread on which is created. 183 // we destruct from the same thread on which is created.
172 class AsyncAddressResolverImpl : public base::NonThreadSafe, 184 class AsyncAddressResolverImpl : public base::NonThreadSafe,
173 public rtc::AsyncResolverInterface { 185 public rtc::AsyncResolverInterface {
(...skipping 14 matching lines...) Expand all
188 int port_; // Port number in |addr| from Start() method. 200 int port_; // Port number in |addr| from Start() method.
189 std::vector<rtc::IPAddress> addresses_; // Resolved addresses. 201 std::vector<rtc::IPAddress> addresses_; // Resolved addresses.
190 }; 202 };
191 203
192 IpcPacketSocket::IpcPacketSocket() 204 IpcPacketSocket::IpcPacketSocket()
193 : type_(P2P_SOCKET_UDP), 205 : type_(P2P_SOCKET_UDP),
194 message_loop_(base::MessageLoop::current()), 206 message_loop_(base::MessageLoop::current()),
195 state_(IS_UNINITIALIZED), 207 state_(IS_UNINITIALIZED),
196 send_bytes_available_(kMaximumInFlightBytes), 208 send_bytes_available_(kMaximumInFlightBytes),
197 writable_signal_expected_(false), 209 writable_signal_expected_(false),
198 error_(0) { 210 error_(0),
211 max_discard_bytes_sequence_(0),
212 cur_discard_bytes_sequence_(0),
213 packets_discarded_(0),
214 total_packets_(0) {
199 COMPILE_ASSERT(kMaximumInFlightBytes > 0, would_send_at_zero_rate); 215 COMPILE_ASSERT(kMaximumInFlightBytes > 0, would_send_at_zero_rate);
200 std::fill_n(options_, static_cast<int> (P2P_SOCKET_OPT_MAX), 216 std::fill_n(options_, static_cast<int> (P2P_SOCKET_OPT_MAX),
201 kDefaultNonSetOptionValue); 217 kDefaultNonSetOptionValue);
202 } 218 }
203 219
204 IpcPacketSocket::~IpcPacketSocket() { 220 IpcPacketSocket::~IpcPacketSocket() {
205 if (state_ == IS_OPENING || state_ == IS_OPEN || 221 if (state_ == IS_OPENING || state_ == IS_OPEN ||
206 state_ == IS_ERROR) { 222 state_ == IS_ERROR) {
207 Close(); 223 Close();
208 } 224 }
225
226 UMA_HISTOGRAM_COUNTS_10000("WebRTC.MaxApplicationConsecutiveBytesDiscard",
227 max_discard_bytes_sequence_);
228
229 if (total_packets_ > 0) {
230 UMA_HISTOGRAM_PERCENTAGE("WebRTC.PacketDiscardByApplication",
231 ((static_cast<double>(packets_discarded_)) /
232 (static_cast<double>(total_packets_)) * 100.0));
Alexei Svitkine (slow) 2014/10/27 17:45:21 The usual way to do this is: (packets_discarded_
guoweis2 2014/10/27 18:07:07 Done.
233 }
209 } 234 }
210 235
211 void IpcPacketSocket::TraceSendThrottlingState() const { 236 void IpcPacketSocket::TraceSendThrottlingState() const {
212 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(), 237 TRACE_COUNTER_ID1("p2p", "P2PSendBytesAvailable", local_address_.port(),
213 send_bytes_available_); 238 send_bytes_available_);
214 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(), 239 TRACE_COUNTER_ID1("p2p", "P2PSendPacketsInFlight", local_address_.port(),
215 in_flight_packet_sizes_.size()); 240 in_flight_packet_sizes_.size());
216 } 241 }
217 242
243 void IpcPacketSocket::IncrementDiscardCounters(uint32 size) {
244 cur_discard_bytes_sequence_ += size;
245 packets_discarded_++;
246
247 if (cur_discard_bytes_sequence_ > max_discard_bytes_sequence_) {
248 max_discard_bytes_sequence_ = cur_discard_bytes_sequence_;
249 }
250 }
251
218 bool IpcPacketSocket::Init(P2PSocketType type, 252 bool IpcPacketSocket::Init(P2PSocketType type,
219 P2PSocketClientImpl* client, 253 P2PSocketClientImpl* client,
220 const rtc::SocketAddress& local_address, 254 const rtc::SocketAddress& local_address,
221 const rtc::SocketAddress& remote_address) { 255 const rtc::SocketAddress& remote_address) {
222 DCHECK_EQ(base::MessageLoop::current(), message_loop_); 256 DCHECK_EQ(base::MessageLoop::current(), message_loop_);
223 DCHECK_EQ(state_, IS_UNINITIALIZED); 257 DCHECK_EQ(state_, IS_UNINITIALIZED);
224 258
225 type_ = type; 259 type_ = type;
226 client_ = client; 260 client_ = client;
227 local_address_ = local_address; 261 local_address_ = local_address;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 case IS_OPEN: 343 case IS_OPEN:
310 // Continue sending the packet. 344 // Continue sending the packet.
311 break; 345 break;
312 } 346 }
313 347
314 if (data_size == 0) { 348 if (data_size == 0) {
315 NOTREACHED(); 349 NOTREACHED();
316 return 0; 350 return 0;
317 } 351 }
318 352
353 total_packets_++;
354
319 if (data_size > send_bytes_available_) { 355 if (data_size > send_bytes_available_) {
320 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock", 356 TRACE_EVENT_INSTANT1("p2p", "MaxPendingBytesWouldBlock",
321 TRACE_EVENT_SCOPE_THREAD, 357 TRACE_EVENT_SCOPE_THREAD,
322 "id", 358 "id",
323 client_->GetSocketID()); 359 client_->GetSocketID());
324 if (!writable_signal_expected_) { 360 if (!writable_signal_expected_) {
325 WebRtcLogMessage(base::StringPrintf( 361 WebRtcLogMessage(base::StringPrintf(
326 "IpcPacketSocket: sending is blocked. %d packets_in_flight.", 362 "IpcPacketSocket: sending is blocked. %d packets_in_flight.",
327 static_cast<int>(in_flight_packet_sizes_.size()))); 363 static_cast<int>(in_flight_packet_sizes_.size())));
328 364
329 writable_signal_expected_ = true; 365 writable_signal_expected_ = true;
330 } 366 }
331 367
332 error_ = EWOULDBLOCK; 368 error_ = EWOULDBLOCK;
369 IncrementDiscardCounters(data_size);
333 return -1; 370 return -1;
371 } else {
372 cur_discard_bytes_sequence_ = 0;
334 } 373 }
335 374
336 net::IPEndPoint address_chrome; 375 net::IPEndPoint address_chrome;
337 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) { 376 if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) {
338 NOTREACHED(); 377 NOTREACHED();
339 error_ = EINVAL; 378 error_ = EINVAL;
340 return -1; 379 return -1;
341 } 380 }
342 381
343 send_bytes_available_ -= data_size; 382 send_bytes_available_ -= data_size;
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 } 709 }
671 710
672 rtc::AsyncResolverInterface* 711 rtc::AsyncResolverInterface*
673 IpcPacketSocketFactory::CreateAsyncResolver() { 712 IpcPacketSocketFactory::CreateAsyncResolver() {
674 scoped_ptr<AsyncAddressResolverImpl> resolver( 713 scoped_ptr<AsyncAddressResolverImpl> resolver(
675 new AsyncAddressResolverImpl(socket_dispatcher_)); 714 new AsyncAddressResolverImpl(socket_dispatcher_));
676 return resolver.release(); 715 return resolver.release();
677 } 716 }
678 717
679 } // namespace content 718 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698