support/testing: add numactl runtime test
Signed-off-by: Julien Olivain <ju.o@free.fr> Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
This commit is contained in:
parent
6338bdfc1c
commit
506073c3ed
@ -1816,6 +1816,8 @@ F: support/testing/tests/package/test_netcat.py
|
||||
F: support/testing/tests/package/test_nftables.py
|
||||
F: support/testing/tests/package/test_nftables/
|
||||
F: support/testing/tests/package/test_ngrep.py
|
||||
F: support/testing/tests/package/test_numactl.py
|
||||
F: support/testing/tests/package/test_numactl/
|
||||
F: support/testing/tests/package/test_octave.py
|
||||
F: support/testing/tests/package/test_ola.py
|
||||
F: support/testing/tests/package/test_ola/
|
||||
|
142
support/testing/tests/package/test_numactl.py
Normal file
142
support/testing/tests/package/test_numactl.py
Normal file
@ -0,0 +1,142 @@
|
||||
import os
|
||||
import re
|
||||
|
||||
import infra.basetest
|
||||
|
||||
|
||||
class TestNumaCtl(infra.basetest.BRTest):
|
||||
# A specific configuration is needed for testing numactl:
|
||||
# - This test uses a x86_64 config, which has mature NUMA support.
|
||||
# - A kernel need to compiled with a NUMA support.
|
||||
kernel_fragment = \
|
||||
infra.filepath("tests/package/test_numactl/linux-numactl.fragment")
|
||||
config = \
|
||||
f"""
|
||||
BR2_x86_64=y
|
||||
BR2_x86_corei7=y
|
||||
BR2_TOOLCHAIN_EXTERNAL=y
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.75"
|
||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
|
||||
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/x86_64/linux.config"
|
||||
BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{kernel_fragment}"
|
||||
BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
|
||||
BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y
|
||||
BR2_PACKAGE_NUMACTL=y
|
||||
BR2_TARGET_ROOTFS_CPIO=y
|
||||
BR2_TARGET_ROOTFS_CPIO_GZIP=y
|
||||
# BR2_TARGET_ROOTFS_TAR is not set
|
||||
"""
|
||||
|
||||
def check_numactl_preferred(self):
|
||||
# Show the default NUMA policy settings. We check we have the
|
||||
# 4 physical cpus on 2 nodes we configured the emulator
|
||||
# command line.
|
||||
out, ret = self.emulator.run("numactl --show")
|
||||
self.assertEqual(ret, 0)
|
||||
checks = [
|
||||
"policy: default",
|
||||
"preferred node: current",
|
||||
"physcpubind: 0 1 2 3 ",
|
||||
"nodebind: 0 1 ",
|
||||
"membind: 0 1 "
|
||||
]
|
||||
for pattern in checks:
|
||||
self.assertIn(pattern, out)
|
||||
|
||||
# Check the preferred policy on different nodes. This command
|
||||
# is taken from the numactl man page.
|
||||
for pref_node in range(2):
|
||||
cmd = f"numactl --preferred={pref_node} numactl --show"
|
||||
out, ret = self.emulator.run(cmd)
|
||||
self.assertEqual(ret, 0)
|
||||
checks = [
|
||||
"policy: preferred",
|
||||
f"preferred node: {pref_node}"
|
||||
]
|
||||
for pattern in checks:
|
||||
self.assertIn(pattern, out)
|
||||
|
||||
def get_numa_node_free_mem(self):
|
||||
out, ret = self.emulator.run("numactl --hardware")
|
||||
self.assertEqual(ret, 0)
|
||||
free_mem = {}
|
||||
p = re.compile("^node ([0-9]+) free: ([0-9]+) MB")
|
||||
for line in out:
|
||||
m = p.match(line)
|
||||
if m:
|
||||
node = int(m.group(1))
|
||||
mem = int(m.group(2))
|
||||
free_mem[node] = mem
|
||||
return free_mem
|
||||
|
||||
def check_numactl_membind(self):
|
||||
# We get the current amount of free memory on each node, for
|
||||
# later comparison.
|
||||
initial_node_free_mem = self.get_numa_node_free_mem()
|
||||
|
||||
# We allocate a shared memory file with a restriction to be in
|
||||
# node 1 memory only.
|
||||
shm_file = "/dev/shm/file"
|
||||
file_size = 100
|
||||
cmd = f"numactl --membind=1 dd if=/dev/zero of={shm_file} bs=1M count={file_size}"
|
||||
self.assertRunOk(cmd)
|
||||
|
||||
# We collect again the amount of free memory per node.
|
||||
node_free_mem = self.get_numa_node_free_mem()
|
||||
|
||||
# Since we allocated 100M on node 1 only, we check the free
|
||||
# space on node 0 did not significantly changed and on node 1
|
||||
# approximately reduced of the file size.
|
||||
diff = initial_node_free_mem[0] - node_free_mem[0]
|
||||
self.assertAlmostEqual(diff, 0, delta=10)
|
||||
diff = initial_node_free_mem[1] - node_free_mem[1]
|
||||
self.assertAlmostEqual(diff, file_size, delta=10)
|
||||
|
||||
# Remove the file, to free the memory.
|
||||
self.assertRunOk(f"rm -f {shm_file}")
|
||||
|
||||
# We allocate again a file in shared memory, but this time in
|
||||
# two chunks. Each chunk is requested to be allocated in two
|
||||
# different nodes. This example is taken from the numactl man
|
||||
# page.
|
||||
chunk_size = file_size // 2
|
||||
cmd = "numactl --membind=0 "
|
||||
cmd += f"dd if=/dev/zero of={shm_file} bs=1M count={chunk_size}"
|
||||
self.assertRunOk(cmd)
|
||||
cmd = "numactl --membind=1 "
|
||||
cmd += f"dd if=/dev/zero of={shm_file} bs=1M count={chunk_size} seek={chunk_size}"
|
||||
self.assertRunOk(cmd)
|
||||
|
||||
# We collect again the amount of free memory.
|
||||
node_free_mem = self.get_numa_node_free_mem()
|
||||
|
||||
# We check the free memory space approximately reduced of each
|
||||
# chunk size.
|
||||
for node in range(2):
|
||||
free_mem_diff = initial_node_free_mem[node] - node_free_mem[node]
|
||||
self.assertAlmostEqual(free_mem_diff, chunk_size, delta=5)
|
||||
|
||||
def test_run(self):
|
||||
img = os.path.join(self.builddir, "images", "rootfs.cpio.gz")
|
||||
kern = os.path.join(self.builddir, "images", "bzImage")
|
||||
# We start the Qemu emulator with 4 processors on 2 NUMA nodes.
|
||||
self.emulator.boot(arch="x86_64",
|
||||
kernel=kern,
|
||||
kernel_cmdline=["console=ttyS0"],
|
||||
options=["-cpu", "Nehalem", "-m", "512M",
|
||||
"-smp", "cpus=4,sockets=2,cores=2,maxcpus=4",
|
||||
"-object", "memory-backend-ram,size=256M,id=m0",
|
||||
"-object", "memory-backend-ram,size=256M,id=m1",
|
||||
"-numa", "node,cpus=0-1,nodeid=0,memdev=m0",
|
||||
"-numa", "node,cpus=2-3,nodeid=1,memdev=m1",
|
||||
"-initrd", img])
|
||||
self.emulator.login()
|
||||
|
||||
# Check a simple numactl invication:
|
||||
# show the NUMA hardware inventory.
|
||||
self.assertRunOk("numactl --hardware")
|
||||
|
||||
self.check_numactl_preferred()
|
||||
self.check_numactl_membind()
|
@ -0,0 +1 @@
|
||||
CONFIG_NUMA=y
|
Loading…
Reference in New Issue
Block a user