2015-02-10 20:50:01 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <mutex>
|
|
|
|
#include <memory>
|
2021-10-02 07:13:14 +00:00
|
|
|
#include <base/sleep.h>
|
2021-06-02 08:22:44 +00:00
|
|
|
#include <atomic>
|
2018-05-28 19:53:03 +00:00
|
|
|
|
2015-09-25 12:52:47 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2017-05-10 04:00:19 +00:00
|
|
|
/** Allows you to limit the speed of something (in entities per second) using sleep.
|
2017-05-07 20:25:26 +00:00
|
|
|
* Specifics of work:
|
2021-06-01 22:07:29 +00:00
|
|
|
* Tracks exponentially (pow of 1/2) smoothed speed with hardcoded window.
|
|
|
|
* See more comments in .cpp file.
|
2015-09-25 12:52:47 +00:00
|
|
|
*
|
2017-05-10 04:00:19 +00:00
|
|
|
* Also allows you to set a limit on the maximum number of entities. If exceeded, an exception will be thrown.
|
2015-02-10 20:50:01 +00:00
|
|
|
*/
|
|
|
|
class Throttler
|
|
|
|
{
|
|
|
|
public:
|
2022-03-11 21:47:28 +00:00
|
|
|
explicit Throttler(size_t max_speed_, const std::shared_ptr<Throttler> & parent_ = nullptr)
|
2019-08-03 11:02:40 +00:00
|
|
|
: max_speed(max_speed_), limit_exceeded_exception_message(""), parent(parent_) {}
|
2018-03-29 13:24:36 +00:00
|
|
|
|
2017-08-29 13:23:04 +00:00
|
|
|
Throttler(size_t max_speed_, size_t limit_, const char * limit_exceeded_exception_message_,
|
2019-08-03 11:02:40 +00:00
|
|
|
const std::shared_ptr<Throttler> & parent_ = nullptr)
|
|
|
|
: max_speed(max_speed_), limit(limit_), limit_exceeded_exception_message(limit_exceeded_exception_message_), parent(parent_) {}
|
2017-04-01 07:20:54 +00:00
|
|
|
|
2021-06-01 22:07:29 +00:00
|
|
|
/// Calculates the smoothed speed, sleeps if required and throws exception on
|
|
|
|
/// limit overflow.
|
|
|
|
void add(size_t amount);
|
2015-02-10 20:50:01 +00:00
|
|
|
|
2018-03-29 13:24:36 +00:00
|
|
|
/// Not thread safe
|
|
|
|
void setParent(const std::shared_ptr<Throttler> & parent_)
|
|
|
|
{
|
|
|
|
parent = parent_;
|
|
|
|
}
|
|
|
|
|
2021-06-01 22:07:29 +00:00
|
|
|
/// Reset all throttlers internal stats
|
|
|
|
void reset();
|
2021-05-27 12:54:47 +00:00
|
|
|
|
|
|
|
/// Is throttler already accumulated some sleep time and throttling.
|
2021-06-01 22:07:29 +00:00
|
|
|
bool isThrottling() const;
|
2018-03-09 22:11:42 +00:00
|
|
|
|
2015-02-10 20:50:01 +00:00
|
|
|
private:
|
2021-06-01 22:07:29 +00:00
|
|
|
size_t count{0};
|
|
|
|
const size_t max_speed{0};
|
|
|
|
const uint64_t limit{0}; /// 0 - not limited.
|
2017-04-01 07:20:54 +00:00
|
|
|
const char * limit_exceeded_exception_message = nullptr;
|
|
|
|
std::mutex mutex;
|
2021-06-01 22:07:29 +00:00
|
|
|
std::atomic<uint64_t> accumulated_sleep{0};
|
|
|
|
/// Smoothed value of current speed. Updated in `add` method.
|
|
|
|
double smoothed_speed{0};
|
|
|
|
/// previous `add` call time (in nanoseconds)
|
|
|
|
uint64_t prev_ns{0};
|
2017-08-29 13:23:04 +00:00
|
|
|
|
|
|
|
/// Used to implement a hierarchy of throttlers
|
|
|
|
std::shared_ptr<Throttler> parent;
|
2015-02-10 20:50:01 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-05-28 10:35:44 +00:00
|
|
|
using ThrottlerPtr = std::shared_ptr<Throttler>;
|
2015-09-25 12:52:47 +00:00
|
|
|
|
|
|
|
}
|