CPU Limits Confusion

I am a bit confused about if I should use:

limits.cpu 1
limits.cpu.allowance 25%

to limit the container to a quarter of one cpu or:

limits.cpu.allowance 25ms/100ms

Here is says:

Just give me X CPUs
In this mode, you let LXD pick a bunch of cores for you and then load-balance things as more containers and CPUs go online/offline.
The container only sees that number of CPU.
Give me a specific set of CPUs (say, core 1, 3 and 5)
Similar to the first mode except that no load-balancing is happening, you’re stuck with those cores no matter how busy they may be.
Give me 20% of whatever you have
In this mode, you get to see all the CPUs but the scheduler will restrict you to 20% of the CPU time but only when under load! So if the system isn’t busy, your container can have as much fun as it wants. When containers next to it start using the CPU, then it gets capped.
Out of every measured 200ms, give me 50ms (and no more than that)
This mode is similar to the previous one in that you get to see all the CPUs but this time, you can only use as much CPU time as you set in the limit, no matter how idle the system may be. On a system without over-commit this lets you slice your CPU very neatly and guarantees constant performance to those containers.

It’s also possible to combine one of the first two with one of the last two, that is, request a set of CPUs and then further restrict how much CPU time you get on those.

But there it says:

limits.cpu.allowance drives either the CFS scheduler quotas when passed a time constraint, or the generic CPU shares mechanism when passed a percentage value.

The time constraint (e.g. 20ms/50ms) is relative to one CPU worth of time, so to restrict to two CPUs worth of time, something like 100ms/50ms should be used.

So which is true?
The time measurement applies to the whole cpu time available or only to one?

1 Like
limits.cpu: 1
limits.cpu.allowance: 25%

This will have LXD pick a CPU core for you and pin your container to it, so no matter how busy that core is, your container will always be stuck with it. On that core, should there be more than one container, the scheduler will be configured to give at least 25% of the time to the container (done through tweaks to the process priorities effectively).

limits.cpu.allowance: 25ms/100ms

With this, no pinning is setup and the scheduler is told to give up to 25% of a single CPU worth of time to the container.

I think the LXD docs are slightly more specific in that regard as the multi-CPU case with CFS scheduler budgets is something we looked into much after I wrote the blog post :slight_smile:


Thanks for the great explanation that solves my confusion!

Is there a functional difference between these examples?

limits.cpu.allowance: 1ms/4ms
limits.cpu.allowance: 25ms/100ms
limits.cpu.allowance: 100ms/400ms

In theory, they all are 25% of CPU time, but does it matter which format is used?

I’d expect the scheduler to give you as much CPU time with all of those.

I know this might be old but I did a test on 19wolf’s questions. Seems 1/4, 100/400, etc is not the same.
I have 8 core cpu so I ran ‘apt update’ and timed it for a container for 1ms/8ms, 100ms/800ms, 100ms/100/ms. Just timed how long it took to complete that command and be back at the command prompt. All should equal 1 core worth on my 8 core system.
100/100 = 7.5 secs
100/800 = 60 secs
1/8 = 2 minutes 18 secs.
Ran multiple times switching container back and forth to each spec/ms.