histogram.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #pragma once
  2. #include <library/cpp/json/json_value.h>
  3. #include <library/cpp/json/writer/json.h>
  4. #include <library/cpp/threading/future/async.h>
  5. #include <util/generic/algorithm.h>
  6. #include <util/generic/hash.h>
  7. #include <util/generic/utility.h>
  8. #include <util/generic/vector.h>
  9. #include <util/generic/yexception.h>
  10. #include <util/stream/format.h>
  11. #include <util/string/builder.h>
  12. #include <util/thread/pool.h>
  13. #include <util/system/mutex.h>
  14. namespace NSimpleHistogram {
  15. template <typename T>
  16. class THistogram {
  17. public:
  18. explicit THistogram(TVector<T>&& values)
  19. : Values_(std::move(values))
  20. {
  21. }
  22. size_t TotalCount() const {
  23. return Values_.size();
  24. }
  25. T ValueAtPercentile(double percentile) const {
  26. Y_ASSERT(!Values_.empty());
  27. Y_ASSERT(percentile >= 0.0 && percentile <= 1.0);
  28. const size_t index = static_cast<size_t>(percentile * Values_.size());
  29. return Values_[Min(Values_.size() - 1, index)];
  30. }
  31. private:
  32. TVector<T> Values_;
  33. };
  34. template <typename T>
  35. class THistogramCalcer {
  36. public:
  37. size_t TotalCount() const {
  38. return Values_.size();
  39. }
  40. void Reserve(size_t cnt) {
  41. Values_.reserve(cnt);
  42. }
  43. void RecordValue(T value) {
  44. Values_.push_back(value);
  45. }
  46. THistogram<T> Calc() {
  47. if (!IsSorted(Values_.begin(), Values_.end())) {
  48. Sort(Values_.begin(), Values_.end());
  49. }
  50. return THistogram<T>(std::move(Values_));
  51. }
  52. private:
  53. TVector<T> Values_;
  54. };
  55. template <typename T>
  56. class TMultiHistogramCalcer {
  57. public:
  58. void RecordValue(TStringBuf name, T value) {
  59. Calcers_[name].RecordValue(value);
  60. }
  61. THashMap<TString, THistogram<T>> Calc() {
  62. THashMap<TString, THistogram<T>> result;
  63. for (auto& calcer : Calcers_) {
  64. result.emplace(calcer.first, calcer.second.Calc());
  65. }
  66. return result;
  67. }
  68. private:
  69. THashMap<TString, THistogramCalcer<T>> Calcers_;
  70. };
  71. template <typename T>
  72. class TThreadSafeMultiHistogramCalcer {
  73. public:
  74. void RecordValue(TStringBuf name, T value) {
  75. TGuard<TMutex> guard(Mutex_);
  76. Calcer_.RecordValue(name, value);
  77. }
  78. THashMap<TString, THistogram<T>> Calc() {
  79. return Calcer_.Calc();
  80. }
  81. private:
  82. TMutex Mutex_;
  83. TMultiHistogramCalcer<T> Calcer_;
  84. };
  85. template <typename T>
  86. NJson::TJsonValue ToJson(const THistogram<T>& hist, const TVector<double>& percentiles) {
  87. NJson::TJsonValue json;
  88. for (double percentile : percentiles) {
  89. TStringBuilder name;
  90. name << "Q" << Prec(percentile * 100, PREC_POINT_DIGITS_STRIP_ZEROES, 2);
  91. json[name] = hist.ValueAtPercentile(percentile);
  92. }
  93. json["RecordCount"] = hist.TotalCount();
  94. return json;
  95. }
  96. template <typename T>
  97. NJson::TJsonValue ToJson(const THashMap<TString, THistogram<T>>& hists, const TVector<double>& percentiles) {
  98. NJson::TJsonValue json;
  99. for (const auto& p : hists) {
  100. json[p.first] = ToJson(p.second, percentiles);
  101. }
  102. return json;
  103. }
  104. template <typename T>
  105. TString ToJsonStr(const THashMap<TString, THistogram<T>>& hists, const TVector<double>& percentiles, bool format = true) {
  106. NJson::TJsonValue json = ToJson(hists, percentiles);
  107. NJsonWriter::TBuf buf;
  108. if (format) {
  109. buf.SetIndentSpaces(4);
  110. }
  111. return buf.WriteJsonValue(&json, true).Str();
  112. }
  113. }