in src/oomd/plugins/Senpai.cpp [450:548]
bool Senpai::tick(const CgroupContext& cgroup_ctx, CgroupState& state) {
auto name = cgroup_ctx.cgroup().absolutePath();
auto limit_opt = readMemhigh(cgroup_ctx);
if (!limit_opt) {
return false;
}
auto factor = 0.0;
if (*limit_opt != state.limit) {
// Something else changed limits on this cgroup or it was
// recreated in-between ticks - reset the state and return,
// unfortuantely, the rest of this logic is still racy after this
// point
std::ostringstream oss;
oss << "cgroup " << name << " memory.high " << *limit_opt
<< " does not match recorded state " << state.limit
<< ". Resetting cgroup";
OLOG << oss.str();
if (auto state_opt = initializeCgroup(cgroup_ctx)) {
state = *state_opt;
return true;
}
return false;
}
// Adjust cgroup limit by factor
auto adjust = [&](double factor) {
auto limit_min_bytes_opt = getLimitMinBytes(cgroup_ctx);
if (!limit_min_bytes_opt) {
return false;
}
auto limit_max_bytes_opt = getLimitMaxBytes(cgroup_ctx);
if (!limit_max_bytes_opt) {
return false;
}
state.limit += state.limit * factor;
state.limit = std::max(
*limit_min_bytes_opt, std::min(*limit_max_bytes_opt, state.limit));
// Memory high is always a multiple of 4K
state.limit &= ~0xFFF;
state.ticks = interval_;
state.cumulative = std::chrono::microseconds{0};
return writeMemhigh(cgroup_ctx, state.limit);
};
auto total_opt = getPressureTotalSome(cgroup_ctx);
if (!total_opt) {
return false;
}
auto total = *total_opt;
auto delta = total - state.last_total;
state.last_total = total;
state.cumulative += delta;
auto cumulative = state.cumulative.count();
if (state.cumulative >= pressure_ms_) {
// Excessive pressure, back off. The rate scales exponentially
// with pressure deviation. The coefficient defines how sensitive
// we are to fluctuations around the target pressure: when the
// coefficient is 10, the adjustment curve reaches the backoff
// limit when observed pressure is ten times the target pressure.
double error = state.cumulative / pressure_ms_;
factor = error / coeff_backoff_;
factor *= factor;
factor = std::min(factor * max_backoff_, max_backoff_);
if (!adjust(factor)) {
return false;
}
std::ostringstream oss;
oss << "cgroup " << name << std::setprecision(3) << std::fixed
<< " limitgb " << *limit_opt / (double)(1 << 30UL) << " totalus "
<< total.count() << " deltaus " << delta.count() << " cumus "
<< cumulative << " ticks " << state.ticks << std::defaultfloat
<< " adjust " << factor;
OLOG << oss.str();
} else if (state.ticks) {
--state.ticks;
} else {
// Pressure too low, tighten the limit. Like when backing off, the
// adjustment becomes exponentially more aggressive as observed
// pressure falls below the target pressure. The adjustment limit
// is reached when stall time falls through pressure/coeff_probe_.
auto one = std::chrono::microseconds{1};
double error = pressure_ms_ / std::max(state.cumulative, one);
factor = error / coeff_probe_;
factor *= factor;
factor = std::min(factor * max_probe_, max_probe_);
factor = -factor;
if (!adjust(factor)) {
return false;
}
if (*limit_opt > state.limit) {
state.probe_count++;
state.probe_bytes += *limit_opt - state.limit;
}
}
return true;
}