diff --git a/service/cache_hitrate_calculator.hh b/service/cache_hitrate_calculator.hh index 02e8a42ec1..c6c2457601 100644 --- a/service/cache_hitrate_calculator.hh +++ b/service/cache_hitrate_calculator.hh @@ -46,6 +46,8 @@ class cache_hitrate_calculator : public seastar::async_sharded_service _rates; + size_t _slen = 0; + std::string _gstate; future<> _done = make_ready_future(); future recalculate_hitrates(); diff --git a/service/misc_services.cc b/service/misc_services.cc index fd6c5f780e..8035737b18 100644 --- a/service/misc_services.cc +++ b/service/misc_services.cc @@ -134,16 +134,18 @@ future cache_hitrate_calculator::recalculate_hitrates() return _db.map_reduce0(cf_to_cache_hit_stats, std::unordered_map(), sum_stats_per_cf).then([this, non_system_filter] (std::unordered_map rates) mutable { _diff = 0; + _gstate.reserve(_slen); // assume length did not change from previous iteration + _slen = 0; _rates = std::move(rates); // set calculated rates on all shards return _db.invoke_on_all([this, cpuid = engine().cpu_id(), non_system_filter] (database& db) { - sstring gstate; - for (auto& cf : db.get_column_families() | boost::adaptors::filtered(non_system_filter)) { - auto it = _rates.find(cf.first); - if (it == _rates.end()) { // a table may be added before map/reduce completes and this code runs - continue; + return do_for_each(_rates, [this, cpuid, &db] (auto&& r) mutable { + auto it = db.get_column_families().find(r.first); + if (it == db.get_column_families().end()) { // a table may be added before map/reduce completes and this code runs + return; } - stat s = it->second; + auto& cf = *it; + stat& s = r.second; float rate = 0; if (s.h) { rate = s.h / (s.h + s.m); @@ -151,25 +153,25 @@ future cache_hitrate_calculator::recalculate_hitrates() if (engine().cpu_id() == cpuid) { // calculate max difference between old rate and new one for all cfs _diff = std::max(_diff, std::abs(float(cf.second->get_global_cache_hit_rate()) - rate)); - gstate += format("{}.{}:{:f};", cf.second->schema()->ks_name(), cf.second->schema()->cf_name(), rate); + _gstate += format("{}.{}:{:0.6f};", cf.second->schema()->ks_name(), cf.second->schema()->cf_name(), rate); } cf.second->set_global_cache_hit_rate(cache_temperature(rate)); - } - if (gstate.size()) { - auto& g = gms::get_local_gossiper(); - auto& ss = get_local_storage_service(); - return g.add_local_application_state(gms::application_state::CACHE_HITRATES, ss.value_factory.cache_hitrates(std::move(gstate))); - } - return make_ready_future<>(); + }); }); }).then([this] { - _rates.clear(); + auto& g = gms::get_local_gossiper(); + auto& ss = get_local_storage_service(); + _slen = _gstate.size(); + g.add_local_application_state(gms::application_state::CACHE_HITRATES, ss.value_factory.cache_hitrates(_gstate)); // if max difference during this round is big schedule next recalculate earlier if (_diff < 0.01) { return std::chrono::milliseconds(2000); } else { return std::chrono::milliseconds(500); } + }).finally([this] { + _gstate = std::string(); // free memory, do not trust clear() to do that for string + _rates.clear(); }); }