Repo created
This commit is contained in:
parent
4af19165ec
commit
68073add76
12458 changed files with 12350765 additions and 2 deletions
128
libs/base/stats.hpp
Normal file
128
libs/base/stats.hpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#pragma once
|
||||
|
||||
#include "base/logging.hpp"
|
||||
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace base
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
class NoopStats
|
||||
{
|
||||
public:
|
||||
NoopStats() {}
|
||||
void operator()(T const &) {}
|
||||
std::string GetStatsStr() const { return ""; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class AverageStats
|
||||
{
|
||||
public:
|
||||
AverageStats() = default;
|
||||
template <class ContT>
|
||||
explicit AverageStats(ContT const & cont)
|
||||
{
|
||||
for (auto const & e : cont)
|
||||
(*this)(e);
|
||||
}
|
||||
|
||||
void operator()(T const & x)
|
||||
{
|
||||
++m_count;
|
||||
if (x > m_max)
|
||||
m_max = x;
|
||||
m_sum += x;
|
||||
}
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
out << "N = " << m_count << "; Total = " << m_sum << "; Max = " << m_max << "; Avg = " << GetAverage();
|
||||
return out.str();
|
||||
}
|
||||
|
||||
double GetAverage() const { return m_count == 0 ? 0.0 : m_sum / static_cast<double>(m_count); }
|
||||
uint32_t GetCount() const { return m_count; }
|
||||
|
||||
private:
|
||||
uint32_t m_count = 0;
|
||||
T m_max = 0;
|
||||
T m_sum = 0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class StatsCollector
|
||||
{
|
||||
std::vector<std::pair<std::string, AverageStats<T>>> m_vec;
|
||||
|
||||
public:
|
||||
explicit StatsCollector(std::initializer_list<std::string> init)
|
||||
{
|
||||
for (auto & name : init)
|
||||
m_vec.push_back({std::move(name), {}});
|
||||
}
|
||||
~StatsCollector()
|
||||
{
|
||||
for (auto const & e : m_vec)
|
||||
LOG_SHORT(LINFO, (e.first, ":", e.second.ToString()));
|
||||
}
|
||||
|
||||
AverageStats<T> & Get(size_t i) { return m_vec[i].second; }
|
||||
};
|
||||
|
||||
template <class Key>
|
||||
class TopStatsCounter
|
||||
{
|
||||
std::unordered_map<Key, size_t> m_data;
|
||||
|
||||
public:
|
||||
void Add(Key const & key) { ++m_data[key]; }
|
||||
|
||||
void PrintTop(size_t count) const
|
||||
{
|
||||
ASSERT(count > 0, ());
|
||||
|
||||
using PtrT = std::pair<Key const, size_t> const *;
|
||||
struct GreaterNumber
|
||||
{
|
||||
bool operator()(PtrT l, PtrT r) const { return l->second > r->second; }
|
||||
};
|
||||
|
||||
std::priority_queue<PtrT, std::vector<PtrT>, GreaterNumber> queue;
|
||||
|
||||
for (auto const & p : m_data)
|
||||
{
|
||||
if (queue.size() >= count)
|
||||
{
|
||||
if (queue.top()->second >= p.second)
|
||||
continue;
|
||||
queue.pop();
|
||||
}
|
||||
|
||||
queue.push(&p);
|
||||
}
|
||||
|
||||
std::vector<PtrT> vec;
|
||||
vec.reserve(count);
|
||||
|
||||
while (!queue.empty())
|
||||
{
|
||||
vec.push_back(queue.top());
|
||||
queue.pop();
|
||||
}
|
||||
|
||||
for (auto i = vec.rbegin(); i != vec.rend(); ++i)
|
||||
{
|
||||
PtrT const p = *i;
|
||||
LOG_SHORT(LINFO, (p->first, ":", p->second));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace base
|
||||
Loading…
Add table
Add a link
Reference in a new issue