CPU spinning is something that has been around in NDB for a long time. This CPU
spinning has been static which means that each time a thread wakes up it will spin
waiting for incoming signals. Thus if spin time is set to e.g. 500 microsecond we will
spin 5% of the time even when there is no activity since each thread wakes up each
10 ms to perform timer based activities.
In the new spinning approach we wanted to achieve the following.
- Power efficient CPU spinning
NDB Cluster data nodes can execute queries very efficiently, this leads to efficient
power usage. However CPU spinning requires careful control to ensure that one
doesn't waste power while spinning.
- No spinning unless there is something to gain from it
Static spinning will always spin independent of whether it makes sense.
With the new approach we gather statistics about the usefulness of spinning. This
means that when the thread goes to sleep we will collect statistics on the sleep
time when the thread wakes up again. With this information we are able to calculate
the gains from spinning. We also calculate the cost of going to sleep and waking up
again (this cost is higher usually in virtual machines compared to bare metal servers).
One important part of CPU spinning is what we do while spinning. In x86 and ARM
CPUs there exists CPU instructions for spinning. While spinning we will spend around
one microsecond in the spinning state before checking for input again. Going to sleep
and waking up again can consume between 10 and 50 microseconds dependent on
OS, hardware and whether we are running in a VM, in Docker and so forth. These
special assembler instructions will ensure that the CPU doesn't use so much power
and in hyperthreaded CPUs the other hyperthread(s) will get almost exclusive access
to the CPU core while spinning is performed.
The adaptive part of our new CPU spinning is that we will keep track of the workload
and its ability to benefit from CPU spinning. We do so through a number of
configuration parameters. However for ease of use we have only 4 variants that one
The configuration parameter SpinMethod is used to set the variant of CPU spinning to
use. The following settings are available:
This is the default setting. This means that we will only spin when we actually benefit
from it. This means that if we spend 10 microseconds spinning we will gain 10
microseconds from spinning in avoiding the cost of going to sleep and waking up.
This is a conservative setting that ensures good power efficiency and avoids issues
in situations where the data nodes executes in a shared environment.
This setting is a very good trade off between best latency and best power efficiency.
Here we will spin if 10 microseconds of spinning can gain 1-2 microseconds of
avoided costs of going to sleep and waking up. This is recommended to use in cases
where the data nodes executes in an exclusive environment, e.g. in its own virtual
machine, Docker container or even exclusively using the entire server. This provides
a very distinct advantage in latency of queries as we will show in a later blog.
This setting provides the optimal latency at the expense of decreased power
efficiency. This setting is intended for use cases where latency is of outmost important
and one is willing to sacrifice some extra power to achieve this.
This disables the adaptive spinning and makes NDB Cluster backwards compatible.