Skip to content

Commit 25c42e9

Browse files
committed
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.
1 parent c411fde commit 25c42e9

19 files changed

+1153
-0
lines changed

Dockerfile-alpine.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ RUN set -x \
105105
COPY docker-entrypoint.sh /
106106
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
107107
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
108+
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
108109
ENTRYPOINT ["/docker-entrypoint.sh"]
109110

110111
EXPOSE 80

Dockerfile-debian.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ RUN set -x \
9696
COPY docker-entrypoint.sh /
9797
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
9898
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
99+
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
99100
ENTRYPOINT ["/docker-entrypoint.sh"]
100101

101102
EXPOSE 80
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/bin/sh
2+
# vim:sw=2:ts=2:sts=2:et
3+
4+
set -eu
5+
6+
LC_ALL=C
7+
ME=$( basename "$0" )
8+
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
9+
10+
[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0
11+
12+
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; }
13+
14+
ceildiv() {
15+
num=$1
16+
div=$2
17+
echo $(( (num + div - 1) / div ))
18+
}
19+
20+
get_cpuset() {
21+
cpusetroot=$1
22+
ncpu=0
23+
[ -f "$cpusetroot/cpuset.effective_cpus" ] || return
24+
for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do
25+
case "$token" in
26+
*-*)
27+
count=$( seq $(echo "$token" | tr '-' ' ') | wc -l )
28+
ncpu=$(( ncpu+count ))
29+
;;
30+
*)
31+
ncpu=$(( ncpu+1 ))
32+
;;
33+
esac
34+
done
35+
echo "$ncpu"
36+
}
37+
38+
get_quota() {
39+
cpuroot=$1
40+
ncpu=0
41+
[ -f "$cpuroot/cpu.cfs_quota_us" ] || return
42+
[ -f "$cpuroot/cpu.cfs_period_us" ] || return
43+
cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" )
44+
cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" )
45+
[ "$cfs_quota" = "-1" ] && return
46+
[ "$cfs_period" = "0" ] && return
47+
ncpu=$( ceildiv "$cfs_quota" "$cfs_period" )
48+
[ "$ncpu" -gt 0 ] || return
49+
echo "$ncpu"
50+
}
51+
52+
get_cgroup_path() {
53+
needle=$1
54+
foundroot=
55+
mountpoint=
56+
57+
[ -r "/proc/self/mountinfo" ] || return
58+
[ -r "/proc/self/cgroup" ] || return
59+
60+
while IFS= read -r line; do
61+
case "$needle" in
62+
"cpuset")
63+
case "$line" in
64+
*cpuset*)
65+
found=$( echo "$line" | cut -d ' ' -f 4,5 )
66+
;;
67+
esac
68+
;;
69+
"cpu")
70+
case "$line" in
71+
*cpuset*)
72+
;;
73+
*cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*)
74+
found=$( echo "$line" | cut -d ' ' -f 4,5 )
75+
;;
76+
esac
77+
esac
78+
done << __EOF__
79+
$( grep -F -- '- cgroup ' /proc/self/mountinfo )
80+
__EOF__
81+
82+
while IFS= read -r line; do
83+
controller=$( echo "$line" | cut -d: -f 2 )
84+
case "$needle" in
85+
"cpuset")
86+
case "$controller" in
87+
cpuset)
88+
mountpoint=$( echo "$line" | cut -d: -f 3 )
89+
;;
90+
esac
91+
;;
92+
"cpu")
93+
case "$controller" in
94+
cpu,cpuacct|cpuacct,cpu|cpuacct|cpu)
95+
mountpoint=$( echo "$line" | cut -d: -f 3 )
96+
;;
97+
esac
98+
;;
99+
esac
100+
done << __EOF__
101+
$( grep -F -- 'cpu' /proc/self/cgroup )
102+
__EOF__
103+
104+
case "${found%% *}" in
105+
"/")
106+
foundroot="${found##* }$mountpoint"
107+
;;
108+
"$mountpoint")
109+
foundroot="${found##* }"
110+
;;
111+
esac
112+
echo "$foundroot"
113+
}
114+
115+
ncpu_online=$( getconf _NPROCESSORS_ONLN )
116+
117+
cpuset=$( get_cgroup_path "cpuset" )
118+
[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" )
119+
[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online
120+
121+
cpu=$( get_cgroup_path "cpu" )
122+
[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" )
123+
[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online
124+
125+
ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 )
126+
127+
sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#!/bin/sh
2+
# vim:sw=2:ts=2:sts=2:et
3+
4+
set -eu
5+
6+
LC_ALL=C
7+
ME=$( basename "$0" )
8+
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
9+
10+
[ "${NGINX_ENTRYPOINT_WORKER_PROCESSES_AUTOTUNE:-}" ] || exit 0
11+
12+
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; }
13+
14+
ceildiv() {
15+
num=$1
16+
div=$2
17+
echo $(( (num + div - 1) / div ))
18+
}
19+
20+
get_cpuset() {
21+
cpusetroot=$1
22+
ncpu=0
23+
[ -f "$cpusetroot/cpuset.effective_cpus" ] || return
24+
for token in $( tr ',' ' ' < "$cpusetroot/cpuset.effective_cpus" ); do
25+
case "$token" in
26+
*-*)
27+
count=$( seq $(echo "$token" | tr '-' ' ') | wc -l )
28+
ncpu=$(( ncpu+count ))
29+
;;
30+
*)
31+
ncpu=$(( ncpu+1 ))
32+
;;
33+
esac
34+
done
35+
echo "$ncpu"
36+
}
37+
38+
get_quota() {
39+
cpuroot=$1
40+
ncpu=0
41+
[ -f "$cpuroot/cpu.cfs_quota_us" ] || return
42+
[ -f "$cpuroot/cpu.cfs_period_us" ] || return
43+
cfs_quota=$( cat "$cpuroot/cpu.cfs_quota_us" )
44+
cfs_period=$( cat "$cpuroot/cpu.cfs_period_us" )
45+
[ "$cfs_quota" = "-1" ] && return
46+
[ "$cfs_period" = "0" ] && return
47+
ncpu=$( ceildiv "$cfs_quota" "$cfs_period" )
48+
[ "$ncpu" -gt 0 ] || return
49+
echo "$ncpu"
50+
}
51+
52+
get_cgroup_path() {
53+
needle=$1
54+
foundroot=
55+
mountpoint=
56+
57+
[ -r "/proc/self/mountinfo" ] || return
58+
[ -r "/proc/self/cgroup" ] || return
59+
60+
while IFS= read -r line; do
61+
case "$needle" in
62+
"cpuset")
63+
case "$line" in
64+
*cpuset*)
65+
found=$( echo "$line" | cut -d ' ' -f 4,5 )
66+
;;
67+
esac
68+
;;
69+
"cpu")
70+
case "$line" in
71+
*cpuset*)
72+
;;
73+
*cpu,cpuacct*|*cpuacct,cpu|*cpuacct*|*cpu*)
74+
found=$( echo "$line" | cut -d ' ' -f 4,5 )
75+
;;
76+
esac
77+
esac
78+
done << __EOF__
79+
$( grep -F -- '- cgroup ' /proc/self/mountinfo )
80+
__EOF__
81+
82+
while IFS= read -r line; do
83+
controller=$( echo "$line" | cut -d: -f 2 )
84+
case "$needle" in
85+
"cpuset")
86+
case "$controller" in
87+
cpuset)
88+
mountpoint=$( echo "$line" | cut -d: -f 3 )
89+
;;
90+
esac
91+
;;
92+
"cpu")
93+
case "$controller" in
94+
cpu,cpuacct|cpuacct,cpu|cpuacct|cpu)
95+
mountpoint=$( echo "$line" | cut -d: -f 3 )
96+
;;
97+
esac
98+
;;
99+
esac
100+
done << __EOF__
101+
$( grep -F -- 'cpu' /proc/self/cgroup )
102+
__EOF__
103+
104+
case "${found%% *}" in
105+
"/")
106+
foundroot="${found##* }$mountpoint"
107+
;;
108+
"$mountpoint")
109+
foundroot="${found##* }"
110+
;;
111+
esac
112+
echo "$foundroot"
113+
}
114+
115+
ncpu_online=$( getconf _NPROCESSORS_ONLN )
116+
117+
cpuset=$( get_cgroup_path "cpuset" )
118+
[ "$cpuset" ] && ncpu_cpuset=$( get_cpuset "$cpuset" )
119+
[ "$ncpu_cpuset" ] || ncpu_cpuset=$ncpu_online
120+
121+
cpu=$( get_cgroup_path "cpu" )
122+
[ "$cpu" ] && ncpu_quota=$( get_quota "$cpu" )
123+
[ "$ncpu_quota" ] || ncpu_quota=$ncpu_online
124+
125+
ncpu=$( printf "%s\n%s\n%s\n" "$ncpu_online" "$ncpu_quota" "$ncpu_cpuset" | sort -n | head -n 1 )
126+
127+
sed -i.bak -r 's/^(worker_processes)(.*)$/# Commented out by '"$ME"' on '"$(date)"'\n#\1\2\n\1 '"$ncpu"';/' /etc/nginx/nginx.conf

mainline/alpine-perl/Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ RUN set -x \
116116
COPY docker-entrypoint.sh /
117117
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
118118
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
119+
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
119120
ENTRYPOINT ["/docker-entrypoint.sh"]
120121

121122
EXPOSE 80

0 commit comments

Comments
 (0)