Skip to content

Commit 0ec208c

Browse files
tursulinPeter Zijlstra
authored andcommitted
sched/psi: Optimise psi_group_change a bit
The current code loops over the psi_states only to call a helper which then resolves back to the action needed for each state using a switch statement. That is effectively creating a double indirection of a kind which, given how all the states need to be explicitly listed and handled anyway, we can simply remove. Both the for loop and the switch statement that is. The benefit is both in the code size and CPU time spent in this function. YMMV but on my Steam Deck, while in a game, the patch makes the CPU usage go from ~2.4% down to ~1.2%. Text size at the same time went from 0x323 to 0x2c1. Signed-off-by: Tvrtko Ursulin <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Chengming Zhou <[email protected]> Acked-by: Johannes Weiner <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent c793a62 commit 0ec208c

File tree

1 file changed

+27
-27
lines changed

1 file changed

+27
-27
lines changed

kernel/sched/psi.c

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -218,28 +218,32 @@ void __init psi_init(void)
218218
group_init(&psi_system);
219219
}
220220

221-
static bool test_state(unsigned int *tasks, enum psi_states state, bool oncpu)
221+
static u32 test_states(unsigned int *tasks, u32 state_mask)
222222
{
223-
switch (state) {
224-
case PSI_IO_SOME:
225-
return unlikely(tasks[NR_IOWAIT]);
226-
case PSI_IO_FULL:
227-
return unlikely(tasks[NR_IOWAIT] && !tasks[NR_RUNNING]);
228-
case PSI_MEM_SOME:
229-
return unlikely(tasks[NR_MEMSTALL]);
230-
case PSI_MEM_FULL:
231-
return unlikely(tasks[NR_MEMSTALL] &&
232-
tasks[NR_RUNNING] == tasks[NR_MEMSTALL_RUNNING]);
233-
case PSI_CPU_SOME:
234-
return unlikely(tasks[NR_RUNNING] > oncpu);
235-
case PSI_CPU_FULL:
236-
return unlikely(tasks[NR_RUNNING] && !oncpu);
237-
case PSI_NONIDLE:
238-
return tasks[NR_IOWAIT] || tasks[NR_MEMSTALL] ||
239-
tasks[NR_RUNNING];
240-
default:
241-
return false;
223+
const bool oncpu = state_mask & PSI_ONCPU;
224+
225+
if (tasks[NR_IOWAIT]) {
226+
state_mask |= BIT(PSI_IO_SOME);
227+
if (!tasks[NR_RUNNING])
228+
state_mask |= BIT(PSI_IO_FULL);
229+
}
230+
231+
if (tasks[NR_MEMSTALL]) {
232+
state_mask |= BIT(PSI_MEM_SOME);
233+
if (tasks[NR_RUNNING] == tasks[NR_MEMSTALL_RUNNING])
234+
state_mask |= BIT(PSI_MEM_FULL);
242235
}
236+
237+
if (tasks[NR_RUNNING] > oncpu)
238+
state_mask |= BIT(PSI_CPU_SOME);
239+
240+
if (tasks[NR_RUNNING] && !oncpu)
241+
state_mask |= BIT(PSI_CPU_FULL);
242+
243+
if (tasks[NR_IOWAIT] || tasks[NR_MEMSTALL] || tasks[NR_RUNNING])
244+
state_mask |= BIT(PSI_NONIDLE);
245+
246+
return state_mask;
243247
}
244248

245249
static void get_recent_times(struct psi_group *group, int cpu,
@@ -770,7 +774,6 @@ static void psi_group_change(struct psi_group *group, int cpu,
770774
{
771775
struct psi_group_cpu *groupc;
772776
unsigned int t, m;
773-
enum psi_states s;
774777
u32 state_mask;
775778

776779
groupc = per_cpu_ptr(group->pcpu, cpu);
@@ -841,10 +844,7 @@ static void psi_group_change(struct psi_group *group, int cpu,
841844
return;
842845
}
843846

844-
for (s = 0; s < NR_PSI_STATES; s++) {
845-
if (test_state(groupc->tasks, s, state_mask & PSI_ONCPU))
846-
state_mask |= (1 << s);
847-
}
847+
state_mask = test_states(groupc->tasks, state_mask);
848848

849849
/*
850850
* Since we care about lost potential, a memstall is FULL
@@ -1194,15 +1194,15 @@ void psi_cgroup_restart(struct psi_group *group)
11941194
/*
11951195
* After we disable psi_group->enabled, we don't actually
11961196
* stop percpu tasks accounting in each psi_group_cpu,
1197-
* instead only stop test_state() loop, record_times()
1197+
* instead only stop test_states() loop, record_times()
11981198
* and averaging worker, see psi_group_change() for details.
11991199
*
12001200
* When disable cgroup PSI, this function has nothing to sync
12011201
* since cgroup pressure files are hidden and percpu psi_group_cpu
12021202
* would see !psi_group->enabled and only do task accounting.
12031203
*
12041204
* When re-enable cgroup PSI, this function use psi_group_change()
1205-
* to get correct state mask from test_state() loop on tasks[],
1205+
* to get correct state mask from test_states() loop on tasks[],
12061206
* and restart groupc->state_start from now, use .clear = .set = 0
12071207
* here since no task status really changed.
12081208
*/

0 commit comments

Comments
 (0)