From 25c42e92268ea8239cbd34cf3802de8ce7289fd5 Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov <thresh@videolan.org> Date: Wed, 25 Nov 2020 21:41:08 +0300 Subject: [PATCH] Introduced an entrypoint script to autotune the number of worker processes The script is a no-op bye default, you would need to enable its logic by setting an NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE variable to any value. The script then tries to get the following values: - getconf _NPROCESSORS_ONLN - the amount of cpus from cpuset cgroup - the quotas from cpu/cpuacct cgroup The lowest of all three is then applied to nginx.conf. --- Dockerfile-alpine.template | 1 + Dockerfile-debian.template | 1 + entrypoint/30-tune-worker-processes.sh | 127 ++++++++++++++++++ .../alpine-perl/30-tune-worker-processes.sh | 127 ++++++++++++++++++ mainline/alpine-perl/Dockerfile | 1 + mainline/alpine/30-tune-worker-processes.sh | 127 ++++++++++++++++++ mainline/alpine/Dockerfile | 1 + .../debian-perl/30-tune-worker-processes.sh | 127 ++++++++++++++++++ mainline/debian-perl/Dockerfile | 1 + mainline/debian/30-tune-worker-processes.sh | 127 ++++++++++++++++++ mainline/debian/Dockerfile | 1 + .../alpine-perl/30-tune-worker-processes.sh | 127 ++++++++++++++++++ stable/alpine-perl/Dockerfile | 1 + stable/alpine/30-tune-worker-processes.sh | 127 ++++++++++++++++++ stable/alpine/Dockerfile | 1 + .../debian-perl/30-tune-worker-processes.sh | 127 ++++++++++++++++++ stable/debian-perl/Dockerfile | 1 + stable/debian/30-tune-worker-processes.sh | 127 ++++++++++++++++++ stable/debian/Dockerfile | 1 + 19 files changed, 1153 insertions(+) create mode 100755 entrypoint/30-tune-worker-processes.sh create mode 100755 mainline/alpine-perl/30-tune-worker-processes.sh create mode 100755 mainline/alpine/30-tune-worker-processes.sh create mode 100755 mainline/debian-perl/30-tune-worker-processes.sh create mode 100755 mainline/debian/30-tune-worker-processes.sh create mode 100755 stable/alpine-perl/30-tune-worker-processes.sh create mode 100755 stable/alpine/30-tune-worker-processes.sh create mode 100755 stable/debian-perl/30-tune-worker-processes.sh create mode 100755 stable/debian/30-tune-worker-processes.sh diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template index eb623c2..1ce4411 100644 --- a/Dockerfile-alpine.template +++ b/Dockerfile-alpine.template @@ -105,6 +105,7 @@ RUN set -x \ COPY docker-entrypoint.sh / COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d COPY 20-envsubst-on-templates.sh /docker-entrypoint.d +COPY 30-tune-worker-processes.sh /docker-entrypoint.d ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 80 diff --git a/Dockerfile-debian.template b/Dockerfile-debian.template index 8521d5a..91b7cf7 100644 --- a/Dockerfile-debian.template +++ b/Dockerfile-debian.template @@ -96,6 +96,7 @@ RUN set -x \ COPY docker-entrypoint.sh / COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d COPY 20-envsubst-on-templates.sh /docker-entrypoint.d +COPY 30-tune-worker-processes.sh /docker-entrypoint.d ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 80 diff --git a/entrypoint/30-tune-worker-processes.sh b/entrypoint/30-tune-worker-processes.sh new file mode 100755 index 0000000..f2199ca --- /dev/null +++ b/entrypoint/30-tune-worker-processes.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# vim:sw=2:ts=2:sts=2:et + +set -eu + +LC_ALL=C +ME=$( basename "$0" ) +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 + +touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } + +ceildiv() { + num=$1 + div=$2 + echo $(( (num + div - 1) / div )) +} + +get_cpuset() { + cpusetroot=$1 + ncpu=0 + [ -f "$cpusetroot/cpuset.effective_cpus" ] || return + for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do + case "$token" in + *-*) + count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) + ncpu=$(( ncpu+count )) + ;; + *) + ncpu=$(( ncpu+1 )) + ;; + esac + done + echo "$ncpu" +} + +get_quota() { + cpuroot=$1 + ncpu=0 + [ -f "$cpuroot/cpu.cfs_quota_us" ] || return + [ -f "$cpuroot/cpu.cfs_period_us" ] || return + cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) + cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) + [ "$cfs_quota" = "-1" ] && return + [ "$cfs_period" = "0" ] && return + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) + [ "$ncpu" -gt 0 ] || return + echo "$ncpu" +} + +get_cgroup_path() { + needle=$1 + foundroot= + mountpoint= + + [ -r "/proc/self/mountinfo" ] || return + [ -r "/proc/self/cgroup" ] || return + + while IFS= read -r line; do + case "$needle" in + "cpuset") + case "$line" in + *cpuset*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + ;; + "cpu") + case "$line" in + *cpuset*) + ;; + *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + esac + done << __EOF__ +$( grep -F -- '- cgroup ' /proc/self/mountinfo ) +__EOF__ + + while IFS= read -r line; do + controller=$( echo "$line" | cut -d: -f 2 ) + case "$needle" in + "cpuset") + case "$controller" in + cpuset) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + "cpu") + case "$controller" in + cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + esac +done << __EOF__ +$( grep -F -- 'cpu' /proc/self/cgroup ) +__EOF__ + + case "${found%% *}" in + "/") + foundroot="${found##* }$mountpoint" + ;; + "$mountpoint") + foundroot="${found##* }" + ;; + esac + echo "$foundroot" +} + +ncpu_online=$( getconf _NPROCESSORS_ONLN ) + +cpuset=$( get_cgroup_path "cpuset" ) +[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" ) +[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online + +cpu=$( get_cgroup_path "cpu" ) +[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" ) +[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online + +ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 ) + +sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf diff --git a/mainline/alpine-perl/30-tune-worker-processes.sh b/mainline/alpine-perl/30-tune-worker-processes.sh new file mode 100755 index 0000000..f2199ca --- /dev/null +++ b/mainline/alpine-perl/30-tune-worker-processes.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# vim:sw=2:ts=2:sts=2:et + +set -eu + +LC_ALL=C +ME=$( basename "$0" ) +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 + +touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } + +ceildiv() { + num=$1 + div=$2 + echo $(( (num + div - 1) / div )) +} + +get_cpuset() { + cpusetroot=$1 + ncpu=0 + [ -f "$cpusetroot/cpuset.effective_cpus" ] || return + for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do + case "$token" in + *-*) + count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) + ncpu=$(( ncpu+count )) + ;; + *) + ncpu=$(( ncpu+1 )) + ;; + esac + done + echo "$ncpu" +} + +get_quota() { + cpuroot=$1 + ncpu=0 + [ -f "$cpuroot/cpu.cfs_quota_us" ] || return + [ -f "$cpuroot/cpu.cfs_period_us" ] || return + cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) + cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) + [ "$cfs_quota" = "-1" ] && return + [ "$cfs_period" = "0" ] && return + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) + [ "$ncpu" -gt 0 ] || return + echo "$ncpu" +} + +get_cgroup_path() { + needle=$1 + foundroot= + mountpoint= + + [ -r "/proc/self/mountinfo" ] || return + [ -r "/proc/self/cgroup" ] || return + + while IFS= read -r line; do + case "$needle" in + "cpuset") + case "$line" in + *cpuset*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + ;; + "cpu") + case "$line" in + *cpuset*) + ;; + *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + esac + done << __EOF__ +$( grep -F -- '- cgroup ' /proc/self/mountinfo ) +__EOF__ + + while IFS= read -r line; do + controller=$( echo "$line" | cut -d: -f 2 ) + case "$needle" in + "cpuset") + case "$controller" in + cpuset) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + "cpu") + case "$controller" in + cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + esac +done << __EOF__ +$( grep -F -- 'cpu' /proc/self/cgroup ) +__EOF__ + + case "${found%% *}" in + "/") + foundroot="${found##* }$mountpoint" + ;; + "$mountpoint") + foundroot="${found##* }" + ;; + esac + echo "$foundroot" +} + +ncpu_online=$( getconf _NPROCESSORS_ONLN ) + +cpuset=$( get_cgroup_path "cpuset" ) +[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" ) +[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online + +cpu=$( get_cgroup_path "cpu" ) +[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" ) +[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online + +ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 ) + +sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf diff --git a/mainline/alpine-perl/Dockerfile b/mainline/alpine-perl/Dockerfile index 513d7c6..1c0f606 100644 --- a/mainline/alpine-perl/Dockerfile +++ b/mainline/alpine-perl/Dockerfile @@ -116,6 +116,7 @@ RUN set -x \ COPY docker-entrypoint.sh / COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d COPY 20-envsubst-on-templates.sh /docker-entrypoint.d +COPY 30-tune-worker-processes.sh /docker-entrypoint.d ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 80 diff --git a/mainline/alpine/30-tune-worker-processes.sh b/mainline/alpine/30-tune-worker-processes.sh new file mode 100755 index 0000000..f2199ca --- /dev/null +++ b/mainline/alpine/30-tune-worker-processes.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# vim:sw=2:ts=2:sts=2:et + +set -eu + +LC_ALL=C +ME=$( basename "$0" ) +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 + +touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } + +ceildiv() { + num=$1 + div=$2 + echo $(( (num + div - 1) / div )) +} + +get_cpuset() { + cpusetroot=$1 + ncpu=0 + [ -f "$cpusetroot/cpuset.effective_cpus" ] || return + for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do + case "$token" in + *-*) + count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) + ncpu=$(( ncpu+count )) + ;; + *) + ncpu=$(( ncpu+1 )) + ;; + esac + done + echo "$ncpu" +} + +get_quota() { + cpuroot=$1 + ncpu=0 + [ -f "$cpuroot/cpu.cfs_quota_us" ] || return + [ -f "$cpuroot/cpu.cfs_period_us" ] || return + cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) + cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) + [ "$cfs_quota" = "-1" ] && return + [ "$cfs_period" = "0" ] && return + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) + [ "$ncpu" -gt 0 ] || return + echo "$ncpu" +} + +get_cgroup_path() { + needle=$1 + foundroot= + mountpoint= + + [ -r "/proc/self/mountinfo" ] || return + [ -r "/proc/self/cgroup" ] || return + + while IFS= read -r line; do + case "$needle" in + "cpuset") + case "$line" in + *cpuset*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + ;; + "cpu") + case "$line" in + *cpuset*) + ;; + *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + esac + done << __EOF__ +$( grep -F -- '- cgroup ' /proc/self/mountinfo ) +__EOF__ + + while IFS= read -r line; do + controller=$( echo "$line" | cut -d: -f 2 ) + case "$needle" in + "cpuset") + case "$controller" in + cpuset) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + "cpu") + case "$controller" in + cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + esac +done << __EOF__ +$( grep -F -- 'cpu' /proc/self/cgroup ) +__EOF__ + + case "${found%% *}" in + "/") + foundroot="${found##* }$mountpoint" + ;; + "$mountpoint") + foundroot="${found##* }" + ;; + esac + echo "$foundroot" +} + +ncpu_online=$( getconf _NPROCESSORS_ONLN ) + +cpuset=$( get_cgroup_path "cpuset" ) +[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" ) +[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online + +cpu=$( get_cgroup_path "cpu" ) +[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" ) +[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online + +ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 ) + +sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf diff --git a/mainline/alpine/Dockerfile b/mainline/alpine/Dockerfile index 5fc76ef..c6eb9a5 100644 --- a/mainline/alpine/Dockerfile +++ b/mainline/alpine/Dockerfile @@ -115,6 +115,7 @@ RUN set -x \ COPY docker-entrypoint.sh / COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d COPY 20-envsubst-on-templates.sh /docker-entrypoint.d +COPY 30-tune-worker-processes.sh /docker-entrypoint.d ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 80 diff --git a/mainline/debian-perl/30-tune-worker-processes.sh b/mainline/debian-perl/30-tune-worker-processes.sh new file mode 100755 index 0000000..f2199ca --- /dev/null +++ b/mainline/debian-perl/30-tune-worker-processes.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# vim:sw=2:ts=2:sts=2:et + +set -eu + +LC_ALL=C +ME=$( basename "$0" ) +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 + +touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } + +ceildiv() { + num=$1 + div=$2 + echo $(( (num + div - 1) / div )) +} + +get_cpuset() { + cpusetroot=$1 + ncpu=0 + [ -f "$cpusetroot/cpuset.effective_cpus" ] || return + for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do + case "$token" in + *-*) + count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) + ncpu=$(( ncpu+count )) + ;; + *) + ncpu=$(( ncpu+1 )) + ;; + esac + done + echo "$ncpu" +} + +get_quota() { + cpuroot=$1 + ncpu=0 + [ -f "$cpuroot/cpu.cfs_quota_us" ] || return + [ -f "$cpuroot/cpu.cfs_period_us" ] || return + cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) + cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) + [ "$cfs_quota" = "-1" ] && return + [ "$cfs_period" = "0" ] && return + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) + [ "$ncpu" -gt 0 ] || return + echo "$ncpu" +} + +get_cgroup_path() { + needle=$1 + foundroot= + mountpoint= + + [ -r "/proc/self/mountinfo" ] || return + [ -r "/proc/self/cgroup" ] || return + + while IFS= read -r line; do + case "$needle" in + "cpuset") + case "$line" in + *cpuset*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + ;; + "cpu") + case "$line" in + *cpuset*) + ;; + *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + esac + done << __EOF__ +$( grep -F -- '- cgroup ' /proc/self/mountinfo ) +__EOF__ + + while IFS= read -r line; do + controller=$( echo "$line" | cut -d: -f 2 ) + case "$needle" in + "cpuset") + case "$controller" in + cpuset) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + "cpu") + case "$controller" in + cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + esac +done << __EOF__ +$( grep -F -- 'cpu' /proc/self/cgroup ) +__EOF__ + + case "${found%% *}" in + "/") + foundroot="${found##* }$mountpoint" + ;; + "$mountpoint") + foundroot="${found##* }" + ;; + esac + echo "$foundroot" +} + +ncpu_online=$( getconf _NPROCESSORS_ONLN ) + +cpuset=$( get_cgroup_path "cpuset" ) +[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" ) +[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online + +cpu=$( get_cgroup_path "cpu" ) +[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" ) +[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online + +ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 ) + +sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf diff --git a/mainline/debian-perl/Dockerfile b/mainline/debian-perl/Dockerfile index 2080b84..3299932 100644 --- a/mainline/debian-perl/Dockerfile +++ b/mainline/debian-perl/Dockerfile @@ -107,6 +107,7 @@ RUN set -x \ COPY docker-entrypoint.sh / COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d COPY 20-envsubst-on-templates.sh /docker-entrypoint.d +COPY 30-tune-worker-processes.sh /docker-entrypoint.d ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 80 diff --git a/mainline/debian/30-tune-worker-processes.sh b/mainline/debian/30-tune-worker-processes.sh new file mode 100755 index 0000000..f2199ca --- /dev/null +++ b/mainline/debian/30-tune-worker-processes.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# vim:sw=2:ts=2:sts=2:et + +set -eu + +LC_ALL=C +ME=$( basename "$0" ) +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 + +touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } + +ceildiv() { + num=$1 + div=$2 + echo $(( (num + div - 1) / div )) +} + +get_cpuset() { + cpusetroot=$1 + ncpu=0 + [ -f "$cpusetroot/cpuset.effective_cpus" ] || return + for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do + case "$token" in + *-*) + count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) + ncpu=$(( ncpu+count )) + ;; + *) + ncpu=$(( ncpu+1 )) + ;; + esac + done + echo "$ncpu" +} + +get_quota() { + cpuroot=$1 + ncpu=0 + [ -f "$cpuroot/cpu.cfs_quota_us" ] || return + [ -f "$cpuroot/cpu.cfs_period_us" ] || return + cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) + cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) + [ "$cfs_quota" = "-1" ] && return + [ "$cfs_period" = "0" ] && return + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) + [ "$ncpu" -gt 0 ] || return + echo "$ncpu" +} + +get_cgroup_path() { + needle=$1 + foundroot= + mountpoint= + + [ -r "/proc/self/mountinfo" ] || return + [ -r "/proc/self/cgroup" ] || return + + while IFS= read -r line; do + case "$needle" in + "cpuset") + case "$line" in + *cpuset*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + ;; + "cpu") + case "$line" in + *cpuset*) + ;; + *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + esac + done << __EOF__ +$( grep -F -- '- cgroup ' /proc/self/mountinfo ) +__EOF__ + + while IFS= read -r line; do + controller=$( echo "$line" | cut -d: -f 2 ) + case "$needle" in + "cpuset") + case "$controller" in + cpuset) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + "cpu") + case "$controller" in + cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + esac +done << __EOF__ +$( grep -F -- 'cpu' /proc/self/cgroup ) +__EOF__ + + case "${found%% *}" in + "/") + foundroot="${found##* }$mountpoint" + ;; + "$mountpoint") + foundroot="${found##* }" + ;; + esac + echo "$foundroot" +} + +ncpu_online=$( getconf _NPROCESSORS_ONLN ) + +cpuset=$( get_cgroup_path "cpuset" ) +[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" ) +[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online + +cpu=$( get_cgroup_path "cpu" ) +[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" ) +[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online + +ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 ) + +sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf diff --git a/mainline/debian/Dockerfile b/mainline/debian/Dockerfile index fd707c5..60bd285 100644 --- a/mainline/debian/Dockerfile +++ b/mainline/debian/Dockerfile @@ -106,6 +106,7 @@ RUN set -x \ COPY docker-entrypoint.sh / COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d COPY 20-envsubst-on-templates.sh /docker-entrypoint.d +COPY 30-tune-worker-processes.sh /docker-entrypoint.d ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 80 diff --git a/stable/alpine-perl/30-tune-worker-processes.sh b/stable/alpine-perl/30-tune-worker-processes.sh new file mode 100755 index 0000000..f2199ca --- /dev/null +++ b/stable/alpine-perl/30-tune-worker-processes.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# vim:sw=2:ts=2:sts=2:et + +set -eu + +LC_ALL=C +ME=$( basename "$0" ) +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 + +touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } + +ceildiv() { + num=$1 + div=$2 + echo $(( (num + div - 1) / div )) +} + +get_cpuset() { + cpusetroot=$1 + ncpu=0 + [ -f "$cpusetroot/cpuset.effective_cpus" ] || return + for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do + case "$token" in + *-*) + count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) + ncpu=$(( ncpu+count )) + ;; + *) + ncpu=$(( ncpu+1 )) + ;; + esac + done + echo "$ncpu" +} + +get_quota() { + cpuroot=$1 + ncpu=0 + [ -f "$cpuroot/cpu.cfs_quota_us" ] || return + [ -f "$cpuroot/cpu.cfs_period_us" ] || return + cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) + cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) + [ "$cfs_quota" = "-1" ] && return + [ "$cfs_period" = "0" ] && return + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) + [ "$ncpu" -gt 0 ] || return + echo "$ncpu" +} + +get_cgroup_path() { + needle=$1 + foundroot= + mountpoint= + + [ -r "/proc/self/mountinfo" ] || return + [ -r "/proc/self/cgroup" ] || return + + while IFS= read -r line; do + case "$needle" in + "cpuset") + case "$line" in + *cpuset*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + ;; + "cpu") + case "$line" in + *cpuset*) + ;; + *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + esac + done << __EOF__ +$( grep -F -- '- cgroup ' /proc/self/mountinfo ) +__EOF__ + + while IFS= read -r line; do + controller=$( echo "$line" | cut -d: -f 2 ) + case "$needle" in + "cpuset") + case "$controller" in + cpuset) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + "cpu") + case "$controller" in + cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + esac +done << __EOF__ +$( grep -F -- 'cpu' /proc/self/cgroup ) +__EOF__ + + case "${found%% *}" in + "/") + foundroot="${found##* }$mountpoint" + ;; + "$mountpoint") + foundroot="${found##* }" + ;; + esac + echo "$foundroot" +} + +ncpu_online=$( getconf _NPROCESSORS_ONLN ) + +cpuset=$( get_cgroup_path "cpuset" ) +[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" ) +[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online + +cpu=$( get_cgroup_path "cpu" ) +[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" ) +[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online + +ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 ) + +sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf diff --git a/stable/alpine-perl/Dockerfile b/stable/alpine-perl/Dockerfile index d86c2cc..6df7dde 100644 --- a/stable/alpine-perl/Dockerfile +++ b/stable/alpine-perl/Dockerfile @@ -116,6 +116,7 @@ RUN set -x \ COPY docker-entrypoint.sh / COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d COPY 20-envsubst-on-templates.sh /docker-entrypoint.d +COPY 30-tune-worker-processes.sh /docker-entrypoint.d ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 80 diff --git a/stable/alpine/30-tune-worker-processes.sh b/stable/alpine/30-tune-worker-processes.sh new file mode 100755 index 0000000..f2199ca --- /dev/null +++ b/stable/alpine/30-tune-worker-processes.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# vim:sw=2:ts=2:sts=2:et + +set -eu + +LC_ALL=C +ME=$( basename "$0" ) +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 + +touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } + +ceildiv() { + num=$1 + div=$2 + echo $(( (num + div - 1) / div )) +} + +get_cpuset() { + cpusetroot=$1 + ncpu=0 + [ -f "$cpusetroot/cpuset.effective_cpus" ] || return + for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do + case "$token" in + *-*) + count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) + ncpu=$(( ncpu+count )) + ;; + *) + ncpu=$(( ncpu+1 )) + ;; + esac + done + echo "$ncpu" +} + +get_quota() { + cpuroot=$1 + ncpu=0 + [ -f "$cpuroot/cpu.cfs_quota_us" ] || return + [ -f "$cpuroot/cpu.cfs_period_us" ] || return + cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) + cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) + [ "$cfs_quota" = "-1" ] && return + [ "$cfs_period" = "0" ] && return + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) + [ "$ncpu" -gt 0 ] || return + echo "$ncpu" +} + +get_cgroup_path() { + needle=$1 + foundroot= + mountpoint= + + [ -r "/proc/self/mountinfo" ] || return + [ -r "/proc/self/cgroup" ] || return + + while IFS= read -r line; do + case "$needle" in + "cpuset") + case "$line" in + *cpuset*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + ;; + "cpu") + case "$line" in + *cpuset*) + ;; + *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + esac + done << __EOF__ +$( grep -F -- '- cgroup ' /proc/self/mountinfo ) +__EOF__ + + while IFS= read -r line; do + controller=$( echo "$line" | cut -d: -f 2 ) + case "$needle" in + "cpuset") + case "$controller" in + cpuset) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + "cpu") + case "$controller" in + cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + esac +done << __EOF__ +$( grep -F -- 'cpu' /proc/self/cgroup ) +__EOF__ + + case "${found%% *}" in + "/") + foundroot="${found##* }$mountpoint" + ;; + "$mountpoint") + foundroot="${found##* }" + ;; + esac + echo "$foundroot" +} + +ncpu_online=$( getconf _NPROCESSORS_ONLN ) + +cpuset=$( get_cgroup_path "cpuset" ) +[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" ) +[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online + +cpu=$( get_cgroup_path "cpu" ) +[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" ) +[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online + +ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 ) + +sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf diff --git a/stable/alpine/Dockerfile b/stable/alpine/Dockerfile index bd34cfb..397380a 100644 --- a/stable/alpine/Dockerfile +++ b/stable/alpine/Dockerfile @@ -115,6 +115,7 @@ RUN set -x \ COPY docker-entrypoint.sh / COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d COPY 20-envsubst-on-templates.sh /docker-entrypoint.d +COPY 30-tune-worker-processes.sh /docker-entrypoint.d ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 80 diff --git a/stable/debian-perl/30-tune-worker-processes.sh b/stable/debian-perl/30-tune-worker-processes.sh new file mode 100755 index 0000000..f2199ca --- /dev/null +++ b/stable/debian-perl/30-tune-worker-processes.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# vim:sw=2:ts=2:sts=2:et + +set -eu + +LC_ALL=C +ME=$( basename "$0" ) +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 + +touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } + +ceildiv() { + num=$1 + div=$2 + echo $(( (num + div - 1) / div )) +} + +get_cpuset() { + cpusetroot=$1 + ncpu=0 + [ -f "$cpusetroot/cpuset.effective_cpus" ] || return + for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do + case "$token" in + *-*) + count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) + ncpu=$(( ncpu+count )) + ;; + *) + ncpu=$(( ncpu+1 )) + ;; + esac + done + echo "$ncpu" +} + +get_quota() { + cpuroot=$1 + ncpu=0 + [ -f "$cpuroot/cpu.cfs_quota_us" ] || return + [ -f "$cpuroot/cpu.cfs_period_us" ] || return + cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) + cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) + [ "$cfs_quota" = "-1" ] && return + [ "$cfs_period" = "0" ] && return + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) + [ "$ncpu" -gt 0 ] || return + echo "$ncpu" +} + +get_cgroup_path() { + needle=$1 + foundroot= + mountpoint= + + [ -r "/proc/self/mountinfo" ] || return + [ -r "/proc/self/cgroup" ] || return + + while IFS= read -r line; do + case "$needle" in + "cpuset") + case "$line" in + *cpuset*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + ;; + "cpu") + case "$line" in + *cpuset*) + ;; + *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + esac + done << __EOF__ +$( grep -F -- '- cgroup ' /proc/self/mountinfo ) +__EOF__ + + while IFS= read -r line; do + controller=$( echo "$line" | cut -d: -f 2 ) + case "$needle" in + "cpuset") + case "$controller" in + cpuset) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + "cpu") + case "$controller" in + cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + esac +done << __EOF__ +$( grep -F -- 'cpu' /proc/self/cgroup ) +__EOF__ + + case "${found%% *}" in + "/") + foundroot="${found##* }$mountpoint" + ;; + "$mountpoint") + foundroot="${found##* }" + ;; + esac + echo "$foundroot" +} + +ncpu_online=$( getconf _NPROCESSORS_ONLN ) + +cpuset=$( get_cgroup_path "cpuset" ) +[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" ) +[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online + +cpu=$( get_cgroup_path "cpu" ) +[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" ) +[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online + +ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 ) + +sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf diff --git a/stable/debian-perl/Dockerfile b/stable/debian-perl/Dockerfile index 9998d13..90a797d 100644 --- a/stable/debian-perl/Dockerfile +++ b/stable/debian-perl/Dockerfile @@ -107,6 +107,7 @@ RUN set -x \ COPY docker-entrypoint.sh / COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d COPY 20-envsubst-on-templates.sh /docker-entrypoint.d +COPY 30-tune-worker-processes.sh /docker-entrypoint.d ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 80 diff --git a/stable/debian/30-tune-worker-processes.sh b/stable/debian/30-tune-worker-processes.sh new file mode 100755 index 0000000..f2199ca --- /dev/null +++ b/stable/debian/30-tune-worker-processes.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# vim:sw=2:ts=2:sts=2:et + +set -eu + +LC_ALL=C +ME=$( basename "$0" ) +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0 + +touch /etc/nginx/nginx.conf 2>/dev/null || { echo >&2 "$ME: error: can not modify /etc/nginx/nginx.conf (read-only file system?)"; exit 0; } + +ceildiv() { + num=$1 + div=$2 + echo $(( (num + div - 1) / div )) +} + +get_cpuset() { + cpusetroot=$1 + ncpu=0 + [ -f "$cpusetroot/cpuset.effective_cpus" ] || return + for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do + case "$token" in + *-*) + count=$( seq $(echo "$token" | tr '-' ' ') | wc -l ) + ncpu=$(( ncpu+count )) + ;; + *) + ncpu=$(( ncpu+1 )) + ;; + esac + done + echo "$ncpu" +} + +get_quota() { + cpuroot=$1 + ncpu=0 + [ -f "$cpuroot/cpu.cfs_quota_us" ] || return + [ -f "$cpuroot/cpu.cfs_period_us" ] || return + cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" ) + cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" ) + [ "$cfs_quota" = "-1" ] && return + [ "$cfs_period" = "0" ] && return + ncpu=$( ceildiv "$cfs_quota" "$cfs_period" ) + [ "$ncpu" -gt 0 ] || return + echo "$ncpu" +} + +get_cgroup_path() { + needle=$1 + foundroot= + mountpoint= + + [ -r "/proc/self/mountinfo" ] || return + [ -r "/proc/self/cgroup" ] || return + + while IFS= read -r line; do + case "$needle" in + "cpuset") + case "$line" in + *cpuset*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + ;; + "cpu") + case "$line" in + *cpuset*) + ;; + *cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*) + found=$( echo "$line" | cut -d ' ' -f 4,5 ) + ;; + esac + esac + done << __EOF__ +$( grep -F -- '- cgroup ' /proc/self/mountinfo ) +__EOF__ + + while IFS= read -r line; do + controller=$( echo "$line" | cut -d: -f 2 ) + case "$needle" in + "cpuset") + case "$controller" in + cpuset) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + "cpu") + case "$controller" in + cpu,cpuacct|cpuacct,cpu|cpuacct|cpu) + mountpoint=$( echo "$line" | cut -d: -f 3 ) + ;; + esac + ;; + esac +done << __EOF__ +$( grep -F -- 'cpu' /proc/self/cgroup ) +__EOF__ + + case "${found%% *}" in + "/") + foundroot="${found##* }$mountpoint" + ;; + "$mountpoint") + foundroot="${found##* }" + ;; + esac + echo "$foundroot" +} + +ncpu_online=$( getconf _NPROCESSORS_ONLN ) + +cpuset=$( get_cgroup_path "cpuset" ) +[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" ) +[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online + +cpu=$( get_cgroup_path "cpu" ) +[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" ) +[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online + +ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 ) + +sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf diff --git a/stable/debian/Dockerfile b/stable/debian/Dockerfile index a4b6b7f..a4d932b 100644 --- a/stable/debian/Dockerfile +++ b/stable/debian/Dockerfile @@ -106,6 +106,7 @@ RUN set -x \ COPY docker-entrypoint.sh / COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d COPY 20-envsubst-on-templates.sh /docker-entrypoint.d +COPY 30-tune-worker-processes.sh /docker-entrypoint.d ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 80 -- GitLab