From patchwork Wed Oct 13 14:13:19 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Zupka X-Patchwork-Id: 250731 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o9DECrwI002623 for ; Wed, 13 Oct 2010 14:12:53 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752717Ab0JMOMr (ORCPT ); Wed, 13 Oct 2010 10:12:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41647 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752470Ab0JMOMq (ORCPT ); Wed, 13 Oct 2010 10:12:46 -0400 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o9DECjGI006563 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 13 Oct 2010 10:12:46 -0400 Received: from jzupka.local.com (dhcp-27-161.brq.redhat.com [10.34.27.161]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o9DECb2J009027; Wed, 13 Oct 2010 10:12:44 -0400 From: =?UTF-8?q?Ji=C5=99=C3=AD=20=C5=BDupka?= To: kvm-autotest@redhat.com, kvm@vger.kernel.org Cc: jzupka@redhat.com, akong@redhat.com, ldoktor@redhat.com Subject: [Autotest][PATCH 4/4] Get system and/or process values and return average value of load cpu or mem. Date: Wed, 13 Oct 2010 16:13:19 +0200 Message-Id: <1286979199-13109-5-git-send-email-jzupka@redhat.com> In-Reply-To: <1286979199-13109-1-git-send-email-jzupka@redhat.com> References: <1286979199-13109-1-git-send-email-jzupka@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.16 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Wed, 13 Oct 2010 14:12:53 +0000 (UTC) diff --git a/client/common_lib/utils.py b/client/common_lib/utils.py index e7e0d02..6fb6ae4 100644 --- a/client/common_lib/utils.py +++ b/client/common_lib/utils.py @@ -969,6 +969,226 @@ def get_cpu_percentage(function, *args, **dargs): return cpu_percent, to_return +class SystemLoad(): + """ + Get system and/or process values and return average value of load. + """ + def __init__(self, pids, advanced=False, time_step=0.1, cpu_cont=False, + use_log=False): + """ + @param pids: List of pids to be monitored. If pid = 0 whole system will + be monitored. pid == 0 means whole system. + @param advanced: monitor add value for system irq count and softirq + for process minor and maior page fault + @param time_step: Time step for continuous monitoring. + @param cpu_cont: If True monitor CPU load continuously. + @param use_log: If true every monitoring is logged for dump. + """ + self.pids = [] + self.stats = {} + for pid in pids: + if pid == 0: + cpu = FileFieldMonitor("/proc/stat", + [("cpu", 0), # User Time + ("cpu", 2), # System Time + ("intr", 0), # IRQ Count + ("softirq", 0)], # Soft IRQ Count + True, + cpu_cont, + use_log, + " +", + time_step) + mem = FileFieldMonitor("/proc/meminfo", + [("MemTotal:", 0), # Mem Total + ("MemFree:", 0), # Mem Free + ("Buffers:", 0), # Buffers + ("Cached:", 0)], # Cached + False, + True, + use_log, + " +", + time_step) + self.stats[pid] = ["TOTAL", cpu, mem] + self.pids.append(pid) + else: + name = "" + if (type(pid) is int): + self.pids.append(pid) + name = get_process_name(pid) + else: + self.pids.append(pid[0]) + name = pid[1] + + cpu = FileFieldMonitor("/proc/%d/stat" % + self.pids[-1], + [("", 13), # User Time + ("", 14), # System Time + ("", 9), # Minority Page Fault + ("", 11)], # Majority Page Fault + True, + cpu_cont, + use_log, + " +", + time_step) + mem = FileFieldMonitor("/proc/%d/status" % + self.pids[-1], + [("VmSize:", 0), # Virtual Memory Size + ("VmRSS:", 0), # Resident Set Size + ("VmPeak:", 0), # Peak VM Size + ("VmSwap:", 0)], # VM in Swap + False, + True, + use_log, + " +", + time_step) + self.stats[self.pids[-1]] = [name, cpu, mem] + + self.advanced = advanced + + + def __str__(self): + """ + Define format how to print + """ + out = "" + for pid in self.pids: + for stat in self.stats[pid][1:]: + out += str(stat.get_status()) + "\n" + return out + + + def start(self, pids=[]): + """ + Start monitoring of the process system usage. + @param pids: List of PIDs you intend to control. Use pids=[] to control + all defined PIDs. + """ + if pids == []: + pids = self.pids + + for pid in pids: + for stat in self.stats[pid][1:]: + stat.start() + + + def stop(self, pids=[]): + """ + Stop monitoring of the process system usage. + @param pids: List of PIDs you intend to control. Use pids=[] to control + all defined PIDs. + """ + if pids == []: + pids = self.pids + + for pid in pids: + for stat in self.stats[pid][1:]: + stat.stop() + + + def dump(self, pids=[]): + """ + Get the status of monitoring. + @param pids: List of PIDs you intend to control. Use pids=[] to control + all defined PIDs. + @return: + tuple([cpu load], [memory load]): + ([(PID1, (PID1_cpu_meas)), (PID2, (PID2_cpu_meas)), ...], + [(PID1, (PID1_mem_meas)), (PID2, (PID2_mem_meas)), ...]) + + PID1_cpu_meas: + average_values[], test_time, cont_meas_values[[]], time_step + PID1_mem_meas: + average_values[], test_time, cont_meas_values[[]], time_step + where average_values[] are the measured values (mem_free,swap,...) + which are described in SystemLoad.__init__()-FileFieldMonitor. + cont_meas_values[[]] is a list of average_values in the sampling + times. + """ + if pids == []: + pids = self.pids + + cpus = [] + memory = [] + for pid in pids: + stat = (pid, self.stats[pid][1].get_status()) + cpus.append(stat) + for pid in pids: + stat = (pid, self.stats[pid][2].get_status()) + memory.append(stat) + + return (cpus, memory) + + + def get_cpu_status_string(self, pids=[]): + """ + Convert status to string array. + @param pids: List of PIDs you intend to control. Use pids=[] to control + all defined PIDs. + @return: String format to table. + """ + if pids == []: + pids = self.pids + + headers = ["NAME", + ("%7s") % "PID", + ("%5s") % "USER", + ("%5s") % "SYS", + ("%5s") % "SUM"] + if self.advanced: + headers.extend(["MINFLT/IRQC", + "MAJFLT/SOFTIRQ"]) + headers.append(("%11s") % "TIME") + textstatus = [] + for pid in pids: + stat = self.stats[pid][1].get_status() + time = stat[1] + stat = stat[0] + textstatus.append(["%s" % self.stats[pid][0], + "%7s" % pid, + "%4.0f%%" % (stat[0] / time), + "%4.0f%%" % (stat[1] / time), + "%4.0f%%" % ((stat[0] + stat[1]) / time), + "%10.3fs" % time]) + if self.advanced: + textstatus[-1].insert(-1, "%11d" % stat[2]) + textstatus[-1].insert(-1, "%14d" % stat[3]) + + return matrix_to_string(textstatus, tuple(headers)) + + + def get_mem_status_string(self, pids=[]): + """ + Convert status to string array. + @param pids: List of PIDs you intend to control. Use pids=[] to control + all defined PIDs. + @return: String format to table. + """ + if pids == []: + pids = self.pids + + headers = ["NAME", + ("%7s") % "PID", + ("%8s") % "TOTAL/VMSIZE", + ("%8s") % "FREE/VMRSS", + ("%8s") % "BUFFERS/VMPEAK", + ("%8s") % "CACHED/VMSWAP", + ("%11s") % "TIME"] + textstatus = [] + for pid in pids: + stat = self.stats[pid][2].get_status() + time = stat[1] + stat = stat[0] + textstatus.append(["%s" % self.stats[pid][0], + "%7s" % pid, + "%10dMB" % (stat[0] / 1024), + "%8dMB" % (stat[1] / 1024), + "%12dMB" % (stat[2] / 1024), + "%11dMB" % (stat[3] / 1024), + "%10.3fs" % time]) + + return matrix_to_string(textstatus, tuple(headers)) + + def get_arch(run_function=run): """ Get the hardware architecture of the machine.