Merge pull request #292 from hodgesds/stress-ng-ci

Add stress-ng to scheduler tests
This commit is contained in:
David Vernet 2024-06-21 11:35:56 -05:00 committed by GitHub
commit 3219d15e3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 147 additions and 2 deletions

View File

@ -16,7 +16,7 @@ jobs:
### DOWNLOAD AND INSTALL DEPENDENCIES ###
# Download dependencies packaged by Ubuntu
- run: sudo apt -y install bison busybox-static cargo cmake coreutils cpio elfutils file flex gcc gcc-multilib git iproute2 jq kbd kmod libcap-dev libelf-dev libunwind-dev libvirt-clients libzstd-dev linux-headers-generic linux-tools-common linux-tools-generic make ninja-build pahole pkg-config python3-dev python3-pip python3-requests qemu-kvm rsync rustc udev zstd
- run: sudo apt -y install bison busybox-static cargo cmake coreutils cpio elfutils file flex gcc gcc-multilib git iproute2 jq kbd kmod libcap-dev libelf-dev libunwind-dev libvirt-clients libzstd-dev linux-headers-generic linux-tools-common linux-tools-generic make ninja-build pahole pkg-config python3-dev python3-pip python3-requests qemu-kvm rsync rustc stress-ng udev zstd
# clang 17
# Use a custom llvm.sh script which includes the -y flag for
@ -54,7 +54,7 @@ jobs:
### END DEPENDENCIES ###
# The actual build:
- run: meson setup build -Dkernel=$(pwd)/linux -Dkernel_headers=./linux/usr/include
- run: meson setup build -Dkernel=$(pwd)/linux -Dkernel_headers=./linux/usr/include -Denable_stress=true
- run: meson compile -C build --jobs=1
# Print CPU model before running the tests (this can be useful for
@ -69,3 +69,5 @@ jobs:
# Test schedulers
- run: meson compile -C build test_sched
# Stress schedulers
- run: meson compile -C build stress_tests

113
meson-scripts/run_stress_tests Executable file
View File

@ -0,0 +1,113 @@
#!/usr/bin/env python3
"""
Small wrapper for running stress tests. Do not make this more complicated and
assume any libraries besides Python3 stdlib.
"""
import logging
import os
import subprocess
import sys
import time
from pathlib import PurePath
from typing import List
from argparse import ArgumentParser, Namespace
from configparser import ConfigParser
logger = logging.getLogger(__name__)
SCRIPT_DIR: str = os.path.dirname(os.path.realpath(__file__))
def get_exe_path(exe: str) -> str:
path = subprocess.check_output(["which", exe])
return path.decode("utf-8").replace("\n", "")
def sched_path(path: str, sched: str) -> str:
rel_path = subprocess.check_output(
["find", path, "-type", "f", "-executable", "-name", sched]).decode("utf-8").replace("\n", "")
full_path = subprocess.check_output(["readlink", "-f", rel_path]).decode("utf-8").replace("\n", "")
logger.debug(f"found scheduler {sched} in path: {full_path}")
return full_path
def load_config(path: str) -> ConfigParser:
config = ConfigParser()
config.read(path)
return config
def run_stress_test(
config,
build_dir: str,
output: str,
vng_path: str,
kernel: str,
verbose: bool,
) -> int:
scheduler_args = config.get('scheduler_args')
stress_cmd = config.get('stress_cmd')
s_path = sched_path(build_dir, config.get('sched'))
sched_cmd = s_path + " " + config.get('sched_args')
timeout_sec = int(config.get("timeout_sec"))
if vng_path:
vm_input = f"{stress_cmd} & timeout --foreground --preserve-status {timeout_sec} {sched_cmd}"
cmd = [vng_path, "--user", "root", "--force-9p", "-v", "--", vm_input]
err = sys.stderr if output == "-" else open(output, "w")
out = sys.stdout if output == "-" else err
proc = subprocess.Popen(
cmd, env=os.environ, cwd=kernel, shell=False, stdout=out,
stderr=err, stdin=subprocess.PIPE, text=True)
proc.wait()
return proc.returncode
def stress_tests(args: Namespace) -> None:
configs = load_config(args.config)
vng_path = ""
if args.vng:
try:
vng_path = get_exe_path("vng")
except Exception:
raise OSError(
"Please install `vng` to run, see:\n"
"https://github.com/arighi/virtme-ng?tab=readme-ov-file#installation")
return_codes = {}
for test_name in configs.sections():
if args.stress_test and test_name != args.stress_test:
continue
return_codes[test_name] = run_stress_test(
configs[test_name],
args.build_dir,
args.output,
vng_path,
args.kernel,
args.verbose,
)
for test_name, ret in return_codes.items():
if ret not in (143, 0):
logging.error(f"Failed stress tests for {test_name}: exit {ret}")
sys.exit(ret)
logging.info("All stress tests passed!")
if __name__ == "__main__":
parser = ArgumentParser(prog=__file__)
parser.add_argument(
'-c', '--config',
default=os.path.join(SCRIPT_DIR, "stress_tests.ini"),
help='Path to config file'
)
parser.add_argument('-o', '--output', default='-', help='Scheduler output')
parser.add_argument(
'-t', '--stress-test', default='', help='Name of the stress test (default: all)')
parser.add_argument(
'-b', '--build-dir', default='build', help='Meson build dir')
parser.add_argument(
'-k', '--kernel', default='', help='Kernel path for vng')
parser.add_argument(
'-v', '--verbose', action='store_true', help='Verbose output')
parser.add_argument(
'--vng', action='store_true', default=True, help='Run in vng')
args = parser.parse_args()
if args.verbose:
logger.setLevel(logging.DEBUG)
stress_tests(args)

View File

@ -0,0 +1,17 @@
[scx_lavd]
sched: scx_lavd
sched_args:
stress_cmd: stress-ng -t 14 --aggressive -M -c `nproc` -f `nproc`
timeout_sec: 15
[scx_rusty]
sched: scx_rusty
sched_args:
stress_cmd: stress-ng -t 14 --aggressive -M -c `nproc` -f `nproc`
timeout_sec: 15
[scx_rustland]
sched: scx_rustland
sched_args:
stress_cmd: stress-ng -t 14 --aggressive -M -c `nproc` -f `nproc`
timeout_sec: 15

View File

@ -14,10 +14,16 @@ enable_rust = get_option('enable_rust')
bpf_clang = find_program(get_option('bpf_clang'))
enable_stress = get_option('enable_stress')
if enable_rust
cargo = find_program(get_option('cargo'))
endif
if enable_stress
run_stress_tests = find_program(join_paths(meson.current_source_dir(),
'meson-scripts/run_stress_tests'))
endif
get_clang_ver = find_program(join_paths(meson.current_source_dir(),
'meson-scripts/get_clang_ver'))
@ -320,6 +326,11 @@ if enable_rust
endif
subdir('scheds')
if enable_stress
run_target('stress_tests', command: [run_stress_tests, '-k', kernel, '-b',
meson.current_build_dir()])
endif
systemd = dependency('systemd', required: get_option('systemd'))
if systemd.found()

View File

@ -14,6 +14,8 @@ option('offline', type: 'boolean', value: 'false',
description: 'Compilation step should not access the internet')
option('enable_rust', type: 'boolean', value: 'true',
description: 'Enable rust sub-projects')
option('enable_stress', type: 'boolean', value: 'true',
description: 'Enable stress tests')
option('kernel', type: 'string', value: 'vmlinuz',
description: 'kernel image used to test schedulers')
option('kernel_headers', type: 'string', value: '',