Skip to content

Commit 421a88f

Browse files
lnyngmeta-codesync[bot]
authored andcommitted
prerun for per cgroup rulesets
Summary: prerun is a step that allows all plugins to do some prelimiary monitoring and state update before running the ruleset. All plugins will be prerun even if some will be skipped during actual run, e.g. detector does not fire. This is useful for actions that monitor rate changes like pgscan per second. Currently when a ruleset uses ruleset cgroup, only the base ruleset plugins are prerun but not the per-cgroup rulesets. Instead, the base ruleset plugins should not prerun and the per-cgroup ruleset plugins should. This diff adds prerunImpl similar to runOnceImpl to prerun per-cgroup rulesets which also set and unset OomdContext ruleset cgroup. Reviewed By: kev-common Differential Revision: D90274177 fbshipit-source-id: 99962dc75a40aaba6b36c3b4f40e419ee3049e37
1 parent 2a10a95 commit 421a88f

3 files changed

Lines changed: 120 additions & 11 deletions

File tree

src/oomd/config/ConfigCompilerTest.cpp

Lines changed: 102 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ namespace {
4040
int prerun_count;
4141
int prerun_stored_count;
4242
int count;
43-
std::map<std::string, int> count_map = std::map<std::string, int>();
43+
std::unordered_map<CgroupPath, int> prerun_count_map{};
44+
std::unordered_map<CgroupPath, int> count_map{};
4445
int stored_count;
4546
bool controlled_detector_on;
4647
std::unordered_map<std::string, unsigned int> prekill_hook_count;
@@ -52,6 +53,8 @@ void reset_counters() {
5253
stored_count = 0;
5354
controlled_detector_on = false;
5455
prekill_hook_count.clear();
56+
prerun_count_map.clear();
57+
count_map.clear();
5558
}
5659

5760
} // namespace
@@ -69,8 +72,11 @@ class ContinuePlugin : public BasePlugin {
6972
return 0;
7073
}
7174

