throttling.cpp 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. #include "throttling.h"
  2. #include <util/datetime/cputimer.h>
  3. namespace NUnifiedAgent {
  4. TThrottler::TThrottler(double rate, TDuration updatePeriod)
  5. : CyclesPerMillisecond(GetCyclesPerMillisecond())
  6. , UpdatePeriod(updatePeriod.MilliSeconds() * CyclesPerMillisecond)
  7. , PeriodTokens(updatePeriod.SecondsFloat() * rate)
  8. , AvailableTokens(0)
  9. , ExpirationTime(0)
  10. {
  11. }
  12. TThrottler::TThrottler(double rate, double burst)
  13. : TThrottler(rate, TDuration::Seconds(burst / rate))
  14. {
  15. }
  16. void TThrottler::Consume(double& tokens, TFMaybe<TDuration>& nextCheckDelay) {
  17. const auto updateTime = UpdateTokens();
  18. if (tokens <= AvailableTokens) {
  19. AvailableTokens -= tokens;
  20. tokens = 0.0;
  21. nextCheckDelay = Nothing();
  22. } else {
  23. tokens -= AvailableTokens;
  24. AvailableTokens = 0.0;
  25. nextCheckDelay = TDuration::MicroSeconds((ExpirationTime - updateTime) * 1000 / CyclesPerMillisecond + 1);
  26. }
  27. }
  28. bool TThrottler::TryConsume(double tokens) {
  29. UpdateTokens();
  30. if (tokens > AvailableTokens) {
  31. return false;
  32. }
  33. AvailableTokens -= tokens;
  34. return true;
  35. }
  36. void TThrottler::ConsumeAndWait(double tokens) {
  37. TFMaybe<TDuration> nextCheckDelay;
  38. while (true) {
  39. Consume(tokens, nextCheckDelay);
  40. if (!nextCheckDelay.Defined()) {
  41. return;
  42. }
  43. Sleep(*nextCheckDelay);
  44. }
  45. }
  46. ui64 TThrottler::UpdateTokens() {
  47. const auto updateTime = GetCycleCount();
  48. if (updateTime >= ExpirationTime) {
  49. if (ExpirationTime == 0) {
  50. ExpirationTime = updateTime + UpdatePeriod;
  51. } else {
  52. ExpirationTime += ((updateTime - ExpirationTime) / UpdatePeriod + 1) * UpdatePeriod;
  53. }
  54. AvailableTokens = PeriodTokens;
  55. }
  56. return updateTime;
  57. }
  58. }