Skip to content

Conversation

@ghost
Copy link

@ghost ghost commented Jul 20, 2018

In the unified cgroup hierarchy, some CPU accounting information, usage_usec, user_usec, system_usec are always available in the cpu.stat file, while the CPU controller provides additional information nr_periods, nr_throttled, throttled_usec in the cpu.stat file. This behavior is defined in https://www.kernel.org/doc/Documentation/cgroup-v2.txt. On the other hand, systemd's unit_get_cpu_usage_raw() only uses usage_usec. Therefore, there is no need to enable the CPU controller in cgroup v2 when CPU accounting is required. This change prevents the CPU accounting from enabling the CPU controller when the unified cgroup is used, and meets the half of RFE 9650.

In the unified cgroup hierarchy, some CPU accounting information, usage_usec, user_usec, system_usec are always available, while the CPU controller provides additional information nr_periods, nr_throttled, throttled_usec in the cpu.stat file. This behavior is defined in https://www.kernel.org/doc/Documentation/cgroup-v2.txt . On the other hand, systemd's unit_get_cpu_usage_raw() only uses usage_usec. Therefore, there is no need to enable the CPU controller in cgroup v2 when CPU accounting is required. This change prevents the CPU accounting from enabling the CPU controller when the unified cgroup is used.
@poettering
Copy link
Member

Hmm, older kernels with cgroupsv2 didn't expose the cpu.stat file unless the CPU controller was enabled. On those we should really continue to enable the controller...

@htejun can you comment on this? What's the state there? Is it correct that on newer cgroupsv2 cpu.stat is always there regardless if "cpu" is enabled or not? Is there any nice way how we can detect kernels where it is like that?

@htejun
Copy link
Contributor

htejun commented Jul 20, 2018

Yeah, cpu.stat is always there regardless of cpu controller on newer kernels (v4.15+). On older kernels, cpu.stat requires cpu controller to be enabled, which depending on workloads could lead to noticeable overhead (we observe ~4% point higher system cpu time on context switch heavy workloads with 3-4 level of nesting).

@poettering
Copy link
Member

@htejun hmm, is there a nice way to know whether it is there without "cpu" being enabled? i.e. i need to know if i have to enable the "cpu" controller for a cgroup, but i'd like to know that ahead of time. i mean, i could create a cgroup two levels deep and check if the file is there without enabling the controller, and then i know, but i'd prefer being able to do that without creating cgroups... i could also to a kernel version check, but we usually prefer checking for features rather then kernel versions... any suggestion?

@htejun
Copy link
Contributor

htejun commented Jul 23, 2018

Hmm... unfortunately, I can't think of a way to test it without creating a cgroup; however, two level deep shouldn't be necessary. If cpu controller isn't enabled at the root, checking whether the first level children have cpu.stat should be enough.

@keszybz
Copy link
Member

keszybz commented Aug 2, 2018

I think a version check is acceptable in this case. In the unlikely scenario that somebody backports this feature into an older kernel, we will unnecessarily enable the controller. But this is just a small performance degradation without other problems. And creating cgroups just to check this is complicated and ugly and much more risky.

Please rework this to keep current behaviour if the kernel is older than 4.15. Something like this:

assert_se(uname(&u) >= 0);
bool need_compat = str_verscmp(u.release, "4.15") < 0;

@keszybz keszybz added the reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks label Aug 2, 2018
@ghost
Copy link
Author

ghost commented Aug 3, 2018

Thank you for examining this issue. I will revise PR, hopefully on Saturday.
Note added: I will wait for the conversation at #9669 to settle and to reach to an agreement (or fail to agree)

Added kernel version check in order to see if CPU_MASK has to be enabled when CPU accounting is requested.
@ghost
Copy link
Author

ghost commented Aug 3, 2018

I updated the commit to check the kernel version as instructed.

Copy link
Member

@poettering poettering left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late review. I have been travelling for more than a month, and am still catching up with queued up reviews. Sorry!

* CPU controller has to be enabled for cpu.stat to appear. Let's check it.
* Related discussion found at PR #9665. */
assert_se(uname(&u) >= 0);
need_cpumask_for_cpu_accounting = str_verscmp(u.release, "4.15") < 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, doing this on each call might be needlessly expensive... could you turn the above two lines into a function of its own, that uses an internal static variable to cache the result? If you need inspiration how that function should look like, please look for the definition of urlify_enabled() in the sources (as one example), which does this correctly...


if (c->cpu_accounting) {
mask |= CGROUP_MASK_CPUACCT;
if(need_cpumask_for_cpu_accounting)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coding style nitpick: please add a space between if and the opening (

if (c->cpu_accounting) {
mask |= CGROUP_MASK_CPUACCT;
if(need_cpumask_for_cpu_accounting)
mask |= CGROUP_MASK_CPU;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, on cgroupsv1 we should still add CPUACCT and CPU into the mask here as before, after all we always mount both controllers together there.


if ((u->cgroup_realized_mask & CGROUP_MASK_CPU) == 0)
return -ENODATA;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this test should stay, but be bypassed if the version check holds (which is cheap if it becomes its own function as suggested above)

@poettering
Copy link
Member

Let's close this in favour of #10507.

@poettering poettering closed this Oct 24, 2018
cdown added a commit to cdown/systemd that referenced this pull request Oct 25, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Oct 26, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Oct 26, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Oct 26, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Oct 26, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Oct 27, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Oct 27, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Oct 27, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Oct 30, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Oct 30, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Oct 30, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Nov 17, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Nov 17, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
cdown added a commit to cdown/systemd that referenced this pull request Nov 18, 2018
systemd only uses functions that are as of Linux 4.15+ provided
externally to the CPU controller (currently usage_usec), so if we have a
new enough kernel, we don't need to set CGROUP_MASK_CPU for
CPUAccounting=true as the CPU controller does not need to necessarily be
enabled in this case.

Part of this patch is modelled on an earlier patch by Ryutaroh Matsumoto
(see PR systemd#9665).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cgroups pid1 reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks

Development

Successfully merging this pull request may close these issues.

3 participants