bvar_percentile_unittest.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Licensed to the Apache Software Foundation (ASF) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The ASF licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. // Date: 2015/09/15 15:42:55
  18. #include "bvar/detail/percentile.h"
  19. #include "butil/logging.h"
  20. #include <gtest/gtest.h>
  21. #include <fstream>
  22. class PercentileTest : public testing::Test {
  23. protected:
  24. void SetUp() {}
  25. void TearDown() {}
  26. };
  27. TEST_F(PercentileTest, add) {
  28. bvar::detail::Percentile p;
  29. for (int j = 0; j < 10; ++j) {
  30. for (int i = 0; i < 10000; ++i) {
  31. p << (i + 1);
  32. }
  33. bvar::detail::GlobalPercentileSamples b = p.reset();
  34. uint32_t last_value = 0;
  35. for (uint32_t k = 1; k <= 10u; ++k) {
  36. uint32_t value = b.get_number(k / 10.0);
  37. EXPECT_GE(value, last_value);
  38. last_value = value;
  39. EXPECT_GT(value, (k * 1000 - 500)) << "k=" << k;
  40. EXPECT_LT(value, (k * 1000 + 500)) << "k=" << k;
  41. }
  42. LOG(INFO) << "99%:" << b.get_number(0.99) << ' '
  43. << "99.9%:" << b.get_number(0.999) << ' '
  44. << "99.99%:" << b.get_number(0.9999);
  45. std::ofstream out("out.txt");
  46. b.describe(out);
  47. }
  48. }
  49. TEST_F(PercentileTest, merge1) {
  50. // Merge 2 PercentileIntervals b1 and b2. b2 has double SAMPLE_SIZE
  51. // and num_added. Remaining samples of b1 and b2 in merged result should
  52. // be 1:2 approximately.
  53. const size_t N = 1000;
  54. const size_t SAMPLE_SIZE = 32;
  55. size_t belong_to_b1 = 0;
  56. size_t belong_to_b2 = 0;
  57. for (int repeat = 0; repeat < 100; ++repeat) {
  58. bvar::detail::PercentileInterval<SAMPLE_SIZE*3> b0;
  59. bvar::detail::PercentileInterval<SAMPLE_SIZE> b1;
  60. for (size_t i = 0; i < N; ++i) {
  61. if (b1.full()) {
  62. b0.merge(b1);
  63. b1.clear();
  64. }
  65. ASSERT_TRUE(b1.add32(i));
  66. }
  67. b0.merge(b1);
  68. bvar::detail::PercentileInterval<SAMPLE_SIZE * 2> b2;
  69. for (size_t i = 0; i < N * 2; ++i) {
  70. if (b2.full()) {
  71. b0.merge(b2);
  72. b2.clear();
  73. }
  74. ASSERT_TRUE(b2.add32(i + N));
  75. }
  76. b0.merge(b2);
  77. for (size_t i = 0; i < b0._num_samples; ++i) {
  78. if (b0._samples[i] < N) {
  79. ++belong_to_b1;
  80. } else {
  81. ++belong_to_b2;
  82. }
  83. }
  84. }
  85. EXPECT_LT(fabs(belong_to_b1 / (double)belong_to_b2 - 0.5),
  86. 0.2) << "belong_to_b1=" << belong_to_b1
  87. << " belong_to_b2=" << belong_to_b2;
  88. }
  89. TEST_F(PercentileTest, merge2) {
  90. // Merge 2 PercentileIntervals b1 and b2 with same SAMPLE_SIZE. Add N1
  91. // samples to b1 and add N2 samples to b2, Remaining samples of b1 and
  92. // b2 in merged result should be N1:N2 approximately.
  93. const size_t N1 = 1000;
  94. const size_t N2 = 400;
  95. size_t belong_to_b1 = 0;
  96. size_t belong_to_b2 = 0;
  97. for (int repeat = 0; repeat < 100; ++repeat) {
  98. bvar::detail::PercentileInterval<64> b0;
  99. bvar::detail::PercentileInterval<64> b1;
  100. for (size_t i = 0; i < N1; ++i) {
  101. if (b1.full()) {
  102. b0.merge(b1);
  103. b1.clear();
  104. }
  105. ASSERT_TRUE(b1.add32(i));
  106. }
  107. b0.merge(b1);
  108. bvar::detail::PercentileInterval<64> b2;
  109. for (size_t i = 0; i < N2; ++i) {
  110. if (b2.full()) {
  111. b0.merge(b2);
  112. b2.clear();
  113. }
  114. ASSERT_TRUE(b2.add32(i + N1));
  115. }
  116. b0.merge(b2);
  117. for (size_t i = 0; i < b0._num_samples; ++i) {
  118. if (b0._samples[i] < N1) {
  119. ++belong_to_b1;
  120. } else {
  121. ++belong_to_b2;
  122. }
  123. }
  124. }
  125. EXPECT_LT(fabs(belong_to_b1 / (double)belong_to_b2 - N1 / (double)N2),
  126. 0.2) << "belong_to_b1=" << belong_to_b1
  127. << " belong_to_b2=" << belong_to_b2;
  128. }
  129. TEST_F(PercentileTest, combine_of) {
  130. // Combine multiple percentle samplers into one
  131. const int num_samplers = 10;
  132. // Define a base time to make all samples are in the same interval
  133. const uint32_t base = (1 << 30) + 1;
  134. const int N = 1000;
  135. size_t belongs[num_samplers] = {0};
  136. size_t total = 0;
  137. for (int repeat = 0; repeat < 100; ++repeat) {
  138. bvar::detail::Percentile p[num_samplers];
  139. for (int i = 0; i < num_samplers; ++i) {
  140. for (int j = 0; j < N * (i + 1); ++j) {
  141. p[i] << base + i * (i + 1) * N / 2+ j;
  142. }
  143. }
  144. std::vector<bvar::detail::GlobalPercentileSamples> result;
  145. result.reserve(num_samplers);
  146. for (int i = 0; i < num_samplers; ++i) {
  147. result.push_back(p[i].get_value());
  148. }
  149. bvar::detail::PercentileSamples<510> g;
  150. g.combine_of(result.begin(), result.end());
  151. for (size_t i = 0; i < bvar::detail::NUM_INTERVALS; ++i) {
  152. if (g._intervals[i] == NULL) {
  153. continue;
  154. }
  155. bvar::detail::PercentileInterval<510>& p = *g._intervals[i];
  156. total += p._num_samples;
  157. for (size_t j = 0; j < p._num_samples; ++j) {
  158. for (int k = 0; k < num_samplers; ++k) {
  159. if ((p._samples[j] - base) / N < (k + 1) * (k + 2) / 2u){
  160. belongs[k]++;
  161. break;
  162. }
  163. }
  164. }
  165. }
  166. }
  167. for (int i = 0; i < num_samplers; ++i) {
  168. double expect_ratio = (double)(i + 1) * 2 /
  169. (num_samplers * (num_samplers + 1));
  170. double actual_ratio = (double)(belongs[i]) / total;
  171. EXPECT_LT(fabs(expect_ratio / actual_ratio) - 1, 0.2)
  172. << "expect_ratio=" << expect_ratio
  173. << " actual_ratio=" << actual_ratio;
  174. }
  175. }