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

Side by Side Diff: webrtc/stats/rtcstatscollector.cc

Issue 2270033004: RTCStatsCollector collecting stats on multiple threads. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: (nits, no need to rerun bots yet) Created 4 years, 3 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 /* 1 /*
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/stats/rtcstatscollector.h" 11 #include "webrtc/stats/rtcstatscollector.h"
12 12
13 #include <memory> 13 #include <memory>
14 #include <utility> 14 #include <utility>
15 #include <vector> 15 #include <vector>
16 16
17 #include "webrtc/api/peerconnection.h" 17 #include "webrtc/api/peerconnection.h"
18 #include "webrtc/base/checks.h" 18 #include "webrtc/base/checks.h"
19 19
20 namespace webrtc { 20 namespace webrtc {
21 21
22 rtc::scoped_refptr<RTCStatsCollector> RTCStatsCollector::Create(
23 PeerConnection* pc,
24 double cache_lifetime,
25 std::unique_ptr<rtc::Timing> timing) {
26 return rtc::scoped_refptr<RTCStatsCollector>(
27 new rtc::RefCountedObject<RTCStatsCollector>(
28 pc, cache_lifetime, timing.release()));
29 }
30
22 RTCStatsCollector::RTCStatsCollector( 31 RTCStatsCollector::RTCStatsCollector(
23 PeerConnection* pc, 32 PeerConnection* pc,
24 double cache_lifetime, 33 double cache_lifetime,
25 std::unique_ptr<rtc::Timing> timing) 34 rtc::Timing* timing)
26 : pc_(pc), 35 : pc_(pc),
27 timing_(std::move(timing)), 36 signaling_thread_(pc->session()->signaling_thread()),
37 worker_thread_(pc->session()->worker_thread()),
38 network_thread_(pc->session()->network_thread()),
39 num_pending_partial_reports_(0),
40 timing_(timing),
28 cache_timestamp_(0.0), 41 cache_timestamp_(0.0),
29 cache_lifetime_(cache_lifetime) { 42 cache_lifetime_(cache_lifetime) {
30 RTC_DCHECK(pc_); 43 RTC_DCHECK(pc_);
44 RTC_DCHECK(signaling_thread_);
45 RTC_DCHECK(worker_thread_);
46 RTC_DCHECK(network_thread_);
31 RTC_DCHECK(timing_); 47 RTC_DCHECK(timing_);
32 RTC_DCHECK(IsOnSignalingThread());
33 RTC_DCHECK_GE(cache_lifetime_, 0.0); 48 RTC_DCHECK_GE(cache_lifetime_, 0.0);
34 } 49 }
35 50
36 rtc::scoped_refptr<const RTCStatsReport> RTCStatsCollector::GetStatsReport() { 51 void RTCStatsCollector::GetStatsReport(
37 RTC_DCHECK(IsOnSignalingThread()); 52 rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {
38 double now = timing_->TimerNow(); 53 RTC_DCHECK(signaling_thread_->IsCurrent());
39 if (cached_report_ && now - cache_timestamp_ <= cache_lifetime_) 54 RTC_DCHECK(callback);
40 return cached_report_; 55 rtc::scoped_refptr<const RTCStatsReport> cached_report;
41 cache_timestamp_ = now; 56 std::vector<rtc::scoped_refptr<RTCStatsCollectorCallback>> callbacks;
42 57 {
43 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create(); 58 rtc::CritScope cs(&lock_);
44 report->AddStats(ProducePeerConnectionStats()); 59 callbacks_.push_back(callback);
45 60 double now = timing_->TimerNow();
46 cached_report_ = report; 61 if (cached_report_ && now - cache_timestamp_ <= cache_lifetime_) {
47 return cached_report_; 62 // We have a fresh cached report to immediately deliver.
63 cached_report = cached_report_;
64 callbacks = callbacks_;
hta-webrtc 2016/08/31 09:57:36 So you use "callbacks" to pass the list of callbac
hbos 2016/09/01 14:16:16 Ah, only |num_pending_partial_reports_| and |parti
65 callbacks_.clear();
66 } else if (!num_pending_partial_reports_) {
67 // We don't have a fresh cached report and we are not already in the
68 // process of gathering stats.
69 num_pending_partial_reports_ = 3;
70 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
71 rtc::Bind(
72 &RTCStatsCollector::ProducePartialResultsOnSignalingThread_s,
73 rtc::scoped_refptr<RTCStatsCollector>(this), now));
74 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
75 rtc::Bind(&RTCStatsCollector::ProducePartialResultsOnWorkerThread_w,
76 rtc::scoped_refptr<RTCStatsCollector>(this), now));
77 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, network_thread_,
78 rtc::Bind(&RTCStatsCollector::ProducePartialResultsOnNetworkThread_n,
79 rtc::scoped_refptr<RTCStatsCollector>(this), now));
80 }
hta-webrtc 2016/08/31 09:57:36 Where's the "else" branch (the report isn't fresh
hbos 2016/09/01 14:16:16 callback_ has been added to callbacks_ and will be
81 }
82 // Do we have a cached report that is still fresh to deliver?
83 // Then do so without holding the lock.
84 if (cached_report) {
85 for (const rtc::scoped_refptr<RTCStatsCollectorCallback>& callback :
86 callbacks) {
87 callback->OnStatsDelivered(cached_report);
88 }
89 return;
90 }
48 } 91 }
49 92
50 void RTCStatsCollector::ClearCachedStatsReport() { 93 void RTCStatsCollector::ClearCachedStatsReport() {
51 RTC_DCHECK(IsOnSignalingThread()); 94 RTC_DCHECK(signaling_thread_->IsCurrent());
95 rtc::CritScope cs(&lock_);
52 cached_report_ = nullptr; 96 cached_report_ = nullptr;
53 } 97 }
54 98
55 bool RTCStatsCollector::IsOnSignalingThread() const { 99 void RTCStatsCollector::ProducePartialResultsOnSignalingThread_s(
56 return pc_->session()->signaling_thread()->IsCurrent(); 100 double timestamp) {
101 RTC_DCHECK(signaling_thread_->IsCurrent());
102 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create();
103
104 report->AddStats(ProducePeerConnectionStats_s(timestamp));
105
106 AddPartialResults(report, timestamp);
107 }
108
109 void RTCStatsCollector::ProducePartialResultsOnWorkerThread_w(
110 double timestamp) {
111 RTC_DCHECK(worker_thread_->IsCurrent());
112 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create();
113
114 // TODO(hbos): Gather stats on worker thread.
115
116 AddPartialResults(report, timestamp);
117 }
118
119 void RTCStatsCollector::ProducePartialResultsOnNetworkThread_n(
120 double timestamp) {
121 RTC_DCHECK(network_thread_->IsCurrent());
122 rtc::scoped_refptr<RTCStatsReport> report = RTCStatsReport::Create();
123
124 // TODO(hbos): Gather stats on network thread.
125
126 AddPartialResults(report, timestamp);
127 }
128
129 void RTCStatsCollector::AddPartialResults(
130 const rtc::scoped_refptr<RTCStatsReport>& partial_report,
131 double timestamp) {
132 if (!signaling_thread_->IsCurrent()) {
133 invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
134 rtc::Bind(&RTCStatsCollector::AddPartialResults_s,
135 rtc::scoped_refptr<RTCStatsCollector>(this),
136 partial_report, timestamp));
137 return;
138 }
139 AddPartialResults_s(partial_report, timestamp);
140 }
141
142 void RTCStatsCollector::AddPartialResults_s(
143 rtc::scoped_refptr<RTCStatsReport> partial_report, double timestamp) {
144 RTC_DCHECK(signaling_thread_->IsCurrent());
145 rtc::scoped_refptr<const RTCStatsReport> result;
146 std::vector<rtc::scoped_refptr<RTCStatsCollectorCallback>> callbacks;
147 {
148 rtc::CritScope cs(&lock_);
149 RTC_DCHECK_GT(num_pending_partial_reports_, 0);
150 if (!partial_report_)
151 partial_report_ = partial_report;
152 else
153 partial_report_->TakeMembersFrom(partial_report);
154 --num_pending_partial_reports_;
155
156 // Was this the last pending partial report, resulting in a complete and
157 // deliverable |result|?
158 if (!num_pending_partial_reports_) {
159 result = cached_report_ = partial_report_;
160 cache_timestamp_ = timestamp;
161 partial_report_ = nullptr;
162 callbacks = callbacks_;
163 callbacks_.clear();
164 }
165 }
166 // Do we have a report to deliver? Then do so without holding the lock.
167 if (result) {
168 for (const rtc::scoped_refptr<RTCStatsCollectorCallback>& callback :
169 callbacks) {
170 callback->OnStatsDelivered(result);
171 }
172 }
57 } 173 }
58 174
59 std::unique_ptr<RTCPeerConnectionStats> 175 std::unique_ptr<RTCPeerConnectionStats>
60 RTCStatsCollector::ProducePeerConnectionStats() const { 176 RTCStatsCollector::ProducePeerConnectionStats_s(double timestamp) const {
177 RTC_DCHECK(signaling_thread_->IsCurrent());
61 // TODO(hbos): If data channels are removed from the peer connection this will 178 // TODO(hbos): If data channels are removed from the peer connection this will
62 // yield incorrect counts. Address before closing crbug.com/636818. See 179 // yield incorrect counts. Address before closing crbug.com/636818. See
63 // https://w3c.github.io/webrtc-stats/webrtc-stats.html#pcstats-dict*. 180 // https://w3c.github.io/webrtc-stats/webrtc-stats.html#pcstats-dict*.
64 uint32_t data_channels_opened = 0; 181 uint32_t data_channels_opened = 0;
65 const std::vector<rtc::scoped_refptr<DataChannel>>& data_channels = 182 const std::vector<rtc::scoped_refptr<DataChannel>>& data_channels =
66 pc_->sctp_data_channels(); 183 pc_->sctp_data_channels();
67 for (const rtc::scoped_refptr<DataChannel>& data_channel : data_channels) { 184 for (const rtc::scoped_refptr<DataChannel>& data_channel : data_channels) {
68 if (data_channel->state() == DataChannelInterface::kOpen) 185 if (data_channel->state() == DataChannelInterface::kOpen)
69 ++data_channels_opened; 186 ++data_channels_opened;
70 } 187 }
71 // There is always just one |RTCPeerConnectionStats| so its |id| can be a 188 // There is always just one |RTCPeerConnectionStats| so its |id| can be a
72 // constant. 189 // constant.
73 std::unique_ptr<RTCPeerConnectionStats> stats( 190 std::unique_ptr<RTCPeerConnectionStats> stats(
74 new RTCPeerConnectionStats("RTCPeerConnection", cache_timestamp_)); 191 new RTCPeerConnectionStats("RTCPeerConnection", timestamp));
75 stats->data_channels_opened = data_channels_opened; 192 stats->data_channels_opened = data_channels_opened;
76 stats->data_channels_closed = static_cast<uint32_t>(data_channels.size()) - 193 stats->data_channels_closed = static_cast<uint32_t>(data_channels.size()) -
77 data_channels_opened; 194 data_channels_opened;
78 return stats; 195 return stats;
79 } 196 }
80 197
81 } // namespace webrtc 198 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698