Index: webrtc/system_wrappers/source/metrics_default.cc |
diff --git a/webrtc/system_wrappers/source/metrics_default.cc b/webrtc/system_wrappers/source/metrics_default.cc |
index 48c9111e1b817397d91d7b140055fadbdcbdb75a..fa4eac7a4ec943d614af33914ceefc017be39b86 100644 |
--- a/webrtc/system_wrappers/source/metrics_default.cc |
+++ b/webrtc/system_wrappers/source/metrics_default.cc |
@@ -7,6 +7,10 @@ |
// be found in the AUTHORS file in the root of the source tree. |
// |
+#include "webrtc/system_wrappers/include/metrics_default.h" |
+ |
+#include "webrtc/base/criticalsection.h" |
+#include "webrtc/base/thread_annotations.h" |
#include "webrtc/system_wrappers/include/metrics.h" |
// Default implementation of histogram methods for WebRTC clients that do not |
@@ -14,16 +18,192 @@ |
namespace webrtc { |
namespace metrics { |
+class Histogram; |
+ |
+namespace { |
+// Limit for the maximum number of sample values that can be stored. |
+// TODO(asapersson): Consider using bucket count (and set up |
+// linearly/exponentially spaced buckets) if samples are logged more frequently. |
pbos-webrtc
2016/05/09 21:21:13
Note that this would be done for performance reaso
åsapersson
2016/05/13 09:15:53
Acknowledged.
|
+const int kMaxSampleMapSize = 2500; |
+ |
+class RtcHistogram { |
+ public: |
+ RtcHistogram(const std::string& name, int min, int max, int bucket_count) |
+ : info_(name, min, max, bucket_count) { |
+ RTC_CHECK_GT(bucket_count, 0); |
+ } |
+ ~RtcHistogram() {} |
+ |
+ int NumSamples() const { |
+ int num_samples = 0; |
+ rtc::CritScope cs(&crit_); |
+ for (const auto& sample : info_.samples) { |
+ num_samples += sample.second; |
+ } |
+ return num_samples; |
+ } |
+ |
+ int MinSample() const { |
+ rtc::CritScope cs(&crit_); |
+ if (info_.samples.empty()) { |
+ return -1; |
+ } |
+ return info_.samples.begin()->first; |
+ } |
+ |
+ int NumEvents(int sample) const { |
+ rtc::CritScope cs(&crit_); |
+ const auto it = info_.samples.find(sample); |
+ if (it == info_.samples.end()) { |
+ return 0; |
+ } |
+ return it->second; |
+ } |
+ |
+ void Add(int sample) { |
+ if (sample < info_.min) |
+ sample = info_.min - 1; // Underflow bucket. |
+ if (sample > info_.max) |
+ sample = info_.max; |
+ |
+ rtc::CritScope cs(&crit_); |
+ if (info_.samples.size() == kMaxSampleMapSize && |
+ info_.samples.find(sample) == info_.samples.end()) { |
+ return; |
+ } |
+ ++info_.samples[sample]; |
+ } |
+ |
+ // Clears samples. |
+ void Reset() { |
+ rtc::CritScope cs(&crit_); |
+ info_.samples.clear(); |
+ } |
+ |
+ // Returns a copy (or nullptr if there are no samples) and clears samples. |
+ SampleInfo* GetAndReset() { |
pbos-webrtc
2016/05/09 21:21:13
Should this return a std::unique_ptr?
åsapersson
2016/05/13 09:15:53
Done.
|
+ rtc::CritScope cs(&crit_); |
+ if (info_.samples.empty()) |
+ return nullptr; |
+ |
+ SampleInfo* copy = |
+ new SampleInfo(info_.name, info_.min, info_.max, info_.bucket_count); |
+ copy->samples = info_.samples; |
+ info_.samples.clear(); |
+ return copy; |
+ } |
+ |
+ const std::string& name() const { return info_.name; } |
+ |
+ private: |
+ rtc::CriticalSection crit_; |
+ SampleInfo info_; |
+ |
+ RTC_DISALLOW_COPY_AND_ASSIGN(RtcHistogram); |
+}; |
+ |
+// Map holding samples of a histogram (mapped by the histogram name). |
+bool rtc_histograms_enabled_ = false; |
+rtc::CriticalSection rtc_histograms_crit_; |
juberti2
2016/05/10 05:29:33
non-pod data at global scope is not allowed..
åsapersson
2016/05/13 09:15:53
Done.
|
+std::map<std::string, std::unique_ptr<RtcHistogram>> rtc_histograms_ |
+ GUARDED_BY(rtc_histograms_crit_); |
+} // namespace |
-Histogram* HistogramFactoryGetCounts(const std::string& name, int min, int max, |
- int bucket_count) { return NULL; } |
+// Implementation of histogram methods in |
+// webrtc/system_wrappers/interface/metrics.h. |
+// Histogram with exponentially spaced buckets. |
+Histogram* HistogramFactoryGetCounts(const std::string& name, |
+ int min, |
+ int max, |
+ int bucket_count) { |
+ rtc::CritScope cs(&rtc_histograms_crit_); |
+ if (rtc_histograms_.find(name) == rtc_histograms_.end()) { |
+ rtc_histograms_[name].reset(new RtcHistogram(name, min, max, bucket_count)); |
+ } |
+ const auto& it = rtc_histograms_.find(name); |
+ return reinterpret_cast<Histogram*>(it->second.get()); |
+} |
+ |
+// Histogram with linearly spaced buckets. |
Histogram* HistogramFactoryGetEnumeration(const std::string& name, |
- int boundary) { return NULL; } |
+ int boundary) { |
+ rtc::CritScope cs(&rtc_histograms_crit_); |
+ if (rtc_histograms_.find(name) == rtc_histograms_.end()) { |
+ rtc_histograms_[name].reset( |
+ new RtcHistogram(name, 1, boundary, boundary + 1)); |
+ } |
+ const auto& it = rtc_histograms_.find(name); |
+ return reinterpret_cast<Histogram*>(it->second.get()); |
+} |
+ |
+void HistogramAdd(Histogram* histogram_pointer, |
+ const std::string& name, |
+ int sample) { |
+ if (!rtc_histograms_enabled_) |
+ return; |
+ |
+ RtcHistogram* ptr = reinterpret_cast<RtcHistogram*>(histogram_pointer); |
+ RTC_DCHECK_EQ(name, ptr->name()) << "The name should not vary."; |
+ ptr->Add(sample); |
+} |
+ |
+SampleInfo::SampleInfo(const std::string& name, |
+ int min, |
+ int max, |
+ size_t bucket_count) |
+ : name(name), min(min), max(max), bucket_count(bucket_count) {} |
+ |
+SampleInfo::~SampleInfo() {} |
+ |
+// Implementation of global functions in metrics_default.h. |
+void Enable() { |
+ rtc_histograms_enabled_ = true; |
+} |
+ |
+void GetAndReset( |
+ std::map<std::string, std::unique_ptr<SampleInfo>>* histograms) { |
+ histograms->clear(); |
+ rtc::CritScope cs(&rtc_histograms_crit_); |
+ for (const auto& kv : rtc_histograms_) { |
+ SampleInfo* info = kv.second->GetAndReset(); |
+ if (info) |
+ (*histograms)[kv.first].reset(info); |
+ } |
+} |
-void HistogramAdd( |
- Histogram* histogram_pointer, const std::string& name, int sample) {} |
+void Reset() { |
+ rtc::CritScope cs(&rtc_histograms_crit_); |
+ for (const auto& kv : rtc_histograms_) |
+ kv.second->Reset(); |
+} |
+ |
+int NumEvents(const std::string& name, int sample) { |
+ rtc::CritScope cs(&rtc_histograms_crit_); |
+ const auto& it = rtc_histograms_.find(name); |
+ if (it == rtc_histograms_.end()) |
+ return 0; |
+ |
+ return it->second->NumEvents(sample); |
+} |
+ |
+int NumSamples(const std::string& name) { |
+ rtc::CritScope cs(&rtc_histograms_crit_); |
+ const auto& it = rtc_histograms_.find(name); |
+ if (it == rtc_histograms_.end()) |
+ return 0; |
+ |
+ return it->second->NumSamples(); |
+} |
+ |
+int MinSample(const std::string& name) { |
+ rtc::CritScope cs(&rtc_histograms_crit_); |
+ const auto& it = rtc_histograms_.find(name); |
+ if (it == rtc_histograms_.end()) |
+ return -1; |
+ |
+ return it->second->MinSample(); |
+} |
} // namespace metrics |
} // namespace webrtc |
- |