实时监控内存、CPU消耗工具 1.概述 通过工具,将能够根据需要监控CPU、内存状态。脚本默认每隔10s钟获取一次当前的cpu、内存状态并记录,设定的时间到了后,停止获取并开始分析数据,最后自动发出结果邮件。运行结果截图如下 2.使用介绍 2.1使用场景 在手工测试APP的时候,可同步监测系统、该app的性能 在做自动化测试的时候,可同步监测系统、指定的apps的性能 在做Monkey测试的时候,可同步监测系统、指定的apps的性能 2.2运行环境 2.2.1 .ubuntu系统,安装好python2.7、adb工具,pychart插件 2.2.2 手机需要支持top、procrank命令 2.3使用方法: 2.3.1根据需要修改systemMonitor.conf配置文件,配置项有: [runTime]#脚步运行时长,以分钟为单位 rumTime=1 [updateTime]#刷新间隔,默认为10秒 updateTime=10 [packageNameList]#过滤进程名,多个进程以逗号分隔 packageNameList=com.android.email,com.android.providers.calendar, [mailto_list]#收件人,以逗号分隔 mailto_list= ***@163.com [mailInfo]#邮件服务器参数 mailserver=*** user=*** password=********* me=guojianbiao@le.com 2.3.2运行脚本 python systemMonitor.py 3.实际代码 分为三个文件,下面将逐个展现。 3.1 systemMonitor.conf [runTime]#运行时长,以分钟为单位 rumTime=10 [updateTime]#刷新间隔,默认为10秒 updateTime=10 [packageNameList]#过滤进程名,多个进程以逗号分隔 packageNameList=com.android.providers.calendar, [mailto_list]#收件人,以逗号分隔 mailto_list=***@163.com [mailInfo]#邮件服务器参数 mailserver=*** user=*** password=*** me=***@163.com 3.2 systemMonitor.py #encoding:utf-8 import os import sys import datetime from threading import Thread import threading import subprocess import ConfigParser from analysisInfo import * from pychartdir import * import smtplib from email.mime.image import MIMEImage from email.MIMEText import MIMEText from email.MIMEMultipart import MIMEMultipart import time def getTime(): now = datetime.datetime.now() return now.strftime("%Y-%m-%d %H:%M:%S") def run_cmd(cmd): process = subprocess.Popen(cmd , shell = True, stdout=subprocess.PIPE) return process.stdout.read().strip() def timestamp_datetime(value): value = time.localtime(value) dt = time.strftime('%Y-%m-%d %H:%M:%S', value) return dt #获取设备型号 def get_model(): return run_cmd('adb shell getprop ro.product.model') #获取Android版本 def get_androidVersion(): return run_cmd('adb shell getprop ro.build.version.release') #获取CPU型号 def get_cpuInfo(): return run_cmd('adb shell getprop ro.product.cpu.abi') #获取系统编译版本增量 def get_buildVersionIncremental(): return run_cmd('adb shell getprop ro.build.version.incremental') #获取系统编译时间 def get_buildDate(): return run_cmd('adb shell getprop ro.build.date.utc') #生成表 #title:标题 #lable: #ytitle #data #chartpath #title_list #style def get_chart(title,label,ytitle,data,chartpath,title_list,style): color_list = [0x008800,0xff0000,0x8A2BE2,0xA52A2A,0x7FFF00,0xFF7F50,0xDC143C,0x8B008B,0xFF1493,0xFFD700] c = XYChart(1400, 600, 0xCCEEFF, 0x000000, 1) c.addTitle(title, "simsun.ttc", 18).setBackground(0xCCEEFF, 0x000000, glassEffect()) c.setPlotArea(50, 55, 1300, 500) c.addLegend(50, 28, 0, "arialbd.ttf", 10).setBackground(Transparent) c.xAxis().setLabels(label) c.yAxis().setTickDensity(30) c.xAxis().setLabelStyle("arialbd.ttf", 8) c.yAxis().setLabelStyle("arialbd.ttf", 8) c.xAxis().setWidth(2) c.yAxis().setWidth(2) c.yAxis().setTitle(ytitle, "arialbd.ttf", 10) layer = c.addLineLayer2() layer.setLineWidth(3) #c.addText(1280, 70,"最大值:111\n最小值:111").setAlignment(BottomRight) for i in range(0,len(data)): layer.addDataSet(data[i], color_list[i],title_list[i]).setDataSymbol(CircleShape, 1) #layer.setDataLabelStyle("",10) #layer.setDataLabelFormat(None) c.setDefaultFonts("simsun.ttc") c.makeChart(chartpath) #发送邮件 def send_mail_image(mailserver,user,password,me,mailto_list,title,bodyinfo,system_file_list,system_maxminavg,appInfo_list,app_file_list): msg = MIMEMultipart('related') msg['Subject']=title msg['From']=me msg['To']=';'.join(mailto_list) content = "" content+="" content+=" "content+="" content+="" content+="" content+=" "content+="运行时长(分):".decode('UTF-8').encode('GBK') + str(bodyinfo[9]) + "" content += " content+="开始时间:".decode('UTF-8').encode('GBK') + bodyinfo[0] + "" content += " content+="结束时间:".decode('UTF-8').encode('GBK') + bodyinfo[1] + "" content += " content+="刷新次数:".decode('UTF-8').encode('GBK') + str(bodyinfo[2]) + "" content += " content+="刷新频率(秒):".decode('UTF-8').encode('GBK') + str(bodyinfo[3]) + "" content += " content+="设备名称:".decode('UTF-8').encode('GBK') + str(bodyinfo[4]) + "" content += " content+="系统版本:".decode('UTF-8').encode('GBK') + str(bodyinfo[5]) + "" content += " content+="CPU信息:".decode('UTF-8').encode('GBK') + str(bodyinfo[6]) + "" content += " content+="系统编译增量:".decode('UTF-8').encode('GBK') + str(bodyinfo[7]) + "" content += " content+="系统编译日期:".decode('UTF-8').encode('GBK') + str(bodyinfo[8]) + "" content += " content += " content+="名词解释:".decode('UTF-8').encode('GBK') content += " content+="PSS:实际使用的物理内存".decode('UTF-8').encode('GBK') content += " content+="USS:进程独自占用的物理内存".decode('UTF-8').encode('GBK') content += " content += " content+="System性能趋势:".decode('UTF-8').encode('GBK') content+="" + system_maxminavg.decode('UTF-8').encode('GBK') + "" content += " for i in system_file_list: pic_name = i.split(sep)[-1] content += " content += " content += " for i in range(0,len(appInfo_list)): content += " content+="AppInfo:" + appInfo_list[i].decode('UTF-8').encode('GBK') + "" content += " for j in app_file_list[i]: pic_name = j.split(sep)[-1] content += " content += " content += " content+="" content+="" msg.attach(MIMEText(content,_subtype='html',_charset='gb2312')) for i in system_file_list: file_name = i.split(sep)[-1] fp = open(i,'rb') img = MIMEImage(fp.read()) img.add_header('Content-ID',file_name) msg.attach(img) for i in app_file_list: for j in i: file_name = j.split(sep)[-1] fp = open(j,'rb') img = MIMEImage(fp.read()) img.add_header('Content-ID',file_name) msg.attach(img) try: ott_mail=smtplib.SMTP() ott_mail.connect(mailserver) ott_mail.login(user, password) ott_mail.sendmail(me,mailto_list,msg.as_string()) ott_mail.close() return True except Exception,e: print e return False #同步获取cpu线程 #path:写cpu信息的文件路径 #count:获取次数 #updateTime:刷新次数 class CpuThread(threading.Thread): def __init__(self,path,count,updateTime): threading.Thread.__init__(self) self.thread_stop = False self.path = path self.count = count self.updateTime = int(updateTime) def run(self): if not self.thread_stop: print "Cpu thread is start" self.output = open(self.path, 'w+') for i in range(self.count): print "Cpu thread run count:" + str(i) + " "+time.strftime('%Y-%m-%d %X', time.localtime( time.time()))+"\n" self.output.write(run_cmd("adb shell top -n 1 -d " + str(self.updateTime)) + "\n") #time.sleep(self.updateTime) self.output.close() print "Cpu thread is stop" def stop(self): self.thread_stop = True #同步获取mem线程 #path:写mem信息的文件路径 #count:获取次数 #updateTime:刷新次数 class MemThread(threading.Thread): def __init__(self,path,count,updateTime): threading.Thread.__init__(self) self.thread_stop = False self.path = path self.count = count self.updateTime = int(updateTime) def run(self): if not self.thread_stop: print "Mem thread is start" self.output = open(self.path, 'w+') for i in range(self.count): print "Mem thread run count:" + str(i) + " "+time.strftime('%Y-%m-%d %X', time.localtime( time.time()))+"\n" self.output.write(run_cmd("adb shell procrank") + "\n") time.sleep(self.updateTime) self.output.close() print "Mem thread is stop" def stop(self): self.thread_stop = True def analyse_log_and_sendmail(path,sep,startTime,endTime,getCount,updateTime,model,androidVersion,cpuInfo,buildVersionIncremental,buildDate,runTime,packageNameList,mailserver,user,password,me,mailto_list): system_file_list = [] system_cpu_png = path + sep + "system_cpu.png" system_mem_png = path + sep + "system_mem.png" system_cpu = analysisSystemCPU(cpu_log_path) x_list = [] x_list.append(startTime) for i in range(0,len(system_cpu[0]) - 2): x_list.append("") x_list.append(endTime) get_chart("System_CPU Trend",x_list,"The numerical",[system_cpu[0],system_cpu[1]],system_cpu_png,['User cpu(%)','System cpu(%)'],"{value|0}%") system_mem = analysisSystemMEM(mem_log_path) x_list = [] x_list.append(startTime) for i in range(0,len(system_mem) - 2): x_list.append("") x_list.append(endTime) get_chart("System_MEM Trend",x_list,"The numerical",[system_mem],system_mem_png,['mem(M)'],"{value|2}") system_maxminavg = " + " + " system_file_list.append(system_cpu_png) system_file_list.append(system_mem_png) bodyinfo = [startTime,endTime,getCount,updateTime,model,androidVersion,cpuInfo,buildVersionIncremental,str(buildDate),runTime] appInfo_list = [] cpumemChatFile_list = [] #分析日志 for packageName in packageNameList: cpu_png = path + sep + packageName + "_cpu.png" mem_png = path + sep + packageName + "_mem.png" cpu_list = analysisAppCPU(cpu_log_path,packageName) if len(cpu_list) == 0: continue x_list = [] x_list.append(startTime) for i in range(0,len(cpu_list) - 2): x_list.append("") x_list.append(endTime) get_chart(packageName + "_CPU Trend",x_list,"The numerical",[cpu_list],cpu_png,['cpu(%)'],"{value|0}%") mem_list = analysisAppMEM(mem_log_path,packageName) x_list = [] x_list.append(startTime) for i in range(0,len(mem_list) - 2): x_list.append("") x_list.append(endTime) get_chart(packageName + "_PSS_USS Trend",x_list,"The numerical",[mem_list[2],mem_list[3]],mem_png,['pss(M)','uss(M)'],"{value|2}") appInfo_list.append(packageName + " + " + " cpumemChatFile_list.append([cpu_png,mem_png]) #print appInfo_list #print cpumemChatFile_list print "send mail!!!" print send_mail_image(mailserver,user,password,me,mailto_list,model + "-System性能测试报告-" + startTime,bodyinfo,system_file_list,system_maxminavg,appInfo_list,cpumemChatFile_list) if __name__=='__main__': sep = os.path.sep #获取系统分隔符 path = sys.path[0] #获取脚本路径 conf_path = path + sep + "systemMonitor.conf" #监控配置文件 cpu_log_path = path + sep + "monitor_cpu.txt" #cpu日志文件 mem_log_path = path + sep + "monitor_mem.txt" #mem日志文件 #读取配置文件 cf = ConfigParser.ConfigParser() cf.read(conf_path) runTime = cf.get("runTime","rumTime") updateTime = cf.get("updateTime","updateTime") packageNameList = cf.get("packageNameList","packageNameList").split(",") mailserver = cf.get("mailInfo","mailserver") user = cf.get("mailInfo","user") password = cf.get("mailInfo","password") me = cf.get("mailInfo","me") mailto_list = cf.get("mailto_list","mailto_list").split(',') #检查配置文件是否存在 if not os.path.exists(conf_path): print "systemMonitor.conf is null" sys.exit() #生成cpu日志文件,如果存在,则先删除 if os.path.exists(cpu_log_path): os.remove(cpu_log_path) #生成mem日志文件,如果存在,则先删除 if os.path.exists(mem_log_path): os.remove(mem_log_path) #删除当前目录下的.png文件 for parent,dirnames,filenames in os.walk(path): for filename in filenames: if filename[-4:] == ".png": os.remove(os.path.join(parent,filename)) #检查环境配置 if runTime == "" or runTime == 0: print "runTime is null" sys.exit() if updateTime == "" or updateTime == 0: print "updateTime is null" sys.exit() if packageNameList == "": print "packageNameList is null" sys.exit() #获取设备信息 model = get_model() androidVersion = get_androidVersion() cpuInfo = get_cpuInfo() buildVersionIncremental = get_buildVersionIncremental() buildDate = timestamp_datetime(float(get_buildDate())) #计算top命令-n参数的值,即刷新多少次 getCount = int(runTime) * 60/int(updateTime) print "runTime:" + runTime print "updateTime:" + updateTime print "count:" + str(getCount) startTime = getTime() print "startTime:" + startTime threads = [] #开始执行获取cpu线程 t1 = CpuThread(cpu_log_path,getCount,updateTime) #开始执行获取mem线程 t2 = MemThread(mem_log_path,getCount,updateTime) threads.append(t2) threads.append(t1) #开始执行所有线程 for t in threads: t.start() #等待所有线程结束 for t in threads: t.join() endTime = getTime() print "endTime:" + endTime analyse_log_and_sendmail(path,sep,startTime,endTime,getCount,updateTime,model,androidVersion,cpuInfo,buildVersionIncremental,str(buildDate),runTime,packageNameList,mailserver,user,password,me,mailto_list) 3.3 analysisInfo.py #encoding:utf-8 import subprocess import threading import time #分析系统CPU def analysisSystemCPU(filePath): fp = open(filePath) try: lines = fp.readlines() finally: fp.close() cpu_user_list = [] cpu_system_list = [] for line in lines: if "User" in line and "System" in line and "IOW" in line and "IRQ" in line: line_split = line.strip().rstrip('\r').lstrip().split(' ') cpu_user_list.append(int(line_split[1].replace('%,',''))) cpu_system_list.append(int(line_split[3].replace('%,',''))) return cpu_user_list,cpu_system_list #分析APP CPU信息 def analysisAppCPU(filePath,packageName): fp = open(filePath) try: lines = fp.readlines() finally: fp.close() cpu_list = [] for line in lines: if packageName in line: line_split = line.strip().rstrip('\r').lstrip().split(' ') for j in line_split: if "%" in j: cpu_list.append(int(j.replace('%',''))) return cpu_list #分析系统MEM信息 def analysisSystemMEM(filePath): fp = open(filePath) try: lines = fp.readlines() finally: fp.close() mem_system_list = [] for line in lines: if "total" in line and "free" in line and "buffers" in line and "cached" in line: line_split = line.strip().rstrip('\r').lstrip().split(' ') system_mem = int(line_split[1].replace('K','')) - int(line_split[3].replace('K','')) mem_system_list.append(round(system_mem/float(1024),2)) return mem_system_list #分析APP MEM信息 def analysisAppMEM(filePath,packageName): fp = open(filePath) try: lines = fp.readlines() finally: fp.close() vss_list = [] rss_list = [] pss_list = [] uss_list = [] result_list = [] count = 0 for line in lines: if packageName in line: line_split = line.strip().rstrip('\r').lstrip().split(' ') temp_list = [] for j in line_split: if "K" in j: temp_list.append(j.replace('K','')) count += 1 result_list.append(temp_list) if count % 4 == 0: for i in result_list: vss_list.append(round(float(i[0])/float(1024),2)) rss_list.append(round(float(i[1])/float(1024),2)) pss_list.append(round(float(i[2])/float(1024),2)) uss_list.append(round(float(i[3])/float(1024),2)) return vss_list,rss_list,pss_list,uss_list else: return vss_list,rss_list,pss_list,uss_list def analysisInfo_bak(filePath,packageName): fp = open(filePath) lines = fp.readlines() fp.close() cpu_list = [] vss_list = [] rss_list = [] cpu_col = 0 vss_col = 0 rss_col = 0 for line in lines: if packageName in line: line_split = line.strip().rstrip('\r').lstrip().split(' ') for j in line_split: if "%" in j: cpu_col = line_split.index(j) if "K" in j: vss_col = line_split.index(j) break for j in line_split[vss_col + 1:]: if "K" in j: rss_col = line_split.index(j) break break for line in lines: if packageName in line: line_split = line.strip().rstrip('\r').lstrip().split(' ') cpu_list.append(line_split[cpu_col].replace('%','')) vss_list.append(int(line_split[vss_col].replace('K',''))/float(1024)) rss_list.append(line_split[rss_col].replace('K','')) return cpu_list,vss_list,rss_list def run_cmd(cmd): process = subprocess.Popen(cmd , shell = True, stdout=subprocess.PIPE) return process.stdout.read().strip() if __name__=='__main__': #print analysisSystemMEM("D:\monitor_mem.txt") #print analysisSystemCPU("D:\monitor_cpu.txt") #print analysisAppCPU("D:\monitor_cpu.txt","com.bestv.ott") #print analysisAppMEM("D:\monitor_mem.txt","com.bestv.ott") pass |