histogram_ut.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "histogram.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <util/generic/cast.h>
  4. using namespace NHdr;
  5. void LoadData(THistogram* h1, THistogram* h2) {
  6. for (int i = 0; i < 1000; i++) {
  7. UNIT_ASSERT(h1->RecordValue(1000));
  8. UNIT_ASSERT(h2->RecordValueWithExpectedInterval(1000, 1000));
  9. }
  10. UNIT_ASSERT(h1->RecordValue(1000 * 1000));
  11. UNIT_ASSERT(h2->RecordValueWithExpectedInterval(1000 * 1000, 1000));
  12. }
  13. Y_UNIT_TEST_SUITE(THistogramTest) {
  14. Y_UNIT_TEST(Creation) {
  15. THistogram h(TDuration::Hours(1).MicroSeconds(), 3);
  16. UNIT_ASSERT_EQUAL(h.GetMemorySize(), 188512);
  17. UNIT_ASSERT_EQUAL(h.GetCountsLen(), 23552);
  18. }
  19. Y_UNIT_TEST(CreateWithLargeValues) {
  20. THistogram h(20L * 1000 * 1000, 100L * 1000 * 1000, 5);
  21. UNIT_ASSERT(h.RecordValue(100L * 1000 * 1000));
  22. UNIT_ASSERT(h.RecordValue(20L * 1000 * 1000));
  23. UNIT_ASSERT(h.RecordValue(30L * 1000 * 1000));
  24. i64 v50 = h.GetValueAtPercentile(50.0);
  25. i64 v8333 = h.GetValueAtPercentile(83.33);
  26. i64 v8334 = h.GetValueAtPercentile(83.34);
  27. i64 v99 = h.GetValueAtPercentile(99.0);
  28. UNIT_ASSERT_EQUAL(v50, 33554431);
  29. UNIT_ASSERT_EQUAL(v8333, 33554431);
  30. UNIT_ASSERT_EQUAL(v8334, 100663295);
  31. UNIT_ASSERT_EQUAL(v99, 100663295);
  32. UNIT_ASSERT(h.ValuesAreEqual(v50, 20L * 1000 * 1000));
  33. UNIT_ASSERT(h.ValuesAreEqual(v8333, 30L * 1000 * 1000));
  34. UNIT_ASSERT(h.ValuesAreEqual(v8334, 100L * 1000 * 1000));
  35. UNIT_ASSERT(h.ValuesAreEqual(v99, 100L * 1000 * 1000));
  36. }
  37. Y_UNIT_TEST(InvalidSignificantValueDigits) {
  38. UNIT_ASSERT_EXCEPTION(THistogram(1000, -1), yexception);
  39. UNIT_ASSERT_EXCEPTION(THistogram(1000, 0), yexception);
  40. UNIT_ASSERT_EXCEPTION(THistogram(1000, 6), yexception);
  41. }
  42. Y_UNIT_TEST(InvalidLowestDiscernibleValue) {
  43. UNIT_ASSERT_EXCEPTION(THistogram(0, 100, 3), yexception);
  44. UNIT_ASSERT_EXCEPTION(THistogram(110, 100, 3), yexception);
  45. }
  46. Y_UNIT_TEST(TotalCount) {
  47. i64 oneHour = SafeIntegerCast<i64>(TDuration::Hours(1).MicroSeconds());
  48. THistogram h1(oneHour, 3);
  49. THistogram h2(oneHour, 3);
  50. LoadData(&h1, &h2);
  51. UNIT_ASSERT_EQUAL(h1.GetTotalCount(), 1001);
  52. UNIT_ASSERT_EQUAL(h2.GetTotalCount(), 2000);
  53. }
  54. Y_UNIT_TEST(StatsValues) {
  55. i64 oneHour = SafeIntegerCast<i64>(TDuration::Hours(1).MicroSeconds());
  56. THistogram h1(oneHour, 3);
  57. THistogram h2(oneHour, 3);
  58. LoadData(&h1, &h2);
  59. // h1 - histogram without correction
  60. {
  61. UNIT_ASSERT_EQUAL(h1.GetMin(), 1000);
  62. UNIT_ASSERT_EQUAL(h1.GetMax(), 1000447);
  63. UNIT_ASSERT(h1.ValuesAreEqual(h1.GetMax(), 1000 * 1000));
  64. // >>> numpy.mean([1000 for i in range(1000)] + [1000000])
  65. // 1998.0019980019979
  66. UNIT_ASSERT_DOUBLES_EQUAL(h1.GetMean(), 1998, 0.5);
  67. // >>> numpy.std([1000 for i in range(1000)] + [1000000])
  68. // 31559.59423085126
  69. UNIT_ASSERT_DOUBLES_EQUAL(h1.GetStdDeviation(), 31559, 10);
  70. }
  71. // h2 - histogram with correction of co-ordinated omission
  72. {
  73. UNIT_ASSERT_EQUAL(h2.GetMin(), 1000);
  74. UNIT_ASSERT_EQUAL(h2.GetMax(), 1000447);
  75. UNIT_ASSERT(h2.ValuesAreEqual(h1.GetMax(), 1000 * 1000));
  76. UNIT_ASSERT_DOUBLES_EQUAL(h2.GetMean(), 250752, 0.5);
  77. UNIT_ASSERT_DOUBLES_EQUAL(h2.GetStdDeviation(), 322557, 0.5);
  78. }
  79. }
  80. Y_UNIT_TEST(Percentiles) {
  81. i64 oneHour = SafeIntegerCast<i64>(TDuration::Hours(1).MicroSeconds());
  82. THistogram h1(oneHour, 3);
  83. THistogram h2(oneHour, 3);
  84. LoadData(&h1, &h2);
  85. // >>> a = [1000 for i in range(1000)] + [1000000]
  86. // >>> [(p, numpy.percentile(a, p)) for p in [50, 90, 99, 99.99, 99.999, 100]]
  87. // [(50, 1000.0), (90, 1000.0), (99, 1000.0), (99.99, 900099.99999986368), (99.999, 990009.99999989558), (100, 1000000.0)]
  88. // h1 - histogram without correction
  89. {
  90. i64 v50 = h1.GetValueAtPercentile(50);
  91. i64 v90 = h1.GetValueAtPercentile(90);
  92. i64 v99 = h1.GetValueAtPercentile(99);
  93. i64 v9999 = h1.GetValueAtPercentile(99.99);
  94. i64 v99999 = h1.GetValueAtPercentile(99.999);
  95. i64 v100 = h1.GetValueAtPercentile(100);
  96. UNIT_ASSERT_EQUAL(v50, 1000);
  97. UNIT_ASSERT_EQUAL(v90, 1000);
  98. UNIT_ASSERT_EQUAL(v99, 1000);
  99. UNIT_ASSERT_EQUAL(v9999, 1000447);
  100. UNIT_ASSERT_EQUAL(v99999, 1000447);
  101. UNIT_ASSERT_EQUAL(v100, 1000447);
  102. UNIT_ASSERT(h1.ValuesAreEqual(v50, 1000));
  103. UNIT_ASSERT(h1.ValuesAreEqual(v90, 1000));
  104. UNIT_ASSERT(h1.ValuesAreEqual(v99, 1000));
  105. UNIT_ASSERT(h1.ValuesAreEqual(v9999, 1000 * 1000));
  106. UNIT_ASSERT(h1.ValuesAreEqual(v99999, 1000 * 1000));
  107. UNIT_ASSERT(h1.ValuesAreEqual(v100, 1000 * 1000));
  108. }
  109. // h2 - histogram with correction of co-ordinated omission
  110. {
  111. i64 v50 = h2.GetValueAtPercentile(50);
  112. i64 v90 = h2.GetValueAtPercentile(90);
  113. i64 v99 = h2.GetValueAtPercentile(99);
  114. i64 v9999 = h2.GetValueAtPercentile(99.99);
  115. i64 v99999 = h2.GetValueAtPercentile(99.999);
  116. i64 v100 = h2.GetValueAtPercentile(100);
  117. UNIT_ASSERT_EQUAL(v50, 1000);
  118. UNIT_ASSERT_EQUAL(v90, 800255);
  119. UNIT_ASSERT_EQUAL(v99, 980479);
  120. UNIT_ASSERT_EQUAL(v9999, 1000447);
  121. UNIT_ASSERT_EQUAL(v99999, 1000447);
  122. UNIT_ASSERT_EQUAL(v100, 1000447);
  123. UNIT_ASSERT(h2.ValuesAreEqual(v50, 1000));
  124. UNIT_ASSERT(h2.ValuesAreEqual(v90, 800 * 1000));
  125. UNIT_ASSERT(h2.ValuesAreEqual(v99, 980 * 1000));
  126. UNIT_ASSERT(h2.ValuesAreEqual(v9999, 1000 * 1000));
  127. UNIT_ASSERT(h2.ValuesAreEqual(v99999, 1000 * 1000));
  128. UNIT_ASSERT(h2.ValuesAreEqual(v100, 1000 * 1000));
  129. }
  130. }
  131. Y_UNIT_TEST(OutOfRangeValues) {
  132. THistogram h(1000, 4);
  133. UNIT_ASSERT(h.RecordValue(32767));
  134. UNIT_ASSERT(!h.RecordValue(32768));
  135. }
  136. Y_UNIT_TEST(Reset) {
  137. THistogram h(TDuration::Hours(1).MicroSeconds(), 3);
  138. UNIT_ASSERT(h.RecordValues(1000, 1000));
  139. UNIT_ASSERT(h.RecordValue(1000 * 1000));
  140. UNIT_ASSERT_EQUAL(h.GetTotalCount(), 1001);
  141. h.Reset();
  142. UNIT_ASSERT_EQUAL(h.GetTotalCount(), 0);
  143. UNIT_ASSERT_EQUAL(h.GetMin(), Max<i64>());
  144. UNIT_ASSERT_EQUAL(h.GetMax(), 0);
  145. UNIT_ASSERT_EQUAL(h.GetValueAtPercentile(99.0), 0);
  146. }
  147. }