Skip to content
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

fix: Parallelism CPU calculation inside Kubernetes and Docker with limits #799

Merged
merged 8 commits into from
Feb 1, 2025
23 changes: 16 additions & 7 deletions hooks/_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ function common::is_hook_run_on_whole_repo {

#######################################################################
# Get the number of CPU logical cores available for pre-commit to use
#
# CPU quota should be calculated as `cpu.cfs_quota_us / cpu.cfs_period_us`
# For K8s see: https://docs.kernel.org/scheduler/sched-bwc.html
# For Docker see: https://docs.docker.com/engine/containers/resource_constraints/#configure-the-default-cfs-scheduler
#
# Arguments:
# parallelism_ci_cpu_cores (string) Used in edge cases when number of
# CPU cores can't be derived automatically
Expand All @@ -197,14 +202,15 @@ function common::is_hook_run_on_whole_repo {
function common::get_cpu_num {
local -r parallelism_ci_cpu_cores=$1

local millicpu
local cpu_quota cpu_period cpu_num

if [[ -f /sys/fs/cgroup/cpu/cpu.cfs_quota_us &&
! -f /proc/sys/fs/binfmt_misc/WSLInterop ]]; then # WSL have cfs_quota_us, but WSL should be checked as usual Linux host
# Inside K8s pod or DinD in K8s
millicpu=$(< /sys/fs/cgroup/cpu/cpu.cfs_quota_us)
cpu_quota=$(< /sys/fs/cgroup/cpu/cpu.cfs_quota_us)
cpu_period=$(cat /sys/fs/cgroup/cpu/cpu.cfs_period_us 2> /dev/null || echo "$cpu_quota")

if [[ $millicpu -eq -1 ]]; then
if [[ $cpu_quota -eq -1 || $cpu_period -lt 1 ]]; then
# K8s no limits or in DinD
if [[ -n $parallelism_ci_cpu_cores ]]; then
if [[ ! $parallelism_ci_cpu_cores =~ ^[[:digit:]]+$ ]]; then
Expand Down Expand Up @@ -233,21 +239,24 @@ function common::get_cpu_num {
return
fi

echo $((millicpu / 1000))
cpu_num=$((cpu_quota / cpu_period))
[[ $cpu_num -lt 1 ]] && echo 1 || echo $cpu_num
return
fi

if [[ -f /sys/fs/cgroup/cpu.max ]]; then
# Inside Linux (Docker?) container
millicpu=$(cut -d' ' -f1 /sys/fs/cgroup/cpu.max)
cpu_quota=$(cut -d' ' -f1 /sys/fs/cgroup/cpu.max)
cpu_period=$(cut -d' ' -f2 /sys/fs/cgroup/cpu.max)

if [[ $millicpu == max ]]; then
if [[ $cpu_quota == max || $cpu_period -lt 1 ]]; then
# No limits
nproc 2> /dev/null || echo 1
return
fi

echo $((millicpu / 1000))
cpu_num=$((cpu_quota / cpu_period))
[[ $cpu_num -lt 1 ]] && echo 1 || echo $cpu_num
return
fi

Expand Down
Loading