From 0ece30dc7c0e34b4c5911969b8fa99c33c6d023c Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 30 Nov 2022 17:48:47 +0300 Subject: Telegram: update for TDLIB --- .../Telegram/tdlib/td/benchmark/hashset_memory.cpp | 193 +++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 protocols/Telegram/tdlib/td/benchmark/hashset_memory.cpp (limited to 'protocols/Telegram/tdlib/td/benchmark/hashset_memory.cpp') diff --git a/protocols/Telegram/tdlib/td/benchmark/hashset_memory.cpp b/protocols/Telegram/tdlib/td/benchmark/hashset_memory.cpp new file mode 100644 index 0000000000..8f31b52114 --- /dev/null +++ b/protocols/Telegram/tdlib/td/benchmark/hashset_memory.cpp @@ -0,0 +1,193 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#if USE_MEMPROF +#include "memprof/memprof_stat.h" +#endif + +#include "td/utils/common.h" +#include "td/utils/FlatHashMap.h" +#include "td/utils/FlatHashMapChunks.h" +#include "td/utils/FlatHashTable.h" +#include "td/utils/HashTableUtils.h" +#include "td/utils/logging.h" +#include "td/utils/MapNode.h" +#include "td/utils/misc.h" +#include "td/utils/port/Stat.h" +#include "td/utils/Slice.h" +#include "td/utils/StringBuilder.h" + +#ifdef SCOPE_EXIT +#undef SCOPE_EXIT +#endif + +#include +#include +#include +#include +#include +#include + +static int mem_stat_i = -1; +static int mem_stat_cur = 0; + +static bool use_memprof() { +#if USE_MEMPROF + return mem_stat_i < 0 && is_memprof_on(); +#else + return mem_stat_i < 0; +#endif +} + +static td::uint64 get_memory() { +#if USE_MEMPROF + if (use_memprof()) { + return get_used_memory_size(); + } +#endif + CHECK(!use_memprof()); + return td::mem_stat().ok().resident_size_; +} + +template +class Generator { + public: + T next() { + UNREACHABLE(); + } + static size_t dyn_size() { + UNREACHABLE(); + } +}; + +template +class IntGenerator { + public: + T next() { + return ++value; + } + static size_t dyn_size() { + return 0; + } + + private: + T value{}; +}; + +template <> +class Generator final : public IntGenerator {}; +template <> +class Generator final : public IntGenerator {}; + +template +class Generator> { + public: + td::unique_ptr next() { + return td::make_unique(); + } + static std::size_t dyn_size() { + return sizeof(T); + } +}; + +template +static void measure(td::StringBuilder &sb, td::Slice name, td::Slice key_name, td::Slice value_name) { + mem_stat_cur++; + if (mem_stat_i >= 0 && mem_stat_cur != mem_stat_i) { + return; + } + sb << name << "<" << key_name << "," << value_name << "> " << (use_memprof() ? "memprof" : "os") << "\n"; + std::size_t ideal_size = sizeof(KeyT) + sizeof(ValueT) + Generator::dyn_size(); + + sb << "\tempty:" << sizeof(T); + struct Stat { + int pi; + double min_ratio; + double max_ratio; + }; + td::vector stat; + stat.reserve(1024); + for (std::size_t size : {1000000u}) { + Generator key_generator; + Generator value_generator; + auto start_mem = get_memory(); + T ht; + auto ratio = [&] { + auto end_mem = get_memory(); + auto used_mem = end_mem - start_mem; + return static_cast(used_mem) / (static_cast(ideal_size) * static_cast(ht.size())); + }; + double min_ratio; + double max_ratio; + auto reset = [&] { + min_ratio = 1e100; + max_ratio = 0; + }; + auto update = [&] { + auto x = ratio(); + min_ratio = td::min(min_ratio, x); + max_ratio = td::max(max_ratio, x); + }; + reset(); + + int p = 10; + int pi = 1; + for (std::size_t i = 0; i < size; i++) { + ht.emplace(key_generator.next(), value_generator.next()); + update(); + if ((i + 1) % p == 0) { + stat.push_back(Stat{pi, min_ratio, max_ratio}); + reset(); + pi++; + p *= 10; + } + } + } + for (auto &s : stat) { + sb << " 10^" << s.pi << ":" << s.min_ratio << "->" << s.max_ratio; + } + sb << '\n'; +} + +template +using Bytes = std::array; + +template