cpuacct.stat in no-root cgroups shows user time without guest time
included int it. This doesn't match with user time shown in root
cpuacct.stat and /proc/<pid>/stat.
Make account_guest_time() to add user time to cgroup's cpustat to
fix this.
Fixes: ef12fefabf94 ("cpuacct: add per-cgroup utime/stime statistics")
Signed-off-by: Andrey Ryabinin <redacted>
Cc: <redacted>
---
kernel/sched/cputime.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
cpuacct has 2 different ways of accounting and showing user
and system times.
The first one uses cpuacct_account_field() to account times
and cpuacct.stat file to expose them. And this one seems to work ok.
The second one is uses cpuacct_charge() function for accounting and
set of cpuacct.usage* files to show times. Despite some attempts to
fix it in the past it still doesn't work. E.g. while running KVM
guest the cpuacct_charge() accounts most of the guest time as
system time. This doesn't match with user&system times shown in
cpuacct.stat or proc/<pid>/stat.
Use cpustats accounted in cpuacct_account_field() as the source
of user/sys times for cpuacct.usage* files. Make cpuacct_charge()
to account only summary execution time.
Fixes: d740037fac70 ("sched/cpuacct: Split usage accounting into user_usage and sys_usage")
Signed-off-by: Andrey Ryabinin <redacted>
Cc: <redacted>
---
kernel/sched/cpuacct.c | 77 +++++++++++++++++++-----------------------
1 file changed, 34 insertions(+), 43 deletions(-)
@@ -29,7 +29,7 @@ struct cpuacct_usage {structcpuacct{structcgroup_subsys_statecss;/* cpuusage holds pointer to a u64-type object on every CPU */-structcpuacct_usage__percpu*cpuusage;+u64__percpu*cpuusage;structkernel_cpustat__percpu*cpustat;};
Global CPUTIME_USER counter already includes CPUTIME_GUEST
Also CPUTIME_NICE already includes CPUTIME_GUEST_NICE.
Remove additions of CPUTIME_GUEST[_NICE] to total ->sum_exec_runtime
to not account them twice.
Fixes: 936f2a70f207 ("cgroup: add cpu.stat file to root cgroup")
Signed-off-by: Andrey Ryabinin <redacted>
Cc: <redacted>
---
kernel/cgroup/rstat.c | 2 --
1 file changed, 2 deletions(-)
cpuacct.stat shows user time based on raw random precision tick
based counters. Use cputime_addjust() to scale these values against the
total runtime accounted by the scheduler, like we already do
for user/system times in /proc/<pid>/stat.
Signed-off-by: Andrey Ryabinin <redacted>
---
kernel/sched/cpuacct.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
From: Daniel Jordan <daniel.m.jordan@oracle.com> Date: 2021-03-17 22:12:10
Andrey Ryabinin [off-list ref] writes:
cpuacct.stat in no-root cgroups shows user time without guest time
included int it. This doesn't match with user time shown in root
cpuacct.stat and /proc/<pid>/stat.
Yeah, that's inconsistent.
Make account_guest_time() to add user time to cgroup's cpustat to
fix this.
Yep.
cgroup2's cpu.stat is broken the same way for child cgroups, and this
happily fixes it. Probably deserves a mention in the changelog.
The problem with cgroup2 was, if the workload was mostly guest time,
cpu.stat's user and system together reflected it, but it was split
unevenly across the two. I think guest time wasn't actually included in
either bucket, it was just that the little user and system time there
was got scaled up in cgroup_base_stat_cputime_show -> cputime_adjust to
match sum_exec_runtime, which did have it.
The stats look ok now for both cgroup1 and 2. Just slightly unsure
whether we want to change the way both interfaces expose the accounting
in case something out there depends on it. Seems like we should, but
it'd be good to hear more opinions.
Makes sense for _USER and _NICE, but it doesn't seem cgroup1 or 2
actually use _GUEST and _GUEST_NICE.
Could go either way. Consistency is nice, but I probably wouldn't
change the GUEST ones so people aren't confused about why they're
accounted. It's also extra cycles for nothing, even though most of the
data is probably in the cache.
From: Daniel Jordan <daniel.m.jordan@oracle.com> Date: 2021-03-17 22:14:56
Andrey Ryabinin [off-list ref] writes:
Global CPUTIME_USER counter already includes CPUTIME_GUEST
Also CPUTIME_NICE already includes CPUTIME_GUEST_NICE.
Remove additions of CPUTIME_GUEST[_NICE] to total ->sum_exec_runtime
to not account them twice.
Yes, that's just wrong. usage_usec looks ok now.
Reviewed-by: Daniel Jordan <redacted>
Tested-by: Daniel Jordan <redacted>
From: Daniel Jordan <daniel.m.jordan@oracle.com> Date: 2021-03-17 22:25:19
Andrey Ryabinin [off-list ref] writes:
cpuacct has 2 different ways of accounting and showing user
and system times.
The first one uses cpuacct_account_field() to account times
and cpuacct.stat file to expose them. And this one seems to work ok.
The second one is uses cpuacct_charge() function for accounting and
set of cpuacct.usage* files to show times. Despite some attempts to
fix it in the past it still doesn't work. E.g. while running KVM
guest the cpuacct_charge() accounts most of the guest time as
system time. This doesn't match with user&system times shown in
cpuacct.stat or proc/<pid>/stat.
I couldn't reproduce this running a cpu bound load in a kvm guest on a
nohz_full cpu on 5.11. The time is almost entirely in cpuacct.usage and
_user, while _sys stays low.
Could you say more about how you're seeing this? Don't really doubt
there's a problem, just wondering what you're doing.
@@ -29,7 +29,7 @@ struct cpuacct_usage {structcpuacct{structcgroup_subsys_statecss;/* cpuusage holds pointer to a u64-type object on every CPU */-structcpuacct_usage__percpu*cpuusage;
Definition of struct cpuacct_usage can go away now.
cpuacct has 2 different ways of accounting and showing user
and system times.
The first one uses cpuacct_account_field() to account times
and cpuacct.stat file to expose them. And this one seems to work ok.
The second one is uses cpuacct_charge() function for accounting and
set of cpuacct.usage* files to show times. Despite some attempts to
fix it in the past it still doesn't work. E.g. while running KVM
guest the cpuacct_charge() accounts most of the guest time as
system time. This doesn't match with user&system times shown in
cpuacct.stat or proc/<pid>/stat.
I couldn't reproduce this running a cpu bound load in a kvm guest on a
nohz_full cpu on 5.11. The time is almost entirely in cpuacct.usage and
_user, while _sys stays low.
Could you say more about how you're seeing this? Don't really doubt
there's a problem, just wondering what you're doing.
Yeah, I it's almost unnoticable if you run some load in guest like qemu.
But more simple case with busy loop in KVM_RUN triggers this:
# git clone https://github.com/aryabinin/kvmsample
# make
# mkdir /sys/fs/cgroup/cpuacct/test
# echo $$ > /sys/fs/cgroup/cpuacct/test/tasks
# ./kvmsample &
# for i in {1..5}; do cat /sys/fs/cgroup/cpuacct/test/cpuacct.usage_sys; sleep 1; done
1976535645
2979839428
3979832704
4983603153
5983604157
@@ -29,7 +29,7 @@ struct cpuacct_usage {structcpuacct{structcgroup_subsys_statecss;/* cpuusage holds pointer to a u64-type object on every CPU */-structcpuacct_usage__percpu*cpuusage;
Definition of struct cpuacct_usage can go away now.
Sorry for abandoning this, got distracted by lots of other stuff.
On 3/18/21 1:09 AM, Daniel Jordan wrote:
Andrey Ryabinin [off-list ref] writes:
quoted
cpuacct.stat in no-root cgroups shows user time without guest time
included int it. This doesn't match with user time shown in root
cpuacct.stat and /proc/<pid>/stat.
Yeah, that's inconsistent.
quoted
Make account_guest_time() to add user time to cgroup's cpustat to
fix this.
Yep.
cgroup2's cpu.stat is broken the same way for child cgroups, and this
happily fixes it. Probably deserves a mention in the changelog.
Sure.
The problem with cgroup2 was, if the workload was mostly guest time,
cpu.stat's user and system together reflected it, but it was split
unevenly across the two. I think guest time wasn't actually included in
either bucket, it was just that the little user and system time there
was got scaled up in cgroup_base_stat_cputime_show -> cputime_adjust to
match sum_exec_runtime, which did have it.
The stats look ok now for both cgroup1 and 2. Just slightly unsure
whether we want to change the way both interfaces expose the accounting
in case something out there depends on it. Seems like we should, but
it'd be good to hear more opinions.
Makes sense for _USER and _NICE, but it doesn't seem cgroup1 or 2
actually use _GUEST and _GUEST_NICE.
Could go either way. Consistency is nice, but I probably wouldn't
change the GUEST ones so people aren't confused about why they're
accounted. It's also extra cycles for nothing, even though most of the
data is probably in the cache.
cpuacct.stat in no-root cgroups shows user time without guest time
included int it. This doesn't match with user time shown in root
cpuacct.stat and /proc/<pid>/stat. This also affects cgroup2's cpu.stat
in the same way.
Make account_guest_time() to add user time to cgroup's cpustat to
fix this.
Fixes: ef12fefabf94 ("cpuacct: add per-cgroup utime/stime statistics")
Signed-off-by: Andrey Ryabinin <redacted>
Cc: <redacted>
---
Changes since v1:
- Don't CPUTIME_GUEST* since they aren't used cgroups
---
kernel/sched/cputime.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
cpuacct has 2 different ways of accounting and showing user
and system times.
The first one uses cpuacct_account_field() to account times
and cpuacct.stat file to expose them. And this one seems to work ok.
The second one is uses cpuacct_charge() function for accounting and
set of cpuacct.usage* files to show times. Despite some attempts to
fix it in the past it still doesn't work. Sometimes while running KVM
guest the cpuacct_charge() accounts most of the guest time as
system time. This doesn't match with user&system times shown in
cpuacct.stat or proc/<pid>/stat.
Demonstration:
# git clone https://github.com/aryabinin/kvmsample
# make
# mkdir /sys/fs/cgroup/cpuacct/test
# echo $$ > /sys/fs/cgroup/cpuacct/test/tasks
# ./kvmsample &
# for i in {1..5}; do cat /sys/fs/cgroup/cpuacct/test/cpuacct.usage_sys; sleep 1; done
1976535645
2979839428
3979832704
4983603153
5983604157
Use cpustats accounted in cpuacct_account_field() as the source
of user/sys times for cpuacct.usage* files. Make cpuacct_charge()
to account only summary execution time.
Fixes: d740037fac70 ("sched/cpuacct: Split usage accounting into user_usage and sys_usage")
Signed-off-by: Andrey Ryabinin <redacted>
Cc: <redacted>
---
Changes since v1:
- remove struct cpuacct_usage;
---
kernel/sched/cpuacct.c | 79 +++++++++++++++++-------------------------
1 file changed, 32 insertions(+), 47 deletions(-)
@@ -21,15 +21,11 @@ static const char * const cpuacct_stat_desc[] = {[CPUACCT_STAT_SYSTEM]="system",};-structcpuacct_usage{-u64usages[CPUACCT_STAT_NSTATS];-};-/* track CPU usage of a group of tasks and its child groups */structcpuacct{structcgroup_subsys_statecss;/* cpuusage holds pointer to a u64-type object on every CPU */-structcpuacct_usage__percpu*cpuusage;+u64__percpu*cpuusage;structkernel_cpustat__percpu*cpustat;};
From: Andrey Ryabinin <redacted>
cpuacct.stat shows user time based on raw random precision tick
based counters. Use cputime_addjust() to scale these values against the
total runtime accounted by the scheduler, like we already do
for user/system times in /proc/<pid>/stat.
Signed-off-by: Andrey Ryabinin <redacted>
---
Changes since v1:
- fix cputime.sum_exec_runtime calculation
---
kernel/sched/cpuacct.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
Global CPUTIME_USER counter already includes CPUTIME_GUEST
Also CPUTIME_NICE already includes CPUTIME_GUEST_NICE.
Remove additions of CPUTIME_GUEST[_NICE] to total ->sum_exec_runtime
to not account them twice.
Fixes: 936f2a70f207 ("cgroup: add cpu.stat file to root cgroup")
Signed-off-by: Andrey Ryabinin <redacted>
Cc: <redacted>
Reviewed-by: Daniel Jordan <redacted>
Tested-by: Daniel Jordan <redacted>
---
Changes since v1:
- Add review/tested tags in changelog
---
kernel/cgroup/rstat.c | 2 --
1 file changed, 2 deletions(-)
On Fri, Aug 20, 2021 at 12:40:01PM +0300, Andrey Ryabinin wrote:
cpuacct.stat in no-root cgroups shows user time without guest time
included int it. This doesn't match with user time shown in root
cpuacct.stat and /proc/<pid>/stat. This also affects cgroup2's cpu.stat
in the same way.
Make account_guest_time() to add user time to cgroup's cpustat to
fix this.
Fixes: ef12fefabf94 ("cpuacct: add per-cgroup utime/stime statistics")
Signed-off-by: Andrey Ryabinin <redacted>
Cc: <redacted>
The fact that this has been broken for so long, prolly from the beginning,
gives me some pause but the patches looks fine to me.
For the series,
Acked-by: Tejun Heo <tj@kernel.org>
Thanks.
--
tejun
From: Daniel Jordan <daniel.m.jordan@oracle.com> Date: 2021-09-10 19:04:23
On Fri, Aug 20, 2021 at 12:40:04PM +0300, Andrey Ryabinin wrote:
cpuacct has 2 different ways of accounting and showing user
and system times.
The first one uses cpuacct_account_field() to account times
and cpuacct.stat file to expose them. And this one seems to work ok.
The second one is uses cpuacct_charge() function for accounting and
set of cpuacct.usage* files to show times. Despite some attempts to
fix it in the past it still doesn't work. Sometimes while running KVM
guest the cpuacct_charge() accounts most of the guest time as
system time. This doesn't match with user&system times shown in
cpuacct.stat or proc/<pid>/stat.
Demonstration:
# git clone https://github.com/aryabinin/kvmsample
# make
# mkdir /sys/fs/cgroup/cpuacct/test
# echo $$ > /sys/fs/cgroup/cpuacct/test/tasks
# ./kvmsample &
# for i in {1..5}; do cat /sys/fs/cgroup/cpuacct/test/cpuacct.usage_sys; sleep 1; done
1976535645
2979839428
3979832704
4983603153
5983604157
Thanks for expanding on this, and fixing broken cpuacct_charge.
For the series,
Reviewed-by: Daniel Jordan <daniel.m.jordan@oracle.com>