#include <chrono>
#include <queue>
#include <random>
#include <string>
namespace bench {
using clock_t = std::chrono::system_clock;
struct SensorSample
{
unsigned sensor_id;
clock_t::time_point timestamp;
std::string payload;
};
struct SensorReaderMockup
{
unsigned sensor_id;
clock_t::duration interval;
clock_t::time_point last_sample;
SensorSample next()
{
SensorSample rtrn {
sensor_id, last_sample,
"some payload longer than SSO" };
last_sample += interval;
return rtrn;
}
};
struct SampleCompare
{
bool operator()(const SensorSample& left,
const SensorSample& right) const noexcept
{ return left.timestamp > right.timestamp; }
};
using min_heap_t = std::priority_queue<
SensorSample, std::vector<SensorSample>, SampleCompare>;
void run_heap(SensorReaderMockup* sensor_states, unsigned sensors,
int events)
{
min_heap_t heap;
/*
* Read first sample of each sensor
*/
for(std::size_t i = 0; i < sensors; ++i)
heap.push(sensor_states[i].next());
for(int i = 0; i < events; ++i) {
/*
* Retrieve oldest sample for transfer to output
*/
SensorSample oldest = std::move(heap.top());
heap.pop();
/*
* Read next sample from this particular sensor.
* Real code would obviously have to check whether sensor is at
* end-of-file
*/
heap.push(sensor_states[oldest.sensor_id].next());
}
}
/**
* Initializes sensors with pseudo-random sampling periods
*/
std::vector<SensorReaderMockup> init_state(unsigned sensors)
{
std::vector<SensorReaderMockup> rtrn;
rtrn.reserve(sensors);
std::default_random_engine rng;
std::uniform_int_distribution<int> distr {1, 100};
for(unsigned i = 0; i < sensors; ++i) {
clock_t::duration interval {distr(rng)};
clock_t::time_point last_sample = clock_t::time_point{} + interval;
rtrn.push_back(SensorReaderMockup{i, interval, last_sample});
}
return rtrn;
}
} // namespace bench
int main()
{
using namespace bench;
unsigned sensors = 60'000;
int events = 100'000'000;
std::vector<SensorReaderMockup> sensor_states = init_state(sensors);
run_heap(sensor_states.data(), sensors, events);
}
Comments
0 B
|👍
/👎