mirror of
https://github.com/Zygo/bees.git
synced 2025-05-17 21:35:45 +02:00
RateEstimator estimates the rate of external events by sampling a counter. Conversion functions are provided to predict the time when the event counter will be incremented to particular values based on past observations of the event counter. Synchronization functions are provided to block a thread until a specific counter value is reached. Event polling is supported using the history of previous event counts to determine the predicted time of the next event. A decay function emphasizes more recent event history. Polling delays are bounded by minimum and maximum values in the constructor parameters. wait_for() and wait_until() block the calling thread until the target event count is reached (or the counter is reset). These functions are not bounded by min_delay or max_delay, and require a separate tread to call update(). wait_for() waits for the counter to be incremented from its current value by the given count. wait_until() waits for the counter to reach an absolute value. update() counts external events and unblocks threads that are blocked in wait_for() or wait_until(). If the event counter decreases then it is reset to the new value. duration() and time_point() convert relative and absolute event counts into relative and absolute C++11 time quantities based on the last update time, last observed event count, and the observed event rate. Convenience functions seconds_for() and seconds_until() calculate polling delays for for the desired relative and absolute event counts respectively. These delays are bounded by max and min delay parameters. rate() and ratio() provide conversion factors based on the current estimated event rate. Signed-off-by: Zygo Blaxell <bees@furryterror.org>
102 lines
2.4 KiB
C++
102 lines
2.4 KiB
C++
#ifndef CRUCIBLE_TIME_H
|
|
#define CRUCIBLE_TIME_H
|
|
|
|
#include "crucible/error.h"
|
|
|
|
#include <chrono>
|
|
#include <condition_variable>
|
|
#include <limits>
|
|
#include <mutex>
|
|
#include <ostream>
|
|
|
|
namespace crucible {
|
|
|
|
double nanosleep(double secs);
|
|
|
|
class Timer {
|
|
chrono::high_resolution_clock::time_point m_start;
|
|
|
|
public:
|
|
Timer();
|
|
double age() const;
|
|
chrono::high_resolution_clock::time_point get() const;
|
|
double report(int precision = 1000) const;
|
|
void reset();
|
|
double lap();
|
|
bool operator<(double d) const;
|
|
bool operator>(double d) const;
|
|
};
|
|
|
|
ostream &operator<<(ostream &os, const Timer &t);
|
|
|
|
class RateLimiter {
|
|
Timer m_timer;
|
|
double m_rate;
|
|
double m_burst;
|
|
double m_tokens = 0.0;
|
|
mutex m_mutex;
|
|
|
|
void update_tokens();
|
|
RateLimiter() = delete;
|
|
public:
|
|
RateLimiter(double rate, double burst);
|
|
RateLimiter(double rate);
|
|
void sleep_for(double cost = 1.0);
|
|
bool is_ready();
|
|
void borrow(double cost = 1.0);
|
|
};
|
|
|
|
class RateEstimator {
|
|
mutable mutex m_mutex;
|
|
mutable condition_variable m_condvar;
|
|
Timer m_timer;
|
|
double m_num = 0.0;
|
|
double m_den = 0.0;
|
|
uint64_t m_last_count = numeric_limits<uint64_t>::max();
|
|
Timer m_last_update;
|
|
const double m_decay = 0.99;
|
|
Timer m_last_decay;
|
|
double m_min_delay;
|
|
double m_max_delay;
|
|
|
|
chrono::duration<double> duration_unlocked(uint64_t relative_count) const;
|
|
chrono::high_resolution_clock::time_point time_point_unlocked(uint64_t absolute_count) const;
|
|
double rate_unlocked() const;
|
|
pair<double, double> ratio_unlocked() const;
|
|
void update_unlocked(uint64_t new_count);
|
|
public:
|
|
RateEstimator(double min_delay = 1, double max_delay = 3600);
|
|
|
|
// Block until count reached
|
|
void wait_for(uint64_t new_count_relative) const;
|
|
void wait_until(uint64_t new_count_absolute) const;
|
|
|
|
// Computed rates and ratios
|
|
double rate() const;
|
|
pair<double, double> ratio() const;
|
|
|
|
// Inspect raw num/den
|
|
pair<double, double> raw() const;
|
|
|
|
// Write count
|
|
void update(uint64_t new_count);
|
|
|
|
// Read count
|
|
uint64_t count() const;
|
|
|
|
// Convert counts to chrono types
|
|
chrono::high_resolution_clock::time_point time_point(uint64_t absolute_count) const;
|
|
chrono::duration<double> duration(uint64_t relative_count) const;
|
|
|
|
// Polling delay until count reached (limited by min/max delay)
|
|
double seconds_for(uint64_t new_count_relative) const;
|
|
double seconds_until(uint64_t new_count_absolute) const;
|
|
};
|
|
|
|
ostream &
|
|
operator<<(ostream &os, const RateEstimator &re);
|
|
|
|
}
|
|
|
|
#endif // CRUCIBLE_TIME_H
|