72-
void prerun(OomdContext& /* unused */) override {
75+
void prerun(OomdContext& ctx) override {
7376
++prerun_count;
77+
if (auto rulesetCgroup = ctx.getRulesetCgroup()) {
78+
prerun_count_map[*rulesetCgroup]++;
79+
}
7480
}
7581

7682
PluginRet run(OomdContext& /* unused */) override {
@@ -92,8 +98,11 @@ class StopPlugin : public BasePlugin {
9298
return 0;
9399
}
94100

95-
void prerun(OomdContext& /* unused */) override {
101+
void prerun(OomdContext& ctx) override {
96102
++prerun_count;
103+
if (auto rulesetCgroup = ctx.getRulesetCgroup()) {
104+
prerun_count_map[*rulesetCgroup]++;
105+
}
97106
}
98107

99108
PluginRet run(OomdContext& /* unused */) override {
@@ -115,12 +124,18 @@ class IncrementCountPlugin : public BasePlugin {
115124
return 0;
116125
}
117126

118-
void prerun(OomdContext& /* unused */) override {
127+
void prerun(OomdContext& ctx) override {
119128
++prerun_count;
129+
if (auto rulesetCgroup = ctx.getRulesetCgroup()) {
130+
prerun_count_map[*rulesetCgroup]++;
131+
}
120132
}
121133

122-
PluginRet run(OomdContext& /* unused */) override {
134+
PluginRet run(OomdContext& ctx) override {
123135
++count;
136+
if (auto rulesetCgroup = ctx.getRulesetCgroup()) {
137+
count_map[*rulesetCgroup]++;
138+
}
124139
return PluginRet::CONTINUE;
125140
}
126141

@@ -139,8 +154,11 @@ class StoreCountPlugin : public BasePlugin {
139154
return 0;
140155
}
141156

142-
void prerun(OomdContext& /* unused */) override {
157+
void prerun(OomdContext& ctx) override {
143158
++prerun_count;
159+
if (auto rulesetCgroup = ctx.getRulesetCgroup()) {
160+
prerun_count_map[*rulesetCgroup]++;
161+
}
144162
}
145163

146164
PluginRet run(OomdContext& /* unused */) override {
@@ -164,8 +182,11 @@ class ControlledDetectorPlugin : public BasePlugin {
164182
return 0;
165183
}
166184

167-
void prerun(OomdContext& /* unused */) override {
185+
void prerun(OomdContext& ctx) override {
168186
++prerun_count;
187+
if (auto rulesetCgroup = ctx.getRulesetCgroup()) {
188+
prerun_count_map[*rulesetCgroup]++;
189+
}
169190
}
170191

171192
PluginRet run(OomdContext& /* unused */) override {
@@ -191,8 +212,11 @@ class AsyncPausePlugin : public BasePlugin {
191212
return 0;
192213
}
193214

194-
void prerun(OomdContext& /* unused */) override {
215+
void prerun(OomdContext& ctx) override {
195216
++prerun_count;
217+
if (auto rulesetCgroup = ctx.getRulesetCgroup()) {
218+
prerun_count_map[*rulesetCgroup]++;
219+
}
196220
}
197221

198222
PluginRet run(OomdContext& /* unused */) override {
@@ -221,8 +245,11 @@ class NoInitPlugin : public BasePlugin {
221245
return 1;
222246
}
223247

224-
void prerun(OomdContext& /* unused */) override {
248+
void prerun(OomdContext& ctx) override {
225249
++prerun_count;
250+
if (auto rulesetCgroup = ctx.getRulesetCgroup()) {
251+
prerun_count_map[*rulesetCgroup]++;
252+
}
226253
}
227254

228255
PluginRet run(OomdContext& /* unused */) override {
@@ -282,8 +309,11 @@ class KillPlugin : public BasePlugin {
282309
return 0;
283310
}
284311

285-
void prerun(OomdContext& /* unused */) override {
312+
void prerun(OomdContext& ctx) override {
286313
++prerun_count;
314+
if (auto rulesetCgroup = ctx.getRulesetCgroup()) {
315+
prerun_count_map[*rulesetCgroup]++;
316+
}
287317
}
288318

289319
PluginRet run(OomdContext& ctx) override {
@@ -805,6 +835,68 @@ TEST_F(DropInCompilerTest, PrerunCount) {
805835
EXPECT_EQ(prerun_count, 0 + 3 + 2 + 3 + 5);
806836
}
807837

838+
TEST_F(CompilerTest, RulesetCGroupCount) {
839+
IR::DetectorGroup always_yes{
840+
.name = "dg",
841+
.detectors = {IR::Detector{IR::Plugin{.name = "Continue"}}}};
842+
IR::Action cnt{IR::Plugin{.name = "IncrementCount"}};
843+
CgroupPath system_slice(kRandomCgroupFs, "system.slice");
844+
CgroupPath workload_slice(kRandomCgroupFs, "workload.slice");
845+
846+
root.rulesets = {IR::Ruleset{
847+
.name = "A",
848+
.dgs = {always_yes},
849+
.acts = {cnt},
850+
.post_action_delay = "0",
851+
.cgroup = "system.slice,workload.slice"}};
852+
853+
auto engine = compile();
854+
ASSERT_TRUE(engine);
855+
856+
// Ruleset Cgroup only gets added in runOnce. Nothing should be prerun now
857+
engine->prerun(context);
858+
EXPECT_EQ(prerun_count, 0);
859+
EXPECT_EQ(prerun_count_map.size(), 0);
860+
EXPECT_EQ(count, 0);
861+
EXPECT_EQ(count_map.size(), 0);
862+
863+
// The newly added per-cgroup rulesets should be immediately prerun.
864+
engine->runOnce(context);
865+
EXPECT_EQ(prerun_count, 4); // 2 cgroup rulesets x 2 plugins
866+
EXPECT_EQ(prerun_count_map.size(), 2);
867+
EXPECT_EQ(prerun_count_map.at(system_slice), 2);
868+
EXPECT_EQ(prerun_count_map.at(workload_slice), 2);
869+
EXPECT_EQ(count, 2); // 2 cgroup rulesets x 1 action
870+
EXPECT_EQ(count_map.size(), 2);
871+
EXPECT_EQ(count_map.at(system_slice), 1);
872+
EXPECT_EQ(count_map.at(workload_slice), 1);
873+
874+
// After the first runOnce, the per-cgroup rulesets should be prerun.
875+
engine->prerun(context);
876+
// Second prerun, everything doubled
877+
EXPECT_EQ(prerun_count, 8);
878+
EXPECT_EQ(prerun_count_map.size(), 2);
879+
EXPECT_EQ(prerun_count_map.at(system_slice), 4);
880+
EXPECT_EQ(prerun_count_map.at(workload_slice), 4);
881+
// No run yet, values should be the same
882+
EXPECT_EQ(count, 2);
883+
EXPECT_EQ(count_map.size(), 2);
884+
EXPECT_EQ(count_map.at(system_slice), 1);
885+
EXPECT_EQ(count_map.at(workload_slice), 1);
886+
887+
// The second runOnce should not prerun the existing rulesets.
888+
engine->runOnce(context);
889+
EXPECT_EQ(prerun_count, 8);
890+
EXPECT_EQ(prerun_count_map.size(), 2);
891+
EXPECT_EQ(prerun_count_map.at(system_slice), 4);
892+
EXPECT_EQ(prerun_count_map.at(workload_slice), 4);
893+
// Second run, everything doubled
894+
EXPECT_EQ(count, 4);
895+
EXPECT_EQ(count_map.size(), 2);
896+
EXPECT_EQ(count_map.at(system_slice), 2);
897+
EXPECT_EQ(count_map.at(workload_slice), 2);
898+
}
899+
808900
TEST_F(CompilerTest, NoInitPlugin) {
809901
IR::Detector noinit;
810902
noinit.name = "NoInit";

src/oomd/engine/Ruleset.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,26 @@ void Ruleset::prerun(OomdContext& context) {
125125
if (!enabled_) {
126126
return;
127127
}
128+
if (!cgroups_.has_value()) {
129+
prerunImpl(context, std::nullopt);
130+
return;
131+
}
132+
for (const auto& runnableRuleset : runnable_rulesets_) {
133+
runnableRuleset.second->prerunImpl(context, runnableRuleset.first);
134+
}
135+
}
136+
137+
void Ruleset::prerunImpl(
138+
OomdContext& context,
139+
const std::optional<CgroupPath>& ruleset_cgroup) {
140+
context.setRulesetCgroup(ruleset_cgroup);
128141
for (const auto& dg : detector_groups_) {
129142
dg->prerun(context);
130143
}
131144
for (const auto& action : action_group_) {
132145
action->prerun(context);
133146
}
147+
context.setRulesetCgroup(std::nullopt);
134148
}
135149

136150
uint32_t Ruleset::runOnce(OomdContext& context) {
@@ -349,7 +363,7 @@ void Ruleset::registerRunnableRulesetForCgroupPath(
349363
post_action_delay_,
350364
prekill_hook_timeout_,
351365
std::unordered_set{CgroupPath(cgroup.cgroupFs(), cgroup.relativePath())});
352-
ruleset->prerun(context);
366+
ruleset->prerunImpl(context, cgroup);
353367
runnable_rulesets_[cgroup] = std::move(ruleset);
354368
}
355369

src/oomd/engine/Ruleset.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ class Ruleset {
9696
void pause_actions(std::chrono::seconds duration);
9797

9898
private:
99+
void prerunImpl(
100+
OomdContext& context,
101+
const std::optional<CgroupPath>& ruleset_cgroup);
99102
uint32_t runOnceImpl(OomdContext& context);
100103
void registerRunnableRulesetForCgroupPath(
101104
OomdContext& context,

0 commit comments

Comments
 (0)