FlatHashMap: improve memory benchmark

This commit is contained in:
Arseny Smirnov 2022-02-10 16:30:23 +01:00
parent 1a28bbd00c
commit 6bb365567b

View File

@ -23,6 +23,9 @@ class Generator {
T next() { T next() {
UNREACHABLE(); UNREACHABLE();
} }
static size_t dyn_size() {
UNREACHABLE();
}
}; };
template <class T> template <class T>
@ -31,6 +34,9 @@ class IntGenerator {
T next() { T next() {
return ++value; return ++value;
} }
static size_t dyn_size() {
return 0;
}
private: private:
T value{}; T value{};
@ -45,10 +51,21 @@ class Generator<uint64_t> : public IntGenerator<uint64_t> {
public: public:
}; };
template <class T>
class Generator<td::unique_ptr<T>> {
public:
td::unique_ptr<T> next() {
return td::make_unique<T>();
}
static size_t dyn_size() {
return sizeof(T);
}
};
template <class T, class KeyT, class ValueT> template <class T, class KeyT, class ValueT>
void measure(td::StringBuilder &sb, td::Slice name, td::Slice key_name, td::Slice value_name) { void measure(td::StringBuilder &sb, td::Slice name, td::Slice key_name, td::Slice value_name) {
sb << name << "<" << key_name << "," << value_name << ">:\n"; sb << name << "<" << key_name << "," << value_name << ">:\n";
size_t ideal_size = sizeof(KeyT) + sizeof(ValueT); size_t ideal_size = sizeof(KeyT) + sizeof(ValueT) + Generator<ValueT>::dyn_size();
sb << "\tempty:" << sizeof(T); sb << "\tempty:" << sizeof(T);
struct Stat { struct Stat {
@ -60,11 +77,13 @@ void measure(td::StringBuilder &sb, td::Slice name, td::Slice key_name, td::Slic
stat.reserve(1024); stat.reserve(1024);
for (size_t size : {10000000u}) { for (size_t size : {10000000u}) {
Generator<KeyT> key_generator; Generator<KeyT> key_generator;
Generator<ValueT> value_generator;
auto start_mem = get_used_memory_size(); auto start_mem = get_used_memory_size();
T ht; T ht;
auto ratio = [&]() { auto ratio = [&]() {
auto end_mem = get_used_memory_size(); auto end_mem = get_used_memory_size();
auto used_mem = end_mem - start_mem; auto used_mem = end_mem - start_mem;
//return double(used_mem);
return double(used_mem) / double(ideal_size * ht.size()); return double(used_mem) / double(ideal_size * ht.size());
}; };
double min_ratio; double min_ratio;
@ -77,16 +96,13 @@ void measure(td::StringBuilder &sb, td::Slice name, td::Slice key_name, td::Slic
auto x = ratio(); auto x = ratio();
min_ratio = std::min(min_ratio, x); min_ratio = std::min(min_ratio, x);
max_ratio = std::max(max_ratio, x); max_ratio = std::max(max_ratio, x);
if (x > 14) {
LOG(ERROR) << "WTF";
}
}; };
reset(); reset();
int p = 10; int p = 10;
int pi = 1; int pi = 1;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
ht.emplace(key_generator.next(), ValueT{}); ht.emplace(key_generator.next(), value_generator.next());
update(); update();
if ((i + 1) % p == 0) { if ((i + 1) % p == 0) {
stat.emplace_back(Stat{pi, min_ratio, max_ratio}); stat.emplace_back(Stat{pi, min_ratio, max_ratio});
@ -102,13 +118,18 @@ void measure(td::StringBuilder &sb, td::Slice name, td::Slice key_name, td::Slic
sb << "\n"; sb << "\n";
} }
template <template <typename... Args> class T>
template <size_t size>
using Bytes = std::array<uint8_t, size>;
template <template<typename... Args> class T>
void print_memory_stats(td::Slice name) { void print_memory_stats(td::Slice name) {
std::string big_buff(1 << 16, '\0'); std::string big_buff(1 << 16, '\0');
td::StringBuilder sb(big_buff, false); td::StringBuilder sb(big_buff, false);
#define MEASURE(KeyT, ValueT) measure<T<KeyT, ValueT>, KeyT, ValueT>(sb, name, #KeyT, #ValueT); #define MEASURE(KeyT, ValueT) \
MEASURE(uint32_t, uint32_t) measure<T<KeyT, ValueT>, KeyT, ValueT>(sb, name, #KeyT, #ValueT);
// MEASURE(uint64_t, td::UInt256) MEASURE(uint32_t, uint32_t);
MEASURE(uint64_t, td::unique_ptr<Bytes<360>>);
LOG(ERROR) << "\n" << sb.as_cslice(); LOG(ERROR) << "\n" << sb.as_cslice();
} }