percentile.h 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. #pragma once
  2. #include "percentile_base.h"
  3. namespace NMonitoring {
  4. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5. // Percentile tracker for monitoring
  6. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  7. template <size_t BUCKET_SIZE, size_t BUCKET_COUNT, size_t FRAME_COUNT>
  8. struct TPercentileTracker : public TPercentileBase {
  9. std::atomic<size_t> Items[BUCKET_COUNT];
  10. size_t Frame[FRAME_COUNT][BUCKET_COUNT];
  11. size_t CurrentFrame;
  12. TPercentileTracker()
  13. : CurrentFrame(0)
  14. {
  15. for (size_t i = 0; i < BUCKET_COUNT; ++i) {
  16. Items[i].store(0);
  17. }
  18. for (size_t frame = 0; frame < FRAME_COUNT; ++frame) {
  19. for (size_t bucket = 0; bucket < BUCKET_COUNT; ++bucket) {
  20. Frame[frame][bucket] = 0;
  21. }
  22. }
  23. }
  24. void Increment(size_t value) {
  25. auto idx = Min((value + BUCKET_SIZE - 1) / BUCKET_SIZE, BUCKET_COUNT - 1);
  26. Items[idx].fetch_add(1, std::memory_order_relaxed);
  27. }
  28. // shift frame (call periodically)
  29. void Update() {
  30. std::array<size_t, BUCKET_COUNT> totals;
  31. size_t total = 0;
  32. for (size_t i = 0; i < BUCKET_COUNT; ++i) {
  33. size_t item = Items[i].load(std::memory_order_relaxed);
  34. size_t prevItem = Frame[CurrentFrame][i];
  35. Frame[CurrentFrame][i] = item;
  36. total += item - prevItem;
  37. totals[i] = total;
  38. }
  39. for (size_t i = 0; i < Percentiles.size(); ++i) {
  40. TPercentile &percentile = Percentiles[i];
  41. auto threshold = (size_t)(percentile.first * (float)total);
  42. threshold = Min(threshold, total);
  43. auto it = LowerBound(totals.begin(), totals.end(), threshold);
  44. size_t index = it - totals.begin();
  45. (*percentile.second) = index * BUCKET_SIZE;
  46. }
  47. CurrentFrame = (CurrentFrame + 1) % FRAME_COUNT;
  48. }
  49. };
  50. } // NMonitoring