mirror of
https://github.com/XTXMarkets/ternfs.git
synced 2025-12-30 23:39:46 -06:00
Fixes #32. This also involves some reworking of the block request machinery to make it more robust and faster. The scrubbing is done assuming that the overwhelming majority of block checking will go through.
96 lines
2.9 KiB
C++
96 lines
2.9 KiB
C++
#include "Timings.hpp"
|
|
|
|
Timings::Timings(Duration firstUpperBound, double growth, int bins) :
|
|
_growth(growth),
|
|
_invLogGrowth(1.0/log(growth)),
|
|
_firstUpperBound(firstUpperBound.ns),
|
|
_growthDivUpperBound(growth / (double)firstUpperBound.ns),
|
|
_startedAt(eggsNow()),
|
|
_bins(bins)
|
|
{
|
|
if (firstUpperBound < 1) {
|
|
throw EGGS_EXCEPTION("non-positive first upper bound %s", firstUpperBound);
|
|
}
|
|
if (growth <= 1) {
|
|
throw EGGS_EXCEPTION("growth %s <= 1.0", growth);
|
|
}
|
|
for (auto& bin: _bins) {
|
|
bin.store(0);
|
|
}
|
|
}
|
|
|
|
void Timings::toStats(const std::string& prefix, std::vector<Stat>& stats) {
|
|
static_assert(std::endian::native == std::endian::little);
|
|
auto now = eggsNow();
|
|
auto elapsed = now - _startedAt;
|
|
{
|
|
auto& histStat = stats.emplace_back();
|
|
histStat.time = now;
|
|
histStat.name = BincodeBytes(prefix + ".latency");
|
|
// elapsed, then upperbound+count
|
|
histStat.value.els.resize(8 + 2*8*_bins.size());
|
|
memcpy(histStat.value.els.data(), &elapsed, 8);
|
|
double upperBound = _firstUpperBound;
|
|
for (int i = 0; i < _bins.size(); i++) {
|
|
uint64_t x = upperBound;
|
|
memcpy(histStat.value.els.data() + 8 + i*2*8, &x, 8);
|
|
x = _bins[i].load();
|
|
memcpy(histStat.value.els.data() + 8 + i*2*8 + 8, &x, 8);
|
|
upperBound *= _growth;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Timings::reset() {
|
|
_startedAt = eggsNow();
|
|
for (auto& bin : _bins) {
|
|
bin.store(0);
|
|
}
|
|
}
|
|
|
|
Duration Timings::mean() const {
|
|
double m = 0;
|
|
double c = count();
|
|
double upperBound = _firstUpperBound;
|
|
for (const auto& bin : _bins) {
|
|
m += (double)bin.load() * (upperBound / c);
|
|
upperBound *= _growth;
|
|
}
|
|
return Duration(m);
|
|
}
|
|
|
|
Duration Timings::percentile(double p) const {
|
|
uint64_t countSoFar = 0;
|
|
uint64_t toReach = count()*p;
|
|
double upperBound = _firstUpperBound;
|
|
for (const auto& bin: _bins) {
|
|
countSoFar += bin.load();
|
|
if (countSoFar >= toReach) { break; }
|
|
upperBound *= _growth;
|
|
}
|
|
return Duration(upperBound);
|
|
}
|
|
|
|
#if 0
|
|
void Timings::toMetrics(MetricsBuilder& builder, const std::string& name, const std::vector<std::pair<std::string, std::string>>& tags) {
|
|
uint64_t sum = 0;
|
|
{
|
|
double upperBound = _firstUpperBound;
|
|
for (int i = 0; i < _bins.size(); i++) {
|
|
sum += _bins[i].load();
|
|
builder.measurement(name + "_bucket");
|
|
for (const auto& tag: tags) {
|
|
builder.tag(tag.first, tag.second);
|
|
}
|
|
builder.tag("le", std::to_string((uint64_t)upperBound));
|
|
builder.fieldU64("count", sum);
|
|
upperBound *= _growth;
|
|
}
|
|
}
|
|
builder.measurement(name + "_count");
|
|
for (const auto& tag: tags) {
|
|
builder.tag(tag.first, tag.second);
|
|
}
|
|
builder.fieldU64("count", sum);
|
|
}
|
|
#endif
|