Message ID | 20181214171508.7791-5-surenb@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | psi: pressure stall monitors | expand |
On Fri, Dec 14, 2018 at 09:15:06AM -0800, Suren Baghdasaryan wrote: > The psi monitoring patches will need to determine the same states as > record_times(). To avoid calculating them twice, maintain a state mask > that can be consulted cheaply. Do this in a separate patch to keep the > churn in the main feature patch at a minimum. > > Signed-off-by: Suren Baghdasaryan <surenb@google.com> > --- > include/linux/psi_types.h | 3 +++ > kernel/sched/psi.c | 29 +++++++++++++++++++---------- > 2 files changed, 22 insertions(+), 10 deletions(-) > > diff --git a/include/linux/psi_types.h b/include/linux/psi_types.h > index 2cf422db5d18..2c6e9b67b7eb 100644 > --- a/include/linux/psi_types.h > +++ b/include/linux/psi_types.h > @@ -53,6 +53,9 @@ struct psi_group_cpu { > /* States of the tasks belonging to this group */ > unsigned int tasks[NR_PSI_TASK_COUNTS]; > > + /* Aggregate pressure state derived from the tasks */ > + u32 state_mask; > + > /* Period time sampling buckets for each state of interest (ns) */ > u32 times[NR_PSI_STATES]; > Since we spend so much time counting space in that line, maybe add a note to the Changlog about how this fits. Also, since I just had to re-count, you might want to add explicit numbers to the psi_res and psi_states enums. > + if (state_mask & (1 << s)) We have the BIT() macro, but I'm honestly not sure that will improve things.
On Mon, Dec 17, 2018 at 7:55 AM Peter Zijlstra <peterz@infradead.org> wrote: > > On Fri, Dec 14, 2018 at 09:15:06AM -0800, Suren Baghdasaryan wrote: > > The psi monitoring patches will need to determine the same states as > > record_times(). To avoid calculating them twice, maintain a state mask > > that can be consulted cheaply. Do this in a separate patch to keep the > > churn in the main feature patch at a minimum. > > > > Signed-off-by: Suren Baghdasaryan <surenb@google.com> > > --- > > include/linux/psi_types.h | 3 +++ > > kernel/sched/psi.c | 29 +++++++++++++++++++---------- > > 2 files changed, 22 insertions(+), 10 deletions(-) > > > > diff --git a/include/linux/psi_types.h b/include/linux/psi_types.h > > index 2cf422db5d18..2c6e9b67b7eb 100644 > > --- a/include/linux/psi_types.h > > +++ b/include/linux/psi_types.h > > @@ -53,6 +53,9 @@ struct psi_group_cpu { > > /* States of the tasks belonging to this group */ > > unsigned int tasks[NR_PSI_TASK_COUNTS]; > > > > + /* Aggregate pressure state derived from the tasks */ > > + u32 state_mask; > > + > > /* Period time sampling buckets for each state of interest (ns) */ > > u32 times[NR_PSI_STATES]; > > > > Since we spend so much time counting space in that line, maybe add a > note to the Changlog about how this fits. Will do. > Also, since I just had to re-count, you might want to add explicit > numbers to the psi_res and psi_states enums. Sounds reasonable. > > + if (state_mask & (1 << s)) > > We have the BIT() macro, but I'm honestly not sure that will improve > things. I was mimicking the rest of the code in psi.c that uses this kind of bit masking. Can change if you think that would be better.
On Mon, Dec 17, 2018 at 05:14:53PM -0800, Suren Baghdasaryan wrote: > On Mon, Dec 17, 2018 at 7:55 AM Peter Zijlstra <peterz@infradead.org> wrote: > > > + if (state_mask & (1 << s)) > > > > We have the BIT() macro, but I'm honestly not sure that will improve > > things. > > I was mimicking the rest of the code in psi.c that uses this kind of > bit masking. Can change if you think that would be better. Yeah, I really don't know.. keep it as is I suppose.
diff --git a/include/linux/psi_types.h b/include/linux/psi_types.h index 2cf422db5d18..2c6e9b67b7eb 100644 --- a/include/linux/psi_types.h +++ b/include/linux/psi_types.h @@ -53,6 +53,9 @@ struct psi_group_cpu { /* States of the tasks belonging to this group */ unsigned int tasks[NR_PSI_TASK_COUNTS]; + /* Aggregate pressure state derived from the tasks */ + u32 state_mask; + /* Period time sampling buckets for each state of interest (ns) */ u32 times[NR_PSI_STATES]; diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index d2b9c9a1a62f..153c0624976b 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c @@ -212,17 +212,17 @@ static bool test_state(unsigned int *tasks, enum psi_states state) static void get_recent_times(struct psi_group *group, int cpu, u32 *times) { struct psi_group_cpu *groupc = per_cpu_ptr(group->pcpu, cpu); - unsigned int tasks[NR_PSI_TASK_COUNTS]; u64 now, state_start; + enum psi_states s; unsigned int seq; - int s; + u32 state_mask; /* Snapshot a coherent view of the CPU state */ do { seq = read_seqcount_begin(&groupc->seq); now = cpu_clock(cpu); memcpy(times, groupc->times, sizeof(groupc->times)); - memcpy(tasks, groupc->tasks, sizeof(groupc->tasks)); + state_mask = groupc->state_mask; state_start = groupc->state_start; } while (read_seqcount_retry(&groupc->seq, seq)); @@ -238,7 +238,7 @@ static void get_recent_times(struct psi_group *group, int cpu, u32 *times) * (u32) and our reported pressure close to what's * actually happening. */ - if (test_state(tasks, s)) + if (state_mask & (1 << s)) times[s] += now - state_start; delta = times[s] - groupc->times_prev[s]; @@ -390,15 +390,15 @@ static void record_times(struct psi_group_cpu *groupc, int cpu, delta = now - groupc->state_start; groupc->state_start = now; - if (test_state(groupc->tasks, PSI_IO_SOME)) { + if (groupc->state_mask & (1 << PSI_IO_SOME)) { groupc->times[PSI_IO_SOME] += delta; - if (test_state(groupc->tasks, PSI_IO_FULL)) + if (groupc->state_mask & (1 << PSI_IO_FULL)) groupc->times[PSI_IO_FULL] += delta; } - if (test_state(groupc->tasks, PSI_MEM_SOME)) { + if (groupc->state_mask & (1 << PSI_MEM_SOME)) { groupc->times[PSI_MEM_SOME] += delta; - if (test_state(groupc->tasks, PSI_MEM_FULL)) + if (groupc->state_mask & (1 << PSI_MEM_FULL)) groupc->times[PSI_MEM_FULL] += delta; else if (memstall_tick) { u32 sample; @@ -419,10 +419,10 @@ static void record_times(struct psi_group_cpu *groupc, int cpu, } } - if (test_state(groupc->tasks, PSI_CPU_SOME)) + if (groupc->state_mask & (1 << PSI_CPU_SOME)) groupc->times[PSI_CPU_SOME] += delta; - if (test_state(groupc->tasks, PSI_NONIDLE)) + if (groupc->state_mask & (1 << PSI_NONIDLE)) groupc->times[PSI_NONIDLE] += delta; } @@ -431,6 +431,8 @@ static void psi_group_change(struct psi_group *group, int cpu, { struct psi_group_cpu *groupc; unsigned int t, m; + enum psi_states s; + u32 state_mask = 0; groupc = per_cpu_ptr(group->pcpu, cpu); @@ -463,6 +465,13 @@ static void psi_group_change(struct psi_group *group, int cpu, if (set & (1 << t)) groupc->tasks[t]++; + /* Calculate state mask representing active states */ + for (s = 0; s < NR_PSI_STATES; s++) { + if (test_state(groupc->tasks, s)) + state_mask |= (1 << s); + } + groupc->state_mask = state_mask; + write_seqcount_end(&groupc->seq); }
The psi monitoring patches will need to determine the same states as record_times(). To avoid calculating them twice, maintain a state mask that can be consulted cheaply. Do this in a separate patch to keep the churn in the main feature patch at a minimum. Signed-off-by: Suren Baghdasaryan <surenb@google.com> --- include/linux/psi_types.h | 3 +++ kernel/sched/psi.c | 29 +++++++++++++++++++---------- 2 files changed, 22 insertions(+), 10 deletions(-)