Skip to content

Commit ed8e4cb

Browse files
sjoelundclaude
andauthored
Limit the memory of a dockerized test job (#317)
test.py caps the address space of one test at a time, so nothing bounds the sum of the tests it runs in parallel. That is worst for wasm-jit, whose tests are allowed 16 GB of address space each because the JIT reserves ~4 GB of it per wasm memory. Cap the container the job runs in with `docker run --memory=N --memory-swap=N`, N = 85% of the node's RAM, since these jobs are pinned to the high-memory nodes. A cgroup limit charges memory in use rather than address space, covers every process test.py spawns, and on a breach the kernel kills the greediest omc - so a model can now fail because of a model tested in parallel with it, which the log makes visible: the limit is printed before the run and the peak plus the OOM kill count after it. Only the targets that build their own image (wasm-jit today) get this; the jobs running directly on a node are unchanged. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent cb514ad commit ed8e4cb

1 file changed

Lines changed: 20 additions & 0 deletions

File tree

‎.CI/Jenkinsfile‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,18 @@ done
598598
"""
599599
}
600600

601+
/**
602+
* `docker run` flags capping the container's cgroup at 90% of the node's RAM. test.py limits one
603+
* test at a time, not the sum of the parallel ones. --memory-swap has to repeat the limit; docker
604+
* reads 0 as "unset" and then allows swapping.
605+
*/
606+
def memoryLimitArgs() {
607+
def mb = sh(script: '''awk '/^MemTotal:/ { print int($2 / 1024 * 0.85) }' /proc/meminfo''',
608+
returnStdout: true).trim()
609+
echo "Test container memory limit: ${mb} MB, no swap"
610+
return "--memory=${mb}m --memory-swap=${mb}m"
611+
}
612+
601613
/**
602614
* Runs `body` with the environment of the shared Rust compile cache of the OpenModelica job
603615
* (OpenModelica/.CI/sccache/), which builds the same commits first. Hitting its keys needs the
@@ -713,10 +725,17 @@ def runRegressiontest(branch, name, extraFlags, omsHash, omcompiler, extrasimfla
713725
// build, the libraries (HOME during the test) and the ssh key; test.py writes a hash next to
714726
// every reference file. rust-cargo-registry is the volume the OpenModelica job uses.
715727
def dockerArgs = "--init" +
728+
(image ? " ${memoryLimitArgs()}" : '') +
716729
" -v /etc/passwd:/etc/passwd:ro -v /etc/group:/etc/group:ro" +
717730
" -v ${env.HOME}:${env.HOME}" +
718731
" -v /mnt/ReferenceFiles:/mnt/ReferenceFiles" +
719732
" --mount type=volume,source=rust-cargo-registry,target=/opt/rust/cargo/registry"
733+
// Only in a container is the cgroup this job's own; a breach kills the greediest omc, which need
734+
// not be the model that caused it.
735+
def cgroupReport = image ? """
736+
cat /sys/fs/cgroup/memory.max || true
737+
trap 'cat /sys/fs/cgroup/memory.peak /sys/fs/cgroup/memory.events || true' EXIT
738+
""" : ''
720739
// Jenkins exports the node's environment into the container, hiding the image's.
721740
def dockerEnv = ['PATH+VENV=/opt/libtest-venv/bin',
722741
'PATH+CARGO=/opt/rust/cargo/bin',
@@ -956,6 +975,7 @@ def runRegressiontest(branch, name, extraFlags, omsHash, omcompiler, extrasimfla
956975
# too bad if we cannot do it, just continue
957976
ln -s -t \${HOME} \${PREVIOUSHOME}/.local .local || true
958977
978+
${cgroupReport}
959979
cd OpenModelicaLibraryTesting
960980
# Force /usr/bin/omc as being used for generating the mos-files. Ensures consistent behavior among all tested OMC versions
961981
stdbuf -oL -eL time ./test.py --ompython_omhome=/usr ${FMI_TESTING_FLAG} --extraflags='${extraFlags}' --extrasimflags='${extrasimflags}' ${testFlags} --branch="${name}" --output="libraries.openmodelica.org:/var/www/libraries.openmodelica.org/branches/${name}/" --libraries='${libraryPath}/.openmodelica/libraries/' --jobs=${jobs} ${libs_config_file} ${params.OLDLIBS ? "configs/conf-old.json configs/conf-nonstandard.json" : ""} || (killall omc ; false) || exit 1

0 commit comments

Comments
 (0)