From: Lukas Doktor <ldoktor@redhat.com>
To: autotest@test.kernel.org, kvm@vger.kernel.org,
kvm-autotest@redhat.com, lmr@redhat.com, ldoktor@redhat.com,
jzupka@redhat.com
Subject: [PATCH 1/2] [KVM-autotest] tests.cgroup: Add cpu_cfs_util test
Date: Fri, 23 Dec 2011 15:37:48 +0100 [thread overview]
Message-ID: <1324651069-9619-2-git-send-email-ldoktor@redhat.com> (raw)
In-Reply-To: <1324651069-9619-1-git-send-email-ldoktor@redhat.com>
This test tests the cpu.cfs_* subsystem. It's focused on known issue with
multiple threads in related cpu cgroup with defined cpu.cfs_quota_us. CFS
might schedule those threads very inefficiently.
* Add TestCpuCFS
Signed-off-by: Lukas Doktor <ldoktor@redhat.com>
---
client/tests/kvm/subtests.cfg.sample | 2 +
client/tests/kvm/tests/cgroup.py | 168 ++++++++++++++++++++++++++++++++++
2 files changed, 170 insertions(+), 0 deletions(-)
diff --git a/client/tests/kvm/subtests.cfg.sample b/client/tests/kvm/subtests.cfg.sample
index 3d47fb4..ca75fe4 100644
--- a/client/tests/kvm/subtests.cfg.sample
+++ b/client/tests/kvm/subtests.cfg.sample
@@ -1048,6 +1048,8 @@ variants:
type = cgroup
# cgroup_tests = "re1[:loops] re2[:loops] ..."
cgroup_tests = ".*:1"
+ #cgroup_memory_limit_kb = 2097152 # default 1/2 guest ram
+ #cgroup_memory_move_mb = 2048 # default 1/2 guest ram
vms += " vm2"
extra_params += " -snapshot"
diff --git a/client/tests/kvm/tests/cgroup.py b/client/tests/kvm/tests/cgroup.py
index 95ca1fd..148e4e7 100644
--- a/client/tests/kvm/tests/cgroup.py
+++ b/client/tests/kvm/tests/cgroup.py
@@ -1315,6 +1315,173 @@ def run_cgroup(test, params, env):
self.speeds = [100000, 100000]
+ class TestCpuCFSUtil:
+ """
+ Tests the utilisation of scheduler when cgroup cpu.cfs_* setting is
+ set. There is a known issue with scheduler and multiple CPUs.
+ """
+ def __init__(self, vms, modules):
+ """
+ Initialization
+ @param vms: list of vms
+ @param modules: initialized cgroup module class
+ """
+ self.vms = vms[:] # Copy of virt machines
+ self.vms_count = len(vms) # Original number of vms
+ self.modules = modules # cgroup module handler
+ self.cgroup = Cgroup('cpu', '') # cgroup blkio handler
+ self.sessions = [] # ssh sessions
+ self.serials = [] # serial consoles
+
+
+ def cleanup(self):
+ """ Cleanup """
+ err = ""
+ del(self.cgroup)
+
+ for i in range(len(self.vms)):
+ self.serials[i].sendline('rm -f /tmp/cgroup-cpu-lock')
+ del self.serials
+
+ for i in range(len(self.sessions)):
+ try:
+ self.sessions[i].close()
+ except Exception, failure_detail:
+ err += ("\nCan't close ssh connection %s" % i)
+ del self.sessions
+
+ for vm in self.vms[self.vms_count:]:
+ try:
+ vm.destroy(gracefully=False)
+ except Exception, failure_detail:
+ err += "\nCan't destroy added VM: %s" % failure_detail
+ del self.vms
+
+ if err:
+ logging.error("Some cleanup operations failed: %s", err)
+ raise error.TestError("Some cleanup operations failed: %s"
+ % err)
+
+
+ def init(self):
+ """
+ Initialization
+ * creates additional VMs (vm_cpus = 2 * host_cpus)
+ * creates cgroup for each VM and subcgroup for theirs vCPUs
+ (../vm[123..]/vcpu[012..])
+ """
+ def get_cpu_pids(vm, smp=None):
+ """ Get pids of all VM's vcpus """
+ cpu_pids = re.findall(r'thread_id=(\d+)',
+ vm.monitor.info("cpus"))
+ if not cpu_pids:
+ raise error.TestFail("Can't get 'info cpus' from monitor")
+ if smp is not None and len(cpu_pids) != smp:
+ raise error.TestFail("Incorrect no vcpus: monitor = %s, "
+ "params = %s" % (len(cpu_pids), smp))
+ return cpu_pids
+
+ self.cgroup.initialize(self.modules)
+ host_cpus = open('/proc/cpuinfo').read().count('model name')
+ smp = int(params.get('smp', 1))
+ vm_cpus = 0
+ # Prepare existing vms (if necessarily)
+ for i in range(min(len(self.vms), 2 * host_cpus / smp)):
+ # create "/vm[123]/ cgroups and set cfs_quota_us to no_vcpus*50%
+ vm_pwd = self.cgroup.mk_cgroup()
+ self.cgroup.set_property("cpu.cfs_period_us", 100000, vm_pwd)
+ self.cgroup.set_property("cpu.cfs_quota_us", 50000*smp, vm_pwd)
+ assign_vm_into_cgroup(self.vms[i], self.cgroup, vm_pwd)
+ cpu_pids = get_cpu_pids(self.vms[i], smp)
+ for j in range(smp):
+ # create "/vm*/vcpu[123] cgroups and set cfs_quota_us to 50%
+ vcpu_pwd = self.cgroup.mk_cgroup(vm_pwd)
+ self.cgroup.set_property("cpu.cfs_period_us", 100000,
+ vcpu_pwd)
+ self.cgroup.set_property("cpu.cfs_quota_us", 50000,
+ vcpu_pwd)
+ self.cgroup.set_cgroup(int(cpu_pids[j]), vcpu_pwd)
+ self.sessions.append(self.vms[i].wait_for_login(timeout=30))
+ vm_cpus += 1
+ self.serials.append(self.vms[i].wait_for_serial_login(
+ timeout=30))
+ self.serials[-1].cmd("touch /tmp/cgroup-cpu-lock")
+ timeout = 1.5 * int(params.get("login_timeout", 360))
+ _params = params
+ # Add additional vms (if necessarily)
+ i = 0
+ while vm_cpus < 2 * host_cpus:
+ vm_name = "clone%s" % i
+ smp = min(vm_cpus, 2 * host_cpus - vm_cpus)
+ _params['smp'] = smp
+ self.vms.append(self.vms[0].clone(vm_name, _params))
+ env.register_vm(vm_name, self.vms[-1])
+ self.vms[-1].create()
+ vm_pwd = self.cgroup.mk_cgroup()
+ self.cgroup.set_property("cpu.cfs_period_us", 100000, vm_pwd)
+ self.cgroup.set_property("cpu.cfs_quota_us", 50000*smp, vm_pwd)
+ assign_vm_into_cgroup(self.vms[-1], self.cgroup, vm_pwd)
+ cpu_pids = get_cpu_pids(self.vms[-1], smp)
+ for j in range(smp):
+ vcpu_pwd = self.cgroup.mk_cgroup(vm_pwd)
+ self.cgroup.set_property("cpu.cfs_period_us", 100000,
+ vcpu_pwd)
+ self.cgroup.set_property("cpu.cfs_quota_us", 50000,
+ vcpu_pwd)
+ self.cgroup.set_cgroup(int(cpu_pids[j]), vcpu_pwd)
+ self.sessions.append(self.vms[-1].wait_for_login(
+ timeout=timeout))
+ self.serials.append(self.vms[-1].wait_for_serial_login(
+ timeout=30))
+ self.serials[-1].cmd("touch /tmp/cgroup-cpu-lock")
+ vm_cpus += smp
+ i += 1
+
+
+ def run(self):
+ """
+ Actual test:
+ It run stressers on all vcpus, gather host CPU utilisation and
+ verifies that guests use at least 95% of CPU time.
+ """
+ stats = []
+ cmd = "renice -n 10 $$; "
+ cmd += "while [ -e /tmp/cgroup-cpu-lock ]; do :; done"
+ for session in self.sessions:
+ session.sendline(cmd)
+
+ # Test
+ time.sleep(1)
+ stats.append(open('/proc/stat', 'r').readline())
+ time.sleep(1)
+ stats.append(open('/proc/stat', 'r').readline())
+ time.sleep(9)
+ stats.append(open('/proc/stat', 'r').readline())
+ time.sleep(49)
+ stats.append(open('/proc/stat', 'r').readline())
+ for session in self.serials:
+ session.sendline('rm -f /tmp/cgroup-cpu-lock')
+
+ # Verification
+ print stats
+ stats[0] = [int(_) for _ in stats[0].split()[1:]]
+ stats[0] = [sum(stats[0][0:8]), sum(stats[0][8:])]
+ for i in range(1, len(stats)):
+ stats[i] = [int(_) for _ in stats[i].split()[1:]]
+ try:
+ stats[i] = (float(sum(stats[i][8:]) - stats[0][1]) /
+ (sum(stats[i][0:8]) - stats[0][0]))
+ except ZeroDivisionError:
+ logging.error("ZeroDivisionError in stats calculation")
+ stats[i] = False
+ print stats
+ for i in range(1, len(stats)):
+ if stats[i] < 0.95:
+ raise error.TestFail("Guest time is not >95%% %s" % stats)
+
+ logging.info("Guest times are over 95%%: %s", stats)
+ return "Guest times are over 95%%: %s" % stats
+
class TestCpusetCpus:
"""
Tests the cpuset.cpus cgroup feature. It stresses all VM's CPUs
@@ -1606,6 +1773,7 @@ def run_cgroup(test, params, env):
"memory_limit" : TestMemoryLimit,
"cpu_share_10" : TestCpuShare10,
"cpu_share_50" : TestCpuShare50,
+ "cpu_cfs_util" : TestCpuCFSUtil,
"cpuset_cpus" : TestCpusetCpus,
"cpuset_cpus_switching" : TestCpusetCpusSwitching,
}
--
1.7.7.4
next prev parent reply other threads:[~2011-12-23 14:37 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-12-23 14:37 [KVM-autotest] tests.cgroup: Add cpu_cfs test and bugfixes Lukas Doktor
2011-12-23 14:37 ` Lukas Doktor [this message]
2011-12-23 14:37 ` [PATCH 2/2] [KVM-autotest] tests.cgroup: Variable limits in TestMemory* " Lukas Doktor
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1324651069-9619-2-git-send-email-ldoktor@redhat.com \
--to=ldoktor@redhat.com \
--cc=autotest@test.kernel.org \
--cc=jzupka@redhat.com \
--cc=kvm-autotest@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=lmr@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).