By Bubi
This is the first article of the Java in Container series. You are welcome to follow the series. 😊
Recently, my colleague talked about Java's ParallelGCThreads parameter. I went through the JDK 8 code and found that the default value of ParallelGCThreads is:
However, the number of GC threads is found to be 38, even on a container with 4 cores allocated. Then, it occurred to me that it should be related to the resource limit of the container. The JVM may not be aware of the resource limit of the current container.
After looking through the code, I found that the latest version of Java is aware of the resource limit of the container, so I went through the code again according to the JDK version:
Write a sleep 1000s program to check the number of threads in the JVM:
./jdk1.8.0_144/bin/java -XX:+UseG1GC -XX:+ParallelRefProcEnabled Main
Then, look at the number of GC threads:
$ jstack $pid | grep 'Parallel GC Threads' | wc -l
38
The physical machine has 56 cores (8 + (56 - 8) * 5/8 = 38).
Then, use the +PrintFlagsFinal
to look at the following parameter:
$ ./jdk1.8.0_144/bin/java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | grep ParallelGCThreads
uintx ParallelGCThreads =38 {product}
It seems that jdk8u144
can't help read the container quota.
Then, I found Java can read the container quota from jdk 8u191:
Run the same program:
./jre1.8.0_191/bin/java -XX:+UseG1GC -XX:+ParallelRefProcEnabled Main
$ jstack $pid | grep 'Parallel GC Threads' | wc -l
4
View the actual parameter:
$ ./jre1.8.0_191/bin/java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | grep ParallelGCThreads
uintx ParallelGCThreads =4 {product}
In addition, JDK 8u191 introduces the PrintContainerInfo parameter:
$ ./jre1.8.0_191/bin/java -XX:+UnlockDiagnosticVMOptions -XX:+PrintContainerInfo -version
OSContainer::init: Initializing Container Support
Path to /memory.limit_in_bytes is /sys/fs/cgroup/memory/memory.limit_in_bytes
Memory Limit is: 10737418240
Path to /cpu.cfs_quota_us is /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
CPU Quota is: 400000
Path to /cpu.cfs_period_us is /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us
CPU Period is: 100000
Path to /cpu.shares is /sys/fs/cgroup/cpu,cpuacct/cpu.shares
CPU Shares is: 681
CPU Quota count based on quota/period: 4
CPU Share count based on shares: 1
OSContainer::active_processor_count: 4
Path to /cpu.cfs_quota_us is /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
CPU Quota is: 400000
Path to /cpu.cfs_period_us is /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us
CPU Period is: 100000
Path to /cpu.shares is /sys/fs/cgroup/cpu,cpuacct/cpu.shares
CPU Shares is: 681
CPU Quota count based on quota/period: 4
CPU Share count based on shares: 1
OSContainer::active_processor_count: 4
……
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
As you can see, the obtained memory limit and the number of available CPUs are correct.
Combining this log and code, we can see how to obtain the container quota:
First, read the location where the corresponding resources are mounted. For example, the CPU is in /sys/fs/cgroup/cpu,cpuacct
:
$ cat /proc/mounts | grep -E -w '(cpu|memory)'
cgroup /sys/fs/cgroup/memory cgroup ro,nosuid,nodev,noexec,relatime,memory 0 0
cgroup /sys/fs/cgroup/cpu,cpuacct cgroup ro,nosuid,nodev,noexec,relatime,cpu,cpuacct 0 0
For memory:
$ cat /sys/fs/cgroup/memory/memory.limit_in_bytes
10737418240
For CPU resources:
First, you can use the quota/period:
$ cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us # the total time slice quota per CPU, in microseconds
100000
$ cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us # the CPU time that the container can occupy in the time slice
400000
For example, the example above indicates that 4 cores are allocated.
You can also use cpu.shares:
$ cat /sys/fs/cgroup/cpu,cpuacct/cpu.shares
681
However, this value is the CPU share, so there is no exact number of available CPUs based on this value, which means it is basically useless.
Use the jdk 8u191
or newer version.
Koordinator v1.1: Load-Aware Scheduling and Interference Detection Collection
Interpreting KubeVela 1.7: Taking Over Your Existing Workloads
508 posts | 49 followers
FollowAlibaba Cloud Native Community - May 8, 2023
Alibaba Cloud Native Community - May 22, 2023
Alibaba Clouder - November 22, 2019
Alibaba Cloud Blockchain Service Team - October 25, 2018
Alibaba Cloud Native Community - May 18, 2023
Alibaba Cloud Native Community - February 24, 2023
508 posts | 49 followers
FollowProvides a control plane to allow users to manage Kubernetes clusters that run based on different infrastructure resources
Learn MoreAlibaba Cloud Container Service for Kubernetes is a fully managed cloud container management service that supports native Kubernetes and integrates with other Alibaba Cloud products.
Learn MoreA secure image hosting platform providing containerized image lifecycle management
Learn MoreAccelerate and secure the development, deployment, and management of containerized applications cost-effectively.
Learn MoreMore Posts by Alibaba Cloud Native Community