-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Stop CPU accounting to require CPU controller #9665
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
|
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? |
|
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). |
|
@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? |
|
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. |
|
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; |
|
Thank you for examining this issue. I will revise PR, hopefully on Saturday. |
Added kernel version check in order to see if CPU_MASK has to be enabled when CPU accounting is requested.
|
I updated the commit to check the kernel version as instructed. |
poettering
left a comment
There was a problem hiding this 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; |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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; | ||
|
|
There was a problem hiding this comment.
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)
|
Let's close this in favour of #10507. |
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).
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).
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).
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).
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).
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).
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).
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).
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).
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).
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).
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).
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).
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).
In the unified cgroup hierarchy, some CPU accounting information,
usage_usec,user_usec,system_usecare always available in thecpu.statfile, while the CPU controller provides additional informationnr_periods,nr_throttled,throttled_usecin thecpu.statfile. This behavior is defined in https://www.kernel.org/doc/Documentation/cgroup-v2.txt. On the other hand, systemd'sunit_get_cpu_usage_raw()only usesusage_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.