123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- 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()
|