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

Side by Side Diff: webrtc/base/analytics/percentile_filter.h

Issue 2529063002: Templatize percentile_filter.h and move it to base/analytics. (Closed)
Patch Set: Only allow removing the oldest element from PercentileFilter. Created 4 years 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
« no previous file with comments | « webrtc/base/BUILD.gn ('k') | webrtc/base/analytics/percentile_filter_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 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/modules/video_coding/percentile_filter.h" 11 #ifndef WEBRTC_BASE_ANALYTICS_PERCENTILE_FILTER_H_
12 #define WEBRTC_BASE_ANALYTICS_PERCENTILE_FILTER_H_
13
14 #include <stdint.h>
12 15
13 #include <iterator> 16 #include <iterator>
17 #include <list>
18 #include <set>
14 19
15 #include "webrtc/base/checks.h" 20 #include "webrtc/base/checks.h"
16 21
17 namespace webrtc { 22 namespace webrtc {
18 23
19 PercentileFilter::PercentileFilter(float percentile) 24 // Class to efficiently get the percentile value from a group of observations.
25 // The percentile is the value below which a given percentage of the
26 // observations fall.
27 template <typename T>
28 class PercentileFilter {
29 public:
30 // Construct filter. |percentile| should be between 0 and 1.
31 explicit PercentileFilter(float percentile);
32
33 // Insert one observation. The complexity of this operation is logarithmic in
34 // the size of the container.
35 void Push(const T& value);
36
37 // Remove the oldest observation. The complexity of this operation is
38 // logarithmic in the size of the container.
39 void Pop();
40
41 // Get the percentile value. The complexity of this operation is constant.
42 T GetPercentileValue() const;
43
44 // Returns the number of observations in the container.
45 size_t Size() const;
46
47 private:
48 // Update iterator and index to point at target percentile value.
49 void UpdatePercentileIterator();
50
51 const float percentile_;
52 std::list<typename std::multiset<T>::iterator> history_;
magjed_webrtc 2016/11/30 10:58:25 An std::queue seems more appropriate. Any reason f
53 std::multiset<T> set_;
54 // Maintain iterator and index of current target percentile value.
55 typename std::multiset<T>::iterator percentile_it_;
56 int64_t percentile_index_;
57 };
58
59 template <typename T>
60 PercentileFilter<T>::PercentileFilter(float percentile)
20 : percentile_(percentile), 61 : percentile_(percentile),
62 history_(),
63 set_(),
21 percentile_it_(set_.begin()), 64 percentile_it_(set_.begin()),
22 percentile_index_(0) { 65 percentile_index_(0) {
23 RTC_CHECK_GE(percentile, 0.0f); 66 RTC_CHECK_GE(percentile, 0.0f);
24 RTC_CHECK_LE(percentile, 1.0f); 67 RTC_CHECK_LE(percentile, 1.0f);
25 } 68 }
26 69
27 void PercentileFilter::Insert(const int64_t& value) { 70 template <typename T>
28 // Insert element at the upper bound. 71 void PercentileFilter<T>::Push(const T& value) {
29 set_.insert(value); 72 // Insert element at the upper bound. This means that each range of equal
73 // elements will be stored in the same order that they were inserted.
74 auto it = set_.insert(value);
75 history_.push_back(it);
30 if (set_.size() == 1u) { 76 if (set_.size() == 1u) {
31 // First element inserted - initialize percentile iterator and index. 77 // First element inserted - initialize percentile iterator and index.
32 percentile_it_ = set_.begin(); 78 percentile_it_ = set_.begin();
33 percentile_index_ = 0; 79 percentile_index_ = 0;
34 } else if (value < *percentile_it_) { 80 } else if (value < *percentile_it_) {
35 // If new element is before us, increment |percentile_index_|. 81 // If new element is before us, increment |percentile_index_|.
36 ++percentile_index_; 82 ++percentile_index_;
37 } 83 }
38 UpdatePercentileIterator(); 84 UpdatePercentileIterator();
39 } 85 }
40 86
41 void PercentileFilter::Erase(const int64_t& value) { 87 template <typename T>
42 std::multiset<int64_t>::const_iterator it = set_.lower_bound(value); 88 void PercentileFilter<T>::Pop() {
43 // Ignore erase operation if the element is not present in the current set. 89 RTC_DCHECK_GT(history_.size(), 0);
magjed_webrtc 2016/11/30 10:58:25 nit: I think this is cleaner and will give the sam
44 if (it == set_.end() || *it != value) 90 RTC_DCHECK_GT(set_.size(), 0);
45 return; 91 auto it = history_.front();
92 history_.pop_front();
46 if (it == percentile_it_) { 93 if (it == percentile_it_) {
47 // If same iterator, update to the following element. Index is not affected. 94 // If removing the percentile value, update iterator to the following
48 percentile_it_ = set_.erase(it); 95 // element. Index is not affected.
96 percentile_it_ = set_.erase(percentile_it_);
49 } else { 97 } else {
98 // If erased element is before percentile, decrement |percentile_index_|.
99 // Note that if the erased element compares equal to the percentile, but
100 // isn't the same iterator, then it has to be before the |percentile_index_|
101 // since each range of equal elements is stored in insertion order and we
102 // are erasing the oldest element.
103 if (*it <= *percentile_it_)
104 --percentile_index_;
50 set_.erase(it); 105 set_.erase(it);
51 // If erased element was before us, decrement |percentile_index_|.
52 if (value <= *percentile_it_)
53 --percentile_index_;
54 } 106 }
55 UpdatePercentileIterator(); 107 UpdatePercentileIterator();
56 } 108 }
57 109
58 void PercentileFilter::UpdatePercentileIterator() { 110 template <typename T>
111 void PercentileFilter<T>::UpdatePercentileIterator() {
59 if (set_.empty()) 112 if (set_.empty())
60 return; 113 return;
61 const int64_t index = static_cast<int64_t>(percentile_ * (set_.size() - 1)); 114 const int64_t index = static_cast<int64_t>(percentile_ * (set_.size() - 1));
62 std::advance(percentile_it_, index - percentile_index_); 115 std::advance(percentile_it_, index - percentile_index_);
63 percentile_index_ = index; 116 percentile_index_ = index;
64 } 117 }
65 118
66 int64_t PercentileFilter::GetPercentileValue() const { 119 template <typename T>
120 T PercentileFilter<T>::GetPercentileValue() const {
67 return set_.empty() ? 0 : *percentile_it_; 121 return set_.empty() ? 0 : *percentile_it_;
68 } 122 }
69 123
124 template <typename T>
125 size_t PercentileFilter<T>::Size() const {
126 RTC_DCHECK_EQ(set_.size(), history_.size());
127 return history_.size();
128 }
129
70 } // namespace webrtc 130 } // namespace webrtc
131
132 #endif // WEBRTC_BASE_ANALYTICS_PERCENTILE_FILTER_H_
OLDNEW
« no previous file with comments | « webrtc/base/BUILD.gn ('k') | webrtc/base/analytics/percentile_filter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698