diff --git a/dbms/include/DB/Common/Throttler.h b/dbms/include/DB/Common/Throttler.h new file mode 100644 index 00000000000..fb972faba69 --- /dev/null +++ b/dbms/include/DB/Common/Throttler.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include + + +/** Позволяет ограничить скорость чего либо (в штуках в секунду) с помощью sleep. + * Особенности работы: + * - считается только средняя скорость, от момента создания объекта; + * если были периоды с низкой скоростью, то в течение промежутка времени после них, скорость будет выше; + */ +class Throttler +{ +public: + Throttler(size_t max_speed_) : max_speed(max_speed_) {} + + void add(size_t amount) + { + size_t new_count; + UInt64 elapsed_ns; + + { + std::lock_guard lock(mutex); + + count += amount; + new_count = count; + + elapsed_ns = watch.elapsed(); + } + + /// Сколько должно было бы пройти времени, если бы скорость была равна max_speed. + UInt64 desired_ns = new_count * 1000000000 / max_speed; + + if (desired_ns > elapsed_ns) + { + UInt64 sleep_ns = desired_ns - elapsed_ns; + timespec sleep_ts; + sleep_ts.tv_sec = sleep_ns / 1000000000; + sleep_ts.tv_nsec = sleep_ns % 1000000000; + nanosleep(&sleep_ts, nullptr); /// NOTE Завершается раньше в случае сигнала. Это считается нормальным. + } + } + +private: + size_t max_speed; + size_t count = 0; + Stopwatch watch; + std::mutex mutex; +}; + + +typedef std::shared_ptr ThrottlerPtr;