1#include <userver/multi-index-lru/container.hpp>
2#include <userver/utils/rand.hpp>
8#include <benchmark/benchmark.h>
9#include <boost/multi_index/member.hpp>
11USERVER_NAMESPACE_BEGIN
15const std::size_t kOperationsNumber = 100000;
16const int kMaxIdSize = 50000;
27 bool operator==(
const User& other)
const {
return id == other.id && email == other.email && name == other.name; }
32 std::string email =
"email" + std::to_string(utils
::RandRange<int>(0
, kMaxIdSize
));
33 std::string name =
"name" + std::to_string(utils
::RandRange<int>(0
, kMaxIdSize
));
39std::string GenerateName() {
return "name" + std::to_string(utils
::RandRange<int>(0
, kMaxIdSize
)); }
41std::string GenerateEmail() {
return "email" + std::to_string(utils
::RandRange<int>(0
, kMaxIdSize
)); }
44using UserCache = multi_index_lru::
Container<
46 boost::multi_index::indexed_by<
47 boost::multi_index::ordered_unique<
48 boost::multi_index::tag<IdTag>,
49 boost::multi_index::member<User,
int, &User::id>>,
50 boost::multi_index::ordered_unique<
51 boost::multi_index::tag<EmailTag>,
52 boost::multi_index::member<User, std::string, &User::email>>,
53 boost::multi_index::ordered_non_unique<
54 boost::multi_index::tag<NameTag>,
55 boost::multi_index::member<User, std::string, &User::name>>>>;
57void LruFindEmplaceMix(benchmark::State& state) {
58 const std::size_t size = state.range(0);
60 UserCache cache(size);
61 for (std::size_t i = 0; i < size; ++i) {
62 cache.emplace(GenerateUser());
65 std::size_t reading_kOperationsNumber = kOperationsNumber * 4 / 5;
66 std::size_t writing_kOperationsNumber = kOperationsNumber / 5;
68 std::vector<std::string> names, emails;
70 std::vector<User> users;
72 for (std::size_t i = 0; i < reading_kOperationsNumber; ++i) {
73 names.push_back(GenerateName());
74 emails.push_back(GenerateEmail());
75 ids.push_back(GenerateId());
78 for (std::size_t i = 0; i < writing_kOperationsNumber; ++i) {
79 users.push_back(GenerateUser());
82 for ([[maybe_unused]]
auto _ : state) {
83 for (std::size_t i = 0; i < reading_kOperationsNumber; ++i) {
84 cache.find<NameTag, std::string>(names[i]);
85 cache.find<EmailTag, std::string>(emails[i]);
86 cache.find<IdTag,
int>(ids[i]);
89 for (std::size_t i = 0; i < writing_kOperationsNumber; ++i) {
90 cache.emplace(users[i]);
95BENCHMARK(LruFindEmplaceMix)->RangeMultiplier(10)->Range(100, 1000000);
97static void prepareCache(UserCache& cache, std::size_t size) {
98 for (std::size_t i = 0; i < size; ++i) {
99 cache.emplace(GenerateUser());
103static void GetOperations(::benchmark::State& state) {
104 const std::size_t cache_size = state.range(0);
105 const std::size_t operations_count = kOperationsNumber;
107 UserCache cache(cache_size);
108 prepareCache(cache, cache_size);
110 for (
auto _ : state) {
112 std::vector<std::string> names, emails;
113 std::vector<
int> ids;
114 for (std::size_t i = 0; i < operations_count; ++i) {
115 names.push_back(GenerateName());
116 emails.push_back(GenerateEmail());
117 ids.push_back(GenerateId());
119 state.ResumeTiming();
121 for (std::size_t i = 0; i < operations_count; ++i) {
122 ::benchmark::DoNotOptimize(cache.find<NameTag, std::string>(names[i]));
123 ::benchmark::DoNotOptimize(cache.find<EmailTag, std::string>(emails[i]));
124 ::benchmark::DoNotOptimize(cache.find<IdTag,
int>(ids[i]));
128 state.SetItemsProcessed(state.iterations() * operations_count * 3);
129 state.SetComplexityN(cache_size);
132BENCHMARK(GetOperations)->RangeMultiplier(10)->Range(100, 1000000);
134static void EmplaceOperations(::benchmark::State& state) {
135 const std::size_t cache_size = state.range(0);
136 const std::size_t operations_count = kOperationsNumber;
138 UserCache cache(cache_size);
139 prepareCache(cache, cache_size);
141 for (
auto _ : state) {
143 std::vector<User> users;
144 for (std::size_t i = 0; i < operations_count; ++i) {
145 users.push_back(GenerateUser());
147 state.ResumeTiming();
149 for (std::size_t i = 0; i < operations_count; ++i) {
150 cache.emplace(users[i]);
154 state.SetItemsProcessed(state.iterations() * operations_count);
155 state.SetComplexityN(cache_size);
158BENCHMARK(EmplaceOperations)->RangeMultiplier(10)->Range(100, 1000000);