Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/base/quantile_estimator.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "testing/gtest/include/gtest/gtest.h" | |
| 9 | |
| 10 namespace { | |
| 11 | |
| 12 // A number to turn sawtooth ramps from 0->100 into something that looks more | |
| 13 // random to the algorithm. | |
| 14 const int kPrimeMultipleToRandomizeRamps = 71; | |
| 15 | |
| 16 // Random numbers (fixed here for repeatability of tests). Generated originally | |
| 17 // by using python's random module with randrange(0,100). | |
| 18 int random_numbers[] = { | |
| 19 83, 11, 33, 98, 49, 54, 83, 19, 93, 37, 98, 39, 59, 13, 51, 39, 69, 18, 17, | |
| 20 17, 6, 85, 95, 51, 83, 39, 18, 82, 88, 47, 69, 27, 20, 82, 86, 38, 98, 65, | |
| 21 53, 13, 71, 66, 29, 40, 70, 28, 64, 35, 47, 50, 84, 90, 36, 54, 15, 93, 98, | |
| 22 51, 82, 50, 17, 46, 12, 18, 26, 39, 95, 61, 52, 63, 97, 92, 12, 71, 7, 15, | |
| 23 74, 10, 64, 57, 25, 82, 95, 40, 76, 8, 28, 83, 58, 1, 22, 58, 17, 33, 61, | |
| 24 94, 40, 50, 84, 47, 81, 9, 79, 16, 45, 78, 15, 3, 97, 60, 70, 25, 11, 11, | |
| 25 68, 64, 61, 84, 52, 64, 54, 72, 24, 46, 48, 4, 46, 34, 10, 97, 2, 42, 13, | |
| 26 9, 95, 75, 11, 99, 92, 33, 65, 48, 19, 72, 63, 39, 0, 10, 83, 62, 12, 99, | |
| 27 67, 98, 99, 83, 40, 45, 34, 80, 13, 94, 22, 74, 8, 11, 11, 98, 35, 86, 80, | |
| 28 94, 87, 60, 16, 46, 9, 25, 75, 50, 54, 23, 31, 63, 9, 50, 5, 18, 87, 16, | |
| 29 47, 72, 24, 93, 14, 1, 26, 41, 50, 49, 41, 77, 54, 48, 50, 3, 50, 16, 54, | |
| 30 97, 57, 63, 83, 33, 65, 90, 48, 55, 44, 11, 71, 6, 86, 29, 46, 61, 20, 8, | |
| 31 88, 3, 70, 76, 84, 59, 36, 50, 77, 63, 10, 55, 32, 82, 58, 19, 97, 8, 73, | |
| 32 47, 55, 74, 46, 52, 62, 19, 65, 75, 57, 23, 98, 39, 63, 19, 75, 48, 93, 58, | |
| 33 29, 96, 57, 31, 17, 33, 8, 69, 89, 90, 17, 79, 59, 67, 34, 20, 44, 80, 71, | |
| 34 79, 24, 63, 13, 27, 28, 61, 38, 67, 82, 46, 9, 4, 69, 41, 49, 49, 10, 3, | |
| 35 93, 46, 57, 96, 78, 51, 45, 37, 0, 6, 99, 93, 87, 18, 72, 83, 95, 39, 54, | |
| 36 84, 12, 47, 14, 55, 15, 27, 95, 6, 13, 80, 40, 8, 39, 18, 15, 52, 31, 66, | |
| 37 59, 67, 90, 12, 61, 77, 66, 61, 33, 89, 47, 40, 86, 34, 98, 13, 76, 30, 43, | |
| 38 56, 57, 88, 34, 48, 67, 6, 29, 92, 38, 11, 23, 74, 45, 38, 35, 94, 15, 72, | |
| 39 65, 20, 94, 72, 97, 78, 61, 79, 75, 0, 45, 38, 32, 94, 3, 5, 67, 91, 34, | |
| 40 37, 12, 11, 15, 75, 14, 73, 34, 55, 78, 64, 52, 29, 60, 62, 16, 51, 44, 78, | |
| 41 0, 15, 41, 5, 52, 4, 68, 53, 39, 39, 68, 71, 66, 68, 97, 65, 55, 39, 94, | |
| 42 57, 43, 81, 67, 22, 30, 64, 37, 42, 35, 60, 61, 2, 51, 49, 43, 82, 61, 70, | |
| 43 63, 47, 57, 8, 55, 96, 68, 7, 46, 69, 8, 43, 18, 9, 25, 8, 97, 98, 83, | |
| 44 79, 19, 92, 54, 90, 72, 80, 92, 94, 26, 48, 94, 74, 32, 29, 44, 34, 55, 56, | |
| 45 97, 40, 86, 35, 64, 25, 85, 13, 57, 2, 29, 77, 19, 94, 46, 85, 15, 71, 81, | |
| 46 25, 45, 2, 1, 62, 77, 28, 95, 72, 72, 28, 3, 36, 76, 81, 56, 52, 27, 62, | |
| 47 8, 5, 62, 1, 43, 68, 40, 68, 22, 65, 30, 50, 36, 89, 5, 71, 68, 99, 53, | |
| 48 22, 26, 0, 1, 72, 76, 79, 50, 2, 32, 39, 40, 6, 99, 60, 59, 55, 28, 17, | |
| 49 12, 94, 51, 3, 4, 71, 36, 88, 26, 99, 25, 13, 80, 53, 4, 57, 55, 44, 26, | |
| 50 82, 4, 53, 34, 47, 16, 97, 56, 30, 0, 73, 85, 59, 86, 24, 70, 73, 53, 68, | |
| 51 15, 91, 90, 74, 39, 61, 32, 98, 14, 82, 99, 31, 7, 99, 34, 6, 3, 30, 57, | |
| 52 44, 58, 86, 37, 12, 63, 82, 78, 94, 4, 93, 89, 92, 59, 40, 94, 88, 97, 95, | |
| 53 5, 88, 40, 80, 79, 0, 2, 46, 86, 46, 75, 87, 86, 8, 23, 35, 62, 79, 66, | |
| 54 16, 16, 45, 11, 78, 76, 40, 73, 85, 28, 44, 33, 34, 22, 11, 62, 8, 35, 88, | |
| 55 92, 35, 53, 50, 51, 54, 75, 41, 21, 83, 57, 82, 80, 84, 65, 19, 11, 85, 41, | |
| 56 80, 86, 62, 34, 54, 54, 79, 81, 52, 87, 54, 54, 43, 17, 44, 63, 54, 14, 88, | |
| 57 84, 86, 73, 58, 44, 2, 70, 86, 80, 94, 13, 85, 78, 6, 44, 11, 11, 97, 67, | |
| 58 65, 28, 42, 40, 84, 92, 66, 85, 75, 29, 84, 82, 54, 50, 26, 12, 83, 57, 90, | |
| 59 9, 40, 69, 38, 70, 65, 76, 85, 76, 4, 30, 86, 43, 79, 77, 69, 53, 35, 12, | |
| 60 98, 7, 47, 12, 63, 10, 81, 39, 88, 12, 16, 88, 22, 72, 25, 41, 22, 34, 87, | |
| 61 68, 51, 86, 45, 27, 51, 80, 69, 89, 64, 89, 68, 61, 80, 6, 83, 47, 18, 86, | |
| 62 73, 16, 61, 89, 47, 5, 33, 59, 47, 75, 15, 60, 28, 18, 59, 65, 51, 13, 28, | |
| 63 26, 84, 89, 80, 51, 15, 92, 36, 89, 83, 28, 56, 65, 25, 44, 84, 70, 26, 10, | |
| 64 74, 91, 55, 85, 73, 25, 24, 64, 11, 1, 55, 32, 45, 74, 4, 55, 98, 42, 91, | |
| 65 88, 18, 79, 37, 15, 5, 98, 63, 65, 77, 66, 18, 99, 1, 78, 96, 15, 16, 16, | |
| 66 51, 11, 47, 58, 1, 12, 46, 5, 56, 34, 40, 36, 20, 4, 89, 59, 4, 13, 3, | |
| 67 8, 74, 41, 21, 64, 88, 97, 42, 14, 29, 38, 53, 65, 55, 67, 33, 69, 17, 79, | |
| 68 45, 2, 63, 2, 97, 47, 73, 22, 86, 32, 31, 95, 90, 84, 25, 86, 91, 77, 1, | |
| 69 5, 6, 22, 91, 3, 94, 52, 2, 95, 17, 1, 19, 22, 34, 49, 96, 88, 63, 26, | |
| 70 5, 25, 75, 23, 25, 80, 21, 83, 86, 81, 11, 70, 67, 11, 95, 81, 57, 63, 8, | |
| 71 43, 60, 40, 42, 67, 50, 2, 51, 43, 34, 7, 1, 90, 59, 74, 87, 23, 23, 71, | |
| 72 20, 89, 2, 75, 21, 91, 32, 87, 67, 98, 99, 22, 31, 59, 50, 64, 55, 22, 84, | |
| 73 9, 31, 31, 84, 36, 92, 60, 37, 85, 18, 12, 38, 55, 55, 93, 36, 9, 46, 48, | |
| 74 24, 91, 60, 95, 55, 73, 63, 27, 55, 96, 79, 50, 41, 5, 67, 85, 99, 95, 3, | |
| 75 97, 28, 27, 78, 38, 11, 77, 11, 64, 25, 22, 88, 34, 86, 30, 78, 95, 17, 9, | |
| 76 29, 58, 35, 22, 99, 28, 66, 35, 60, 10, 7, 51, 64, 86, 30, 27, 97, 63, 0, | |
| 77 36, 87, 52, 16, 5, 90, 8, 66, 58, 91, 85, 3, 95, 31, 73, 87, 30, 78, 46, | |
| 78 30, 75, 36, 44, 52, 76, 24, 58, 8, 70, 58, 95, 88, 0, 35, 86, 21, 96, 90, | |
| 79 54, 85, 56, 30, 37, 30, 62, 56, 63, 91, 25, 56, 20, 56, 23, 12, 8, 70, 56, | |
| 80 83, 49, 70, 67, 61, 95, 50, 41, 88, 37, 89, 37, 21, 63, 25, 46, 16, 75, 73, | |
| 81 86, 39, 4, 55, 41, 39, 45, 31, 97, 6, 81, 68, 38, 49, 80, 9, 87, 22, 37, | |
| 82 41, 28, 47, 74, 76, 34, 72, 65, 34, 41, 59, 42, 73, 32, 75, 25, 18, 26, 71, | |
| 83 93, 92, 12, 76, 93, 84, 44, 43, 4, 9, 3, 90, 91, 45, 0, 10, 43, 45, 65, | |
| 84 34, 82, 54, 1, 78, 36, 74, 58, 3, 26, 89, 21, 57, 42, 37, 12, 90, 97, 48, | |
| 85 27, 75, 40, 69, 61, 56, 44, 75, 77, 55, 31, 0, 77, 12, 23, 16, 98, 77, 8, | |
| 86 96, 92, 91, 26, 50, 42, 65, 38, 58, 41, 45, 69, 42, 37, 89, 92, 40, 74, 68, | |
| 87 86, 80, 49, 16, 48, 74, 50, 92, 54, 6, 82, 21, 35, 57, 81, 29, 10, 60, 74, | |
| 88 41, 70, 18, 65, 44, 77, 64, 8, 87, 90, 24, 52, 67, 58, 56, 89, 47, 15, 20, | |
| 89 4, 87, 72, 87, 13, 79, 3, 26, 43, 52, 72, 83, 17, 99, 29, 10, 61, 62, 42, | |
| 90 35, 47, 42, 40, 17, 71, 54, 30, 99, 64, 78, 70, 75, 38, 32, 51, 2, 49, 47, | |
| 91 0, 41, 50, 41, 64, 57, 78, 22, 17, 94, 24, 65, 84, 38, 75, 3, 58, 18, 51, | |
| 92 91, 72, 91, 55, 6, 70, 76, 73, 30, 54, 73, 77, 45, 85, 88, 58, 25, 80, 35, | |
| 93 99, 57, 73, 15, 55, 71, 44, 44, 79, 20, 63, 29, 14, 51, 10, 46, 80, 36, 47, | |
| 94 80, 53, 15, 64, 42, 59, 94, 55, 99, 28, 76, 80, 51, 4, 98, 98, 38, 59, 71, | |
| 95 9, 93, 91, 46, 74, 63, 10, 39, 1, 43, 11, 64, 39, 59, 54, 9, 44, 78, 52, | |
| 96 98, 9, 73, 24, 15, 40, 5, 55, 23, 83, 67, 10, 58, 45, 64, 41, 92, 85, 72, | |
| 97 18, 67, 65, 30, 56, 84, 63, 96, 51, 55, 19, 70, 48, 81, 2, 37, 85, 77}; | |
|
mmenke
2016/09/19 15:26:18
I don't suppose we have a "deterministic random nu
Randy Smith (Not in Mondays)
2016/09/22 21:52:27
Didn't find it when I looked :-J.
| |
| 98 | |
| 99 class QuantileEstimatorTest : public testing::Test { | |
| 100 public: | |
| 101 QuantileEstimatorTest() : debug_(false), index_(0) {} | |
| 102 | |
| 103 // Create a new estimator with the given parameters. | |
| 104 void SetUpEstimator(int quantile, int initial_estimate) { | |
| 105 estimator_.reset(new net::QuantileEstimator(quantile, initial_estimate)); | |
| 106 estimator_->SetRandomNumberGeneratorForTesting( | |
| 107 base::Bind(&QuantileEstimatorTest::getRandomNumber, | |
| 108 // Safe since |estimator_| is owned by and | |
| 109 // will not survive destruction of |this|. | |
| 110 base::Unretained(this))); | |
| 111 } | |
| 112 | |
| 113 int CurrentEstimate() { return estimator_->current_estimate(); } | |
| 114 void AddSample(int sample) { | |
| 115 estimator_->AddSample(sample); | |
| 116 if (debug_) | |
| 117 LOG(ERROR) << "Current estimate: " << estimator_->current_estimate(); | |
|
mmenke
2016/09/19 15:26:17
Would it make more sense to use VLOG?
Randy Smith (Not in Mondays)
2016/09/22 21:52:27
I dislike VLOG, as I always have to look up the sy
| |
| 118 } | |
| 119 | |
| 120 // Add the sample until there's a change in the estimate, then return the | |
| 121 // new estimate. To get around the randomness of whether samples are | |
| 122 // incorporated or not. | |
| 123 int AddSampleUntilRegistered(int sample) { | |
| 124 int e1 = estimator_->current_estimate(); | |
|
mmenke
2016/09/19 15:26:18
e1 -> old_estimate...And maybe get rid of e2?
Thi
Randy Smith (Not in Mondays)
2016/09/22 21:52:27
Good idea. Done.
| |
| 125 int e2 = e1; | |
| 126 while (e2 == e1) { | |
| 127 estimator_->AddSample(sample); | |
| 128 e2 = estimator_->current_estimate(); | |
| 129 } | |
| 130 return e2; | |
| 131 } | |
| 132 | |
| 133 int getRandomNumber() { | |
|
mmenke
2016/09/19 15:26:17
GetRandomNumber
Randy Smith (Not in Mondays)
2016/09/22 21:52:27
Done.
| |
| 134 int result = random_numbers[index_]; | |
| 135 ++index_; | |
| 136 if (static_cast<unsigned long>(index_) >= | |
| 137 sizeof(random_numbers) / sizeof(int)) { | |
| 138 index_ = 0; | |
| 139 } | |
| 140 return result; | |
| 141 } | |
| 142 | |
| 143 private: | |
| 144 const bool debug_; | |
| 145 int index_; | |
| 146 std::unique_ptr<net::QuantileEstimator> estimator_; | |
|
mmenke
2016/09/19 15:26:18
DISALLOW_COPY_AND_ASSIGN
Randy Smith (Not in Mondays)
2016/09/22 21:52:27
After more than six years, it appears my unconscio
| |
| 147 }; | |
| 148 | |
| 149 // Converges upwards fairly quickly. | |
| 150 TEST_F(QuantileEstimatorTest, MedianConvergesUpwards) { | |
| 151 SetUpEstimator(50, 100); | |
| 152 | |
| 153 for (int i = 0; i < 20; ++i) | |
| 154 AddSample(150); | |
| 155 | |
| 156 EXPECT_EQ(150, CurrentEstimate()); | |
| 157 } | |
| 158 | |
| 159 // Converges downwards fairly quickly. | |
| 160 TEST_F(QuantileEstimatorTest, MedianConvergesDownwards) { | |
| 161 SetUpEstimator(50, 100); | |
| 162 | |
| 163 for (int i = 0; i < 100; ++i) | |
|
mmenke
2016/09/19 15:26:18
Why is this 100, and the above test 50?
mmenke
2016/09/19 15:28:20
The above test 20, rather. Sorry, was looking at
Randy Smith (Not in Mondays)
2016/09/22 21:52:27
The honest answer is that I cranked up the iterati
Randy Smith (Not in Mondays)
2016/09/22 21:52:27
Acknowledged :-}.
| |
| 164 AddSample(50); | |
| 165 | |
| 166 EXPECT_EQ(50, CurrentEstimate()); | |
| 167 } | |
| 168 | |
| 169 // Stable if the value is bouncing around. | |
| 170 TEST_F(QuantileEstimatorTest, BounceStable) { | |
| 171 SetUpEstimator(50, 100); | |
| 172 | |
| 173 for (int i = 0; i < 20; ++i) | |
| 174 AddSample(50 + (i % 2) * 100); | |
| 175 | |
| 176 EXPECT_LT(98, CurrentEstimate()); | |
| 177 EXPECT_LT(CurrentEstimate(), 102); | |
|
mmenke
2016/09/19 15:26:17
Random thought: Are there any hard guarantees abo
Randy Smith (Not in Mondays)
2016/09/22 21:52:27
So there aren't hard guarantees (given that it's p
| |
| 178 } | |
| 179 | |
| 180 // Correctly converges to a 90%l value upwards. | |
| 181 TEST_F(QuantileEstimatorTest, NinetythConvergesUpwards) { | |
| 182 SetUpEstimator(90, 50); | |
| 183 | |
| 184 for (int i = 0; i < 10000; ++i) | |
| 185 AddSample((i * kPrimeMultipleToRandomizeRamps) % 100); | |
| 186 | |
| 187 EXPECT_LE(86, CurrentEstimate()); | |
| 188 EXPECT_LE(CurrentEstimate(), 94); | |
| 189 } | |
| 190 | |
| 191 // Correctly converges to a 90%l value downwards. | |
| 192 TEST_F(QuantileEstimatorTest, NinetythConvergesDownwards) { | |
| 193 SetUpEstimator(90, 150); | |
| 194 | |
| 195 for (int i = 0; i < 1000; ++i) { | |
| 196 AddSample((i * kPrimeMultipleToRandomizeRamps) % 100); | |
| 197 std::cout << i << "\t" << CurrentEstimate() << std::endl; | |
| 198 } | |
| 199 | |
| 200 EXPECT_LT(86, CurrentEstimate()); | |
| 201 EXPECT_LT(CurrentEstimate(), 94); | |
| 202 } | |
| 203 | |
| 204 // Doesn't overshoot sample heading upwards. | |
| 205 TEST_F(QuantileEstimatorTest, NoUpwardsOvershoot) { | |
| 206 SetUpEstimator(50, 100); | |
| 207 | |
| 208 // Crank up the step size | |
| 209 for (int i = 0; i < 20; ++i) | |
| 210 AddSample(1000); | |
| 211 | |
| 212 // Derive the step size. | |
| 213 int e1 = CurrentEstimate(); | |
| 214 int e2 = AddSampleUntilRegistered(1000); | |
| 215 int step_size = e2 - e1; | |
| 216 ASSERT_GT(step_size, 1); | |
| 217 | |
| 218 // Increment by less than the current step size. | |
| 219 int new_sample = e2 + step_size / 2; | |
| 220 AddSampleUntilRegistered(new_sample); | |
| 221 EXPECT_EQ(new_sample, CurrentEstimate()); | |
| 222 AddSampleUntilRegistered(1000); | |
| 223 EXPECT_GT(new_sample + step_size, CurrentEstimate()); | |
| 224 } | |
| 225 | |
| 226 // Doesn't overshoot sample heading downwards | |
| 227 TEST_F(QuantileEstimatorTest, NoDownwardsOvershoot) { | |
| 228 SetUpEstimator(50, 1000); | |
| 229 | |
| 230 // Crank up the step size | |
| 231 for (int i = 0; i < 20; ++i) | |
| 232 AddSample(100); | |
| 233 | |
| 234 // Derive the step size. | |
| 235 int e1 = CurrentEstimate(); | |
| 236 int e2 = AddSampleUntilRegistered(100); | |
| 237 int step_size = e1 - e2; | |
| 238 ASSERT_GT(step_size, 1); | |
| 239 | |
| 240 // Increment by less than the current step size. | |
| 241 int new_sample = e2 - step_size / 2; | |
| 242 AddSampleUntilRegistered(new_sample); | |
| 243 EXPECT_EQ(new_sample, CurrentEstimate()); | |
| 244 AddSampleUntilRegistered(100); | |
| 245 EXPECT_LT(new_sample - step_size, CurrentEstimate()); | |
| 246 } | |
| 247 | |
| 248 } // namespace | |
| OLD | NEW |