-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
core: add CPUQuotaPeriodSec= #9594
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
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.
Looks good, just minro nitpicks.
cc @htejun
src/core/load-fragment.c
Outdated
| /* Valid range for period in cpu.max is [1ms, 1s]: | ||
| * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/sched/core.c?h=v4.18-rc5#n6545 */ | ||
| if (u < 1 * USEC_PER_MSEC || u > 1 * USEC_PER_SEC) { | ||
| log_syntax(unit, LOG_ERR, filename, line, r, "CPU quota period '%s' outside of the valid range [1ms, 1s], ignoring.", rvalue); |
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.
should pass 0 instead of r as 5th argument. (is not actually going to make a difference during runtime, since r is 0, but is semantically more correct)
src/shared/bus-unit-util.c
Outdated
| usec_t u = 0; | ||
|
|
||
| if (!isempty(eq)) { | ||
| r = parse_time(eq, &u, MSEC_PER_SEC); |
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, I am not sure about using ms as default unit here. Currently there's exactly one spot where we deviate from the default unit of seconds which we otherwise universally use: the parsing of RLIMIT_RTTIME values. And the primary reason we parse with a default unit if µs there is for "downwards compat", i.e. simply because setting RLIMIT_RTTIME is widely supported in various tools (think: shell's ulimit command), where it always exposes the raw kernel unit of µs, and we should remain compatible to that. Now, i don't think CPUQuotaPeriod= is a similar case though, it's relatively exotic, and people seldom will echo these values directly to cgroupfs...
Or to say this differently: to deviate from the default unit of seconds for time values needs some major reasons, and I don't think this case qualifies. Having uniformity within the systemd codebase regarding time units is more important here...
Or in shorter words: please just use parse_sec() here!
src/shared/bus-unit-util.c
Outdated
| r = parse_time(eq, &u, MSEC_PER_SEC); | ||
| if (r < 0) { | ||
| log_error_errno(r, "CPU quota period '%s' invalid.", eq); | ||
| return -EINVAL; |
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.
why not merge these two lines into: return log_error_errno(r, …...
src/shared/bus-unit-util.c
Outdated
| /* Valid range for period in cpu.max is [1ms, 1s]: | ||
| * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/sched/core.c?h=v4.18-rc5#n6545 */ | ||
| if (u < 1 * USEC_PER_MSEC || u > 1 * USEC_PER_SEC) | ||
| return log_error_errno(-ERANGE, "CPU quota period '%s' outside of the valid range [1ms, 1s].", eq); |
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.
so far we had the rule, that our logging calls would only log error codes that have been received from somewhere else, rather than error codes that are generated here. (@keszybz disagrees with that rule however, and maybe we should revisit this) However for now I think we should stick to this rule, hence please rework this bit to:
if (…) {
log_error("CPU quota…
return -ERANGE;
}|
(btw, i am fully aware the define drange is [1ms…1s] and hence using seconds as default unit on the first look makes little sense. However, do note that we support a syntax such as "0.5" too, which I think should mean 500ms... |
|
I am wonder if this is one of the cases where clamping the value to the defined range plus warning is better than warning and ignoring the whole setting. I mean, this is a very "soft tune" value, i.e. it's not something that makes or breaks stuff, but rather a fine tune thing that just slightly optimizes behaviour for stuff that works anyway. Hence I think being permissive here and apply the closest we can apply makes sense I think |
| $1.CPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.cpu_shares) | ||
| $1.StartupCPUShares, config_parse_cpu_shares, 0, offsetof($1, cgroup_context.startup_cpu_shares) | ||
| $1.CPUQuota, config_parse_cpu_quota, 0, offsetof($1, cgroup_context) | ||
| $1.CPUQuotaPeriod, config_parse_cpu_quota_period, 0, offsetof($1, cgroup_context) |
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, in light of the other discussions this should probably be called CPUQuotaPeriodSec= or so
src/core/dbus-cgroup.c
Outdated
| else | ||
| unit_write_settingf(u, flags, "CPUQuotaPeriod", | ||
| "CPUQuotaPeriod=%lums", | ||
| (unsigned long) (c->cpu_quota_period_usec / USEC_PER_MSEC)); |
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.
USEC_FMT rather than %lu please
|
Yes, clamping sounds right, since in further testing this I realized that if CPUQuota= gets outside of the range than the setting will fail too, so need to make sure both settings are hand-in-hand and then clamp them when they get out-of-range. (This will potentially make this a bit more complex, since we probably want to store the configured value, but we might also want to store the clamped values as well...) Anyways, I'll address that and also your other comments, I'll let you know when I have an updated version for you to look into. Cheers! |
Nah, note that CPUQuota= takes a percentage value, i.e. a value relative to 100. Internally we then store that relative to 1s, for greater granularity. But this means it's CPUQuota= and CPUQuotaPeriodSec= can be stored fully independently, as conversion of CPUQuota= to µs only happens right at the time we write it to cgroupfs |
bcf95e3 to
7913c27
Compare
|
Updated the PR. I'm now using seconds by default. I added some code to time-util to handle clamping the pair I tested everything again (on unified hierarchy) and everything seems to work fine. The one bit I couldn't manage to trigger is the code in src/core/dbus-cgroup.c that does a unit_write_setting() to update a unit in /run/systemd/system... Should All the comments from the previous revision are no longer relevant (since that code is gone) or have been addressed. PTAL. |
|
This has been updated (on Friday) and it's ready for a new review. Please take another look. |
man/systemd.resource-control.xml
Outdated
| <para>Assign the duration over which the CPU time quota specified by <varname>CPUQuota=</varname> is measured. | ||
| Takes a time duration value in seconds, with an optional suffix such as "ms" for milliseconds (or "s" for seconds.) | ||
| The default setting is 100ms. The period and the time calculated for the quota need to be in the range of | ||
| [1ms, 1000ms], so they will be clamped to that interval if any of them are outside it, while still preserving the ratio. |
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 there's some confusion around CPUQuota here... Note that CPUQuota= takes a percentage from the user, i.e. already a ratio (i.e. relative to 100). Internally, to maintain a larger granularity it is stored relative to 1,000,000 however, but still as a ratio.
i.e.:
- if the user specifies
CPUQuota=3%, then we'll store it intrenally as 30,000 instead. - if the user specifies
CPUQuota=60%, then we'll store it internally as 600,000 instead. - if the user specifies
CPUQuota=75%, then we'll store it internally as 750,000 instead. - if the user specifies
CPUQuota=99%, then we'll store it internally as 990,000 instead. - if hte user specifies
CPUQuota=100%, then we'll store it internally as 1,000,000 instead.
Moreover, it's actually entirely OK to assign a service 200% CPU time, as the time spend on each CPU is counted individually, and hence 200% means effectively "100% on max 2 cpus", if you follow...
This then means:
- if the user specifies
CPUQuota=234%, then we'll store it internally as 2,340,000 instead. - if the user specifies
CPUQuota=4567%, then we'll store it internally as 45,670,000 instead. (which means the user could get full CPU time on a whopping 45 cpus before he maxes out!)
This also means that CPUQuota= never needs clamping (as it's a ratio anyway, and is fine with values > 100%)
To make this even more interesting, with #9484 we start supporting permille values too for this(either suffixed by ‰ or with a single fractional digit), in that case:
- if the user specifies
CPUQuota=134‰we store this as 134,000 - if the user specifies
CPUQuota=17.8%we store this as 178,000
Given that we store things internally like this (i.e. as a ratio, and not as a time) things become a lot easier, and clamping is only necessary for the value configured with CPUQuotaPeriodSec=, but not for the value configured with CPUQuota=.
Hope this makes sense?
src/shared/bus-unit-util.c
Outdated
| } | ||
|
|
||
| if (streq(field, "CPUQuotaPeriodSec")) { | ||
| usec_t u = 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.
we usually use the maximum value for resetting properties, not zero. Hence, please set this to u = USEC_INFINITY here.
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.
So I was thinking about this one in particular, and I'm not sure I agree in this case... I can see how using USEC_INFINITY makes sense for something like WatchdogSec= or TimeoutSec=, where setting it to infinity is essentially the same as disabling it... So I can see the logic in that.
But in this case, the default value is actually in the middle of the interval, so I'm not that convinced that 0 is not as good a choice as USEC_INFINITY would be.
In fact, I think someone setting CPUQuotaPeriodSec=infinity explicitly would expect to get the maximum allowed value in the interval (in other words, 1 second) rather than the default one (100 ms), no?
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.
but following this logic, you could also say that "0" should result in the smallest period, no, i.e. 1ms?
| } else if (streq(name, "CPUQuotaPeriodUSec")) { | ||
| uint64_t u64; | ||
|
|
||
| r = sd_bus_message_read(message, "t", &u64); |
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.
so, we usually use the the maximum value of the type as indicator for "unset", hence we should refuse u64 == 0 here (as zero-length periods are not defined)
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.
Sounds good. But is it OK for me to keep using parse_time to parse the time from the config file? That one accepts 0 as a valid value... What should I do with that case?
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.
for the unit files, filter it out right after calling parse_time(). for the bus API filter out server side where we receive the time value, i.e. at this place here.
src/core/dbus-cgroup.c
Outdated
| if (!UNIT_WRITE_FLAGS_NOOP(flags)) { | ||
| c->cpu_quota_period_usec = u64; | ||
| unit_invalidate_cgroup(u, CGROUP_MASK_CPU); | ||
| if (c->cpu_quota_period_usec == 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.
in accordance with the comment above, this should check if (c->cpu_quota_period_usec == USEC_INFINITY)
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.
not addressed yet
src/core/cgroup.c
Outdated
| static void cgroup_apply_legacy_cpu_config(Unit *u, uint64_t shares, uint64_t quota) { | ||
| static void cgroup_apply_legacy_cpu_config(Unit *u, uint64_t shares, uint64_t quota, uint64_t period) { | ||
| char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1]; | ||
| usec_t bandwidth; |
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.
this is not actually used, is it?
src/core/cgroup.c
Outdated
| "%sCPUShares=%" PRIu64 "\n" | ||
| "%sStartupCPUShares=%" PRIu64 "\n" | ||
| "%sCPUQuotaPerSecSec=%s\n" | ||
| "%sCPUQuotaPeriodUSec=%s\n" |
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.
USec → Sec
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.
So here I was trying to keep the DBus names, which typically use USec suffix on settings that use Sec in the config file...
Though I see the one for CPUQuota doesn't really match exactly the one from DBus, since it's PerSecUSec there and PerSecSec here... What would be correct here do you think?
Should I adjust the CPUQuotaPerSecSec= here to become CPUQuotaPerSecUSec=? (and stop using format_timespan there) or should I use CPUQuotaPeriodSec= here? (If the former, then why not report CPUQuota= with a percentage value here, since that would match the actual configuration?)
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.
we try to keep the prop names in unit files and on the bus objects in sync, but the former usually leans more to the "user friendly" side, while the latter to the "normalized" side. This means the unit file usually lists stuff with seconds as default unit, while the latter exposes stuff normalized to usec like we use everyhere else.
the "dump" calls exist only for debugging, hence we are a bit sloppy there, but usually we show the user friendly version, except where we don't. If in doubt we should probably show the user friendly version there, unless there's a good reason to show the low-level version...
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.
this hasn't been addressed yet...
src/core/cgroup.c
Outdated
| /* Always use default period for infinity quota. */ | ||
| *period = CGROUP_CPU_QUOTA_DEFAULT_PERIOD_USEC; | ||
| else { | ||
| if (*period == 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.
as mentioned elsewhere we should really use == USEC_INFINITY as marker for "default period" not zero, for the only reason that we tend to standardize using a type's max value for marking "undefined"
src/basic/time-util.c
Outdated
| * Returns true if some clamping has been performed, in which case | ||
| * *a and *b will be updated with the new values. | ||
| */ | ||
| bool clamp_time_interval(usec_t *a, usec_t *b, usec_t min, usec_t max) { |
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 am not sure i grok why we need this function... the ratio is stored as ratio anyway, hence when the period is altered the ratio doesn't have to be changed.
We should simply clamp the period early (i.e. while parsing) and then at the time we write to cgroupfs calculate the time value from the period and the ratio.
This also means the ratio never has to be clamped.
i.e. if you say 76% quota, then it means mostly the same regardless if you operate with a 100ms period or a 500ms period: as long as we calculate 76% of the period at the instant we write to cgroupfs we are fine.
Also note quota above 100% is completely OK, as the value is counted per CPU, hence 200% means 2 cpus full time.
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.
So we need this because both period and quota * period (not sure what to call this one... bandwidth?) need to be within the [1ms, 1s] interval.
So if I have CPUQuota=40% and CPUQuotaPeriodSec=10ms, then the first field will be set to 4ms and everything is fine (no clamping needed.) However, if I have the same CPUQuota=40% but CPUQuotaPeriodSec=2ms, then this needs clamping, even though the period is in the allowed interval! But quota * period = 0.8ms is out of it, so this needs to be clamped to 1ms (for the quota * period product, minimum in the range) and 2.5ms for the period, in order to keep the ratio of 40%.
Does this make sense now?
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, so this is just about ensuring the value never becomes 0 after scaling?
I think to deal with that a scaling that rounds up would make sense (which I think would be wise anyway). I.e.
(quota * period + 999999) / 1000000
With that logic we'd never go to zero, given that neither quota nor period can be zero...
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.
No, it's not about zero... It's about making sure that the calculated slice quota * period is also in the [1ms, 1s] range. Otherwise, writing to the cgroup file (at least in cgroupv2) fails.
Like, with this example, CPUQuota=40% and CPUQuotaPeriodSec=2ms, the calculated slice quota * period = 0.8ms, but setting cpu.max to 800 2000 fails. So this needs to be scaled up to 1000 2500, which is the smallest possible period that satisfies both period and quota * period being within the valid interval.
I hope this makes sense?
I'll definitely add more comments here...
I think other than the check for division by zero, this function should be OK. But I'm open to using a slightly different prototype, perhaps sending the quota as is (a percentage) and then just returning the calculated period back... But I think this prototype works fine as is, it's pretty generic and avoids us having to calculate that more than once...
What do you think would be a good name for quota * period? I thought of bandwidth or slice...
One part that is confusing in this code is this other function (cgroup_cpu_adjust_quota_period) which takes quota as an argument (by reference) but returns quota * period (i.e. slice or bandwidth) in that same argument... Perhaps that could use some improvement.
Cheers,
Filipe
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.
Ping? Please see this comment here, I think that's the main point of contention that needs clarification now. Thanks!
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.
so the range is actually only 1ms…1s for the period but for quota*period there is no upper limit, only 1ms lower limit.
now, i am not entirely sure what the right approach to clamping here is if these limits are breached. if i understand you correctly then you opted for a scheme where the quota is kept in effect and the period and the period adjusted if needed. i.e. you consider quota more relevant than period. I figure that makes sense indeed.
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.
What do you think would be a good name for quota * period? I thought of bandwidth or slice...
the kernel calls that quota too...
maybe call it "quota_absolute" or so?
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.
Ah indeed I didn't realize that setting quota_absolute > 1s actually worked... That makes this a bit more complicated, but I'll take a look and see if I can make it nicer.
(And yes, I like quota_absolute, will use that.)
src/basic/time-util.c
Outdated
| if (*a > *b) | ||
| return clamp_time_interval(b, a, min, max); | ||
| if (*a < min) { | ||
| usec_t new_high = min * (*b) / (*a); |
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.
needs division by zero check
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.
btw, this check can be an assert() if we filtered out zero already during parsing and hence know the value can't be zero here anyway...
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.
Sounds good.
|
What about the default for period... Do you insist on USEC_INFINITY (I can do that change then), or do you agree with my previous argument that using 0 for that is acceptable here? |
Yeah, I'd prefer that. Pretty much everywhere else we use UINT64_MAX (or its aliases (uint64_t) -1, USEC_INFINITY, …) as marker for "does not apply" or "not set", and I think we should stick to that here too |
|
Sounds good. I'll address these pointers and ask you to take another look when it's ready... Thanks! |
|
any update? (also needs rebase) |
I updated the code a while ago, but didn't have time to test it thoroughly... Will try to come back to this next week if I find a bit of time... |
2745cc3 to
6e610a1
Compare
|
Ah, I totally missed that you pushed a new version. For some reason github more often than not doesn't notify us about that, hence whenever you push a new version please also add a quick comment, so that we know |
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.
looks excellent, just some minor notes
src/core/cgroup.c
Outdated
| "%sCPUShares=%" PRIu64 "\n" | ||
| "%sStartupCPUShares=%" PRIu64 "\n" | ||
| "%sCPUQuotaPerSecSec=%s\n" | ||
| "%sCPUQuotaPeriodUSec=%s\n" |
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.
this hasn't been addressed yet...
src/shared/bus-unit-util.c
Outdated
| } | ||
|
|
||
| if (streq(field, "CPUQuotaPeriodSec")) { | ||
| usec_t u = 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.
but following this logic, you could also say that "0" should result in the smallest period, no, i.e. 1ms?
src/core/dbus-cgroup.c
Outdated
| if (!UNIT_WRITE_FLAGS_NOOP(flags)) { | ||
| c->cpu_quota_period_usec = u64; | ||
| unit_invalidate_cgroup(u, CGROUP_MASK_CPU); | ||
| if (c->cpu_quota_period_usec == 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.
not addressed yet
| log_unit_full(u, LOG_WARNING, 0, | ||
| "Clamping CPU interval for cpu.max: period is now %s", | ||
| format_timespan(v, sizeof(v), new_period, 1)); | ||
| } |
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, so this way we'll log at LOG_WARNING whenever we realize the cgroup, which might be quite often. We really should generate this message only once though I think (and downgrade to LOG_DEBUG from then on). Maybe add a bool flag to the unit stores whether we already warned, and if so, doesn't warn again?
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.
This one hasn't been addressed yet. The problem with "already warned" is how to clear it every time the value is updated... I've been thinking of storing the last clamped value instead, that way I can compare to it and skip warning if it still matches. Will update with a separate commit on top once I figure out how to fix this.
3e2bc70 to
fb090a3
Compare
fb090a3 to
aa9f956
Compare
|
I just pushed a new version that uses USEC_INFINITY for the default (100ms) and doesn't clamp quota to 1s (only period can be at most 1s.) It also addresses the case where I still haven't addressed the issue with LOG_WARNING being too frequent, I'll investigate that and push a separate commit to fix that. Otherwise, I think this should be ready for review and possibly merge. Cheers! |
|
Hmmm, |
aa9f956 to
0e9314c
Compare
This works like parse_sec() but defaults to USEC_INFINITY when passed an empty string or only whitespace. Also introduce config_parse_sec_def_infinity, which can be used to parse config options using this function. This is useful for time options that use "infinity" for default and that can be reset by unsetting them. Introduce a test case to ensure it works as expected.
This new setting allows configuration of CFS period on the CPU cgroup, instead of using a hardcoded default of 100ms. Tested: - Legacy cgroup + Unified cgroup - systemctl set-property - systemctl show - Confirmed that the cgroup settings (such as cpu.cfs_period_ns) were set appropriately, including updating the CPU quota (cpu.cfs_quota_ns) when CPUQuotaPeriodSec= is updated. - Checked that clamping works properly when either period or (quota * period) are below the resolution of 1ms, or if period is above the max of 1s.
After the first warning log, further messages are downgraded to LOG_DEBUG.
0e9314c to
527ede0
Compare
|
@poettering Please take a look, I believe this one is ready to go or very close to it... I think I have addressed all the items you mentioned. I just retested this on top of v241 and everything seems to be working as expected. There are some quirks with the logs, for instance running Anyways, let me know if you think this still needs changes or if it's good to go. Cheers! |
I think this is fine. In fact, even desirable. Whenever we reread config we should warn again.
Hmm, so this is a general problem, not specific to this new setting, but applies to all settings. I don't really have a good answer for this. Might be worth filing a new issue about this.
I think the PR is good to go in, let's see if people complain before we tweak the log level further. |
This new setting allows configuration of CFS period on the CPU cgroup, instead of using a hardcoded default of 100ms.
Tested:
systemctl set-propertysystemctl showcpu.cfs_period_ns) were set appropriately, including updating the CPU quota (cpu.cfs_quota_ns) whenCPUQuotaPeriodSec=is updated.periodor(quota * period)is out of the[1ms, 1s]range.Fixes #9081
/cc @derekwaynecarr