Skip to content

Instantly share code, notes, and snippets.

@jason-riddle
Last active November 19, 2020 14:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jason-riddle/21d2016227c98e227c0ee8609bca4334 to your computer and use it in GitHub Desktop.
Save jason-riddle/21d2016227c98e227c0ee8609bca4334 to your computer and use it in GitHub Desktop.
Guide using Jshell to query CPU and memory information within a docker container #jvm #guide #complete
#!/usr/bin/env bash
# Ref: https://jaxenter.com/better-containerized-jvms-jdk-10-140593.html
set -eu
OPENJDK_IMAGE='openjdk:10-ea-jdk-slim'
JSHELL_CMD=(/bin/sh -c 'jshell -q')
GREP_CMD="-e HeapSize -e '\<ThreadStackSize\>' -e '\<ConcGCThreads\>' -e '\<ParallelGCThreads\>'"
JAVA_CMD=(/bin/sh -c "java -XX:+PrintFlagsFinal -version 2>/dev/null | grep -i ${GREP_CMD}")
JSHELL_EXIT_SEQUENCE='\n\\exit'
# List the final flags
echo "List the final flags"
sleep 1
echo "${JAVA_CMD[@]}"
docker run "${OPENJDK_IMAGE}" "${JAVA_CMD[@]}"
echo
echo
sleep 1
# List the number of processors on the host
echo "List the number of processors on the host"
sleep 1
printf "Runtime.getRuntime().availableProcessors()" \
| xargs -0 printf "%s${JSHELL_EXIT_SEQUENCE}" \
| "${JSHELL_CMD[@]}"
echo
echo
sleep 1
# jshell> Runtime.getRuntime().availableProcessors()
# $1 ==> 8
# jshell> \exit%
# List the number of processors within the container
echo "List the number of processors within the container"
sleep 1
printf "Runtime.getRuntime().availableProcessors()" \
| xargs -0 printf "%s${JSHELL_EXIT_SEQUENCE}" \
| docker run -i "${OPENJDK_IMAGE}" "${JSHELL_CMD[@]}"
echo
echo
sleep 1
# Mar 24, 2018 8:55:40 PM java.util.prefs.FileSystemPreferences$1 run
# INFO: Created user preferences directory.
# jshell> Runtime.getRuntime().availableProcessors()
# $1 ==> 8
# jshell> \exit%
## CPU Shares
# From: https://jaxenter.com/better-containerized-jvms-jdk-10-140593.html#cpu-shares
#
# This rations the CPU according to the proportions you choose, but only when
# the system is busy. For example, you can have three containers with shares of
# 1024/512/512, but those limits are only applied when necessary. When there is
# headroom your containerized process can use left-over CPU time.
# 1 CPU = 1024 shares, so 36864/1024 = 36 processors, however 36 > 8, so 8 is reported
echo "List the number of processors within the container with 36864 cpu shares"
sleep 1
printf "Runtime.getRuntime().availableProcessors()" \
| xargs -0 printf "%s${JSHELL_EXIT_SEQUENCE}" \
| docker run --cpu-shares 36864 -i "${OPENJDK_IMAGE}" "${JSHELL_CMD[@]}"
echo
echo
sleep 1
# Mar 24, 2018 8:58:55 PM java.util.prefs.FileSystemPreferences$1 run
# INFO: Created user preferences directory.
# jshell> Runtime.getRuntime().availableProcessors()
# $1 ==> 8
# jshell> \exit%
# 1 CPU = 1024 shares, so 4096/1024 = 4 processors, since 4 < 8, 4 is reported
echo "List the number of processors within the container with 4096 cpu shares"
sleep 1
printf "Runtime.getRuntime().availableProcessors()" \
| xargs -0 printf "%s${JSHELL_EXIT_SEQUENCE}" \
| docker run --cpu-shares 4096 -i "${OPENJDK_IMAGE}" "${JSHELL_CMD[@]}"
echo
echo
sleep 1
# Mar 24, 2018 9:02:19 PM java.util.prefs.FileSystemPreferences$1 run
# INFO: Created user preferences directory.
# jshell> Runtime.getRuntime().availableProcessors()
# $1 ==> 4
# jshell> \exit%
## CPU Quota
# From: https://jaxenter.com/better-containerized-jvms-jdk-10-140593.html#cpu-periodquota
#
# This uses the Linux Completely Fair Scheduler to limit the container’s CPU
# usage. This means that the container will have limited CPU time even when the
# machine is lightly loaded and your workload may be spread across all the CPUs
# on the host. The example here might give you 50% time on all 72 cores, for
# example.
# TODO:
# /nix/store/aiahnd4gqvlv0hlgs4j3sv91x8zy05zg-docker-17.09.1-ce/libexec/docker/docker:
# Error response from daemon: NanoCPUs can not be set, as your kernel does not
# support CPU cfs period/quota or the cgroup is not mounted.
#
# See: https://github.com/moby/moby/issues/12348
# See:
# echo "List the number of processors within the container with 2 cpus"
# sleep 1
# printf "Runtime.getRuntime().availableProcessors()" \
# | xargs -0 printf "%s${JSHELL_EXIT_SEQUENCE}" \
# | docker run --cpus 2 -i "${OPENJDK_IMAGE}" "${JSHELL_CMD[@]}"
# echo
# sleep 1
## CPU Sets
# From: https://jaxenter.com/better-containerized-jvms-jdk-10-140593.html#cpu-sets
#
# Unlike the two previous constraints, this pins the containerized process to
# specific CPUs. Your process may have to share those CPUs, but will obviously
# not be allowed to use spare capacity on any others.
echo "List the number of processors within the container with cpuset of 0-2 (3 total) cpus"
sleep 1
printf "Runtime.getRuntime().availableProcessors()" \
| xargs -0 printf "%s${JSHELL_EXIT_SEQUENCE}" \
| docker run --cpuset-cpus 0-2 -i "${OPENJDK_IMAGE}" "${JSHELL_CMD[@]}"
echo
echo
sleep 1
# Mar 24, 2018 9:10:01 PM java.util.prefs.FileSystemPreferences$1 run
# INFO: Created user preferences directory.
# jshell> Runtime.getRuntime().availableProcessors()
# $1 ==> 3
# jshell> \exit%
## Memory
# List the memory on the host
echo "List the memory on the host"
sleep 1
printf "Runtime.getRuntime().maxMemory()" \
| xargs -0 printf "%s${JSHELL_EXIT_SEQUENCE}" \
| "${JSHELL_CMD[@]}"
echo
echo
sleep 1
# jshell> Runtime.getRuntime().maxMemory()
# $1 ==> 2048917504
# jshell> \exit%
# List the memory within the container
echo "List the mex memory within the container"
sleep 1
printf "Runtime.getRuntime().maxMemory()" \
| xargs -0 printf "%s${JSHELL_EXIT_SEQUENCE}" \
| docker run -i "${OPENJDK_IMAGE}" "${JSHELL_CMD[@]}"
echo
echo
sleep 1
# Mar 24, 2018 9:14:11 PM java.util.prefs.FileSystemPreferences$1 run
# INFO: Created user preferences directory.
# jshell> Runtime.getRuntime().maxMemory()
# $1 ==> 2048917504
# jshell> \exit%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment