MXS-2555 Implement cache eviction (or query re-measurment) strategy

This commit is contained in:
Niclas Antti
2019-06-18 17:02:23 +03:00
parent f5615cc174
commit a950715176
4 changed files with 92 additions and 90 deletions

View File

@ -197,29 +197,69 @@ uint64_t SmartRouter::getCapabilities()
return RCAP_TYPE_TRANSACTION_TRACKING | RCAP_TYPE_CONTIGUOUS_INPUT | RCAP_TYPE_CONTIGUOUS_OUTPUT;
}
// Eviction schedule
// Two reasons to evict, and re-measure canonicals.
// 1. When connections are initially created there is more overhead in maxscale and at the server,
// which can (and does) lead to the wrong performance conclusions.
// 2. Depending on the contents and number of rows in tables, different database engines
// have different performance advantages (InnoDb is always very fast for small tables).
//
// TODO make configurable, maybe.
static std::array<maxbase::Duration, 4> eviction_schedules =
{
std::chrono::minutes(2),
std::chrono::minutes(5),
std::chrono::minutes(10),
std::chrono::minutes(20)
};
// TODO need to add the default db to the key (or hash)
PerformanceInfo SmartRouter::perf_find(const std::string& canonical)
{
std::unique_lock<std::mutex> guard(m_perf_mutex);
auto perf = m_performance.find(canonical);
if (perf.is_valid() && perf.age() > std::chrono::minutes(1)) // TODO to config, but not yet
auto perf_it = m_perfs.find(canonical);
if (perf_it != end(m_perfs) && !perf_it->second.is_updating())
{
m_performance.remove(canonical);
return PerformanceInfo();
if (perf_it->second.age() > eviction_schedules[perf_it->second.eviction_schedule()])
{
MXS_SINFO("Trigger re-measure, schedule "
<< eviction_schedules[perf_it->second.eviction_schedule()]
<< ", perf: " << perf_it->second.host()
<< ", " << perf_it->second.duration() << ", "
<< show_some(canonical));
// Not actually evicting, but trigger a re-measure only for this caller (this worker).
perf_it->second.set_updating(true);
perf_it = end(m_perfs);
}
}
return perf;
return perf_it != end(m_perfs) ? perf_it->second : PerformanceInfo();
}
bool SmartRouter::perf_update(const std::string& canonical, const PerformanceInfo& perf)
void SmartRouter::perf_update(const std::string& canonical, const PerformanceInfo& perf)
{
std::unique_lock<std::mutex> guard(m_perf_mutex);
auto ret = m_performance.insert(canonical, perf);
if (ret)
auto perf_it = m_perfs.find(canonical);
if (perf_it != end(m_perfs))
{
MXS_SDEBUG("Stored perf " << perf.duration() << ' ' << perf.host() << ' ' << show_some(canonical));
}
MXS_SINFO("Update perf: from "
<< perf_it->second.host() << ", " << perf_it->second.duration()
<< " to " << perf.host() << ", " << perf.duration()
<< ", " << show_some(canonical));
return ret;
size_t schedule = perf_it->second.eviction_schedule();
perf_it->second = perf;
perf_it->second.set_eviction_schedule(std::min(++schedule, eviction_schedules.size() - 1));
perf_it->second.set_updating(false);
}
else
{
m_perfs.insert({canonical, perf});
MXS_SDEBUG("Stored new perf: " << perf.host() << ", " << perf.duration()
<< ", " << show_some(canonical));
}
}