(任意事件)
30 | '''
31 | #动作百分比配置,合计100%
32 | self.events = {"--pct-touch":35, "--pct-motion":15, "--pct-trackball":15,"--pct-nav":7,"--pct-majornav":8,
33 | "--pct-syskeys":10,"--pct-appswitch":5, "--pct-anyevent":5,"--pct-flip":0}
34 |
35 |
36 | def generateEventStr(self):
37 | "生成action字符串"
38 | eventStr = ""
39 | for key in self.events:
40 | eventStr = eventStr + " %s %s"%(key, self.events[key])
41 | return eventStr
42 |
43 | def generateCommand(self):
44 | "生成monkey命令行"
45 | seed = randint(100000000000, 200000000000)#随机事件种子值
46 |
47 | command = "adb -s %s shell monkey -p %s -s %d -v --throttle %s %s --ignore-crashes --ignore-timeouts\
48 | --ignore-security-exceptions --ignore-native-crashes --monitor-native-crashes "%(self.device_id,self.pkgName, seed, self.throttle, self.generateEventStr())
49 |
50 | command = command + str(self.runNum)
51 | return command
52 |
53 | @staticmethod
54 | def terminateMonkey(deviceID):
55 | def getMonekyPid():
56 | top = os.popen("adb -s %s shell top -n 1"%deviceID).read()
57 | for topItem in top.split("\n"):
58 | if "com.android.commands.monkey" in topItem:
59 | return topItem.split()[0]
60 | pid = getMonekyPid()
61 | while pid:
62 | os.system("adb -s %s shell kill -9 %s"%(deviceID,pid))
63 | pid = getMonekyPid()
64 |
65 | def startMonkey(self):
66 | command = self.generateCommand()
67 | print(command)
68 | os.system("%s >> %s"%(command, os.path.join(self.logPath, "monkey.log")))
69 |
--------------------------------------------------------------------------------
/MonkeyTest/monkey.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/MonkeyTest/monkey.pyc
--------------------------------------------------------------------------------
/MonkeyTest/utils.py:
--------------------------------------------------------------------------------
1 | #coding=utf-8
2 |
3 | import os
4 | import zipfile
5 |
6 |
7 | def clearLog(deviceID):
8 | os.system("adb -s %s shell logcat -c"%deviceID)
9 |
10 | def getLog(logPath,deviceID):
11 | logcatPath = os.path.join(logPath, "logcat.log")
12 | os.system("adb -s %s shell logcat -d > %s"%(deviceID,logcatPath))
13 |
14 | def dumpState(logPath,deviceID):
15 | dumpStateLogPath = os.path.join(logPath, "dumpState.log")
16 | os.system("adb -s %s shell dumpstate > %s"%(deviceID,dumpStateLogPath))
17 |
18 | def getTraceData(logPath,deviceID):
19 | os.system("adb -s %s pull /data/anr %s"%(deviceID,logPath))
20 |
21 | #可能获取到多个设备
22 | def getDeviceInfo():
23 | return os.popen("adb shell getprop ro.build.fingerprint").read().strip()
24 |
25 | def compressFolder(folderPath):
26 |
27 | f = zipfile.ZipFile('abc.zip', 'w')
28 | for item in os.listdir(folderPath):
29 | f.write(os.path.join(folderPath, item))
30 | f.close()
31 |
32 | def forceStop(packageName,deviceID):
33 | os.system("adb -s %s shell am force-stop %s"%(deviceID,packageName))
34 | cmd1 = 'adb -s %s shell ps | grep %s'%(deviceID,packageName)
35 | cmd2 = 'adb -s %s shell ps | find %s'%(deviceID,packageName)
36 | result = os.popen(cmd1).read()
37 | if result is None or result == "":
38 | result = os.popen(cmd2).read()
39 | if result is not None and result != "":
40 | lines = result.split("\n")
41 | for i in xrange(len(lines)):
42 | infos = lines[i].split()
43 | if infos[8]==packageName:
44 | pid = infos[1]
45 | break
46 | os.system('adb -s %s shell su -c "kill -9 %s"'%(deviceID,pid))
47 |
48 | def reboot(deviceID=None):
49 | if deviceID is None:
50 | os.system("adb reboot")
51 | else:
52 | os.system("adb -s %s reboot"%deviceID)
53 |
54 |
--------------------------------------------------------------------------------
/MonkeyTest/utils.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/MonkeyTest/utils.pyc
--------------------------------------------------------------------------------
/Report/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Report/__init__.py
--------------------------------------------------------------------------------
/Report/__init__.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Report/__init__.pyc
--------------------------------------------------------------------------------
/Report/base.py:
--------------------------------------------------------------------------------
1 | # -* - coding: UTF-8 -* -
2 |
3 | import re
4 | import operator
5 | import ast
6 |
7 | VAR_FRAGMENT = 0
8 | OPEN_BLOCK_FRAGMENT = 1
9 | CLOSE_BLOCK_FRAGMENT = 2
10 | TEXT_FRAGMENT = 3
11 |
12 | VAR_TOKEN_START = '{{'
13 | VAR_TOKEN_END = '}}'
14 | BLOCK_TOKEN_START = '{%'
15 | BLOCK_TOKEN_END = '%}'
16 |
17 | TOK_REGEX = re.compile(r"(%s.*?%s|%s.*?%s)" % (
18 | VAR_TOKEN_START,
19 | VAR_TOKEN_END,
20 | BLOCK_TOKEN_START,
21 | BLOCK_TOKEN_END
22 | ))
23 |
24 | WHITESPACE = re.compile('\s+')
25 |
26 | operator_lookup_table = {
27 | '<': operator.lt,
28 | '>': operator.gt,
29 | '==': operator.eq,
30 | '!=': operator.ne,
31 | '<=': operator.le,
32 | '>=': operator.ge
33 | }
34 |
35 |
36 | class TemplateError(Exception):
37 | pass
38 |
39 |
40 | class TemplateContextError(TemplateError):
41 |
42 | def __init__(self, context_var):
43 | self.context_var = context_var
44 |
45 | def __str__(self):
46 | return "cannot resolve '%s'" % self.context_var
47 |
48 |
49 | class TemplateSyntaxError(TemplateError):
50 |
51 | def __init__(self, error_syntax):
52 | self.error_syntax = error_syntax
53 |
54 | def __str__(self):
55 | return "'%s' seems like invalid syntax" % self.error_syntax
56 |
57 |
58 | def eval_expression(expr):
59 | try:
60 | return 'literal', ast.literal_eval(expr)
61 | except ValueError, SyntaxError:
62 | return 'name', expr
63 |
64 |
65 | def resolve(name, context):
66 | if name.startswith('..'):
67 | context = context.get('..', {})
68 | name = name[2:]
69 | try:
70 | for tok in name.split('.'):
71 | context = context[tok]
72 | return context
73 | except KeyError:
74 | raise TemplateContextError(name)
75 |
76 |
77 | class _Fragment(object):
78 | def __init__(self, raw_text):
79 | self.raw = raw_text
80 | self.clean = self.clean_fragment()
81 |
82 | def clean_fragment(self):
83 | if self.raw[:2] in (VAR_TOKEN_START, BLOCK_TOKEN_START):
84 | return self.raw.strip()[2:-2].strip()
85 | return self.raw
86 |
87 | @property
88 | def type(self):
89 | raw_start = self.raw[:2]
90 | if raw_start == VAR_TOKEN_START:
91 | return VAR_FRAGMENT
92 | elif raw_start == BLOCK_TOKEN_START:
93 | return CLOSE_BLOCK_FRAGMENT if self.clean[:3] == 'end' else OPEN_BLOCK_FRAGMENT
94 | else:
95 | return TEXT_FRAGMENT
96 |
97 |
98 | class _Node(object):
99 | creates_scope = False
100 |
101 | def __init__(self, fragment=None):
102 | self.children = []
103 | self.process_fragment(fragment)
104 |
105 | def process_fragment(self, fragment):
106 | pass
107 |
108 | def enter_scope(self):
109 | pass
110 |
111 | def render(self, context):
112 | pass
113 |
114 | def exit_scope(self):
115 | pass
116 |
117 | def render_children(self, context, children=None):
118 | if children is None:
119 | children = self.children
120 | def render_child(child):
121 | child_html = child.render(context)
122 | return '' if not child_html else str(child_html)
123 | return ''.join(map(render_child, children))
124 |
125 |
126 | class _ScopableNode(_Node):
127 | creates_scope = True
128 |
129 | class _Root(_Node):
130 | def render(self, context):
131 | return self.render_children(context)
132 |
133 |
134 | class _Variable(_Node):
135 | def process_fragment(self, fragment):
136 | self.name = fragment
137 |
138 | def render(self, context):
139 | return resolve(self.name, context)
140 |
141 |
142 | class _Each(_ScopableNode):
143 | def process_fragment(self, fragment):
144 | try:
145 | _, it = WHITESPACE.split(fragment, 1)
146 | self.it = eval_expression(it)
147 | except ValueError:
148 | raise TemplateSyntaxError(fragment)
149 |
150 | def render(self, context):
151 | items = self.it[1] if self.it[0] == 'literal' else resolve(self.it[1], context)
152 | def render_item(item):
153 | return self.render_children({'..': context, 'it': item})
154 | return ''.join(map(render_item, items))
155 |
156 |
157 | class _If(_ScopableNode):
158 | def process_fragment(self, fragment):
159 | bits = fragment.split()[1:]
160 | if len(bits) not in (1, 3):
161 | raise TemplateSyntaxError(fragment)
162 | self.lhs = eval_expression(bits[0])
163 | if len(bits) == 3:
164 | self.op = bits[1]
165 | self.rhs = eval_expression(bits[2])
166 |
167 | def render(self, context):
168 | lhs = self.resolve_side(self.lhs, context)
169 | if hasattr(self, 'op'):
170 | op = operator_lookup_table.get(self.op)
171 | if op is None:
172 | raise TemplateSyntaxError(self.op)
173 | rhs = self.resolve_side(self.rhs, context)
174 | exec_if_branch = op(lhs, rhs)
175 | else:
176 | exec_if_branch = operator.truth(lhs)
177 | if_branch, else_branch = self.split_children()
178 | return self.render_children(context,
179 | self.if_branch if exec_if_branch else self.else_branch)
180 |
181 | def resolve_side(self, side, context):
182 | return side[1] if side[0] == 'literal' else resolve(side[1], context)
183 |
184 | def exit_scope(self):
185 | self.if_branch, self.else_branch = self.split_children()
186 |
187 | def split_children(self):
188 | if_branch, else_branch = [], []
189 | curr = if_branch
190 | for child in self.children:
191 | if isinstance(child, _Else):
192 | curr = else_branch
193 | continue
194 | curr.append(child)
195 | return if_branch, else_branch
196 |
197 |
198 | class _Else(_Node):
199 | def render(self, context):
200 | pass
201 |
202 |
203 | class _Call(_Node):
204 | def process_fragment(self, fragment):
205 | try:
206 | bits = WHITESPACE.split(fragment)
207 | self.callable = bits[1]
208 | self.args, self.kwargs = self._parse_params(bits[2:])
209 | except ValueError, IndexError:
210 | raise TemplateSyntaxError(fragment)
211 |
212 | def _parse_params(self, params):
213 | args, kwargs = [], {}
214 | for param in params:
215 | if '=' in param:
216 | name, value = param.split('=')
217 | kwargs[name] = eval_expression(value)
218 | else:
219 | args.append(eval_expression(param))
220 | return args, kwargs
221 |
222 | def render(self, context):
223 | resolved_args, resolved_kwargs = [], {}
224 | for kind, value in self.args:
225 | if kind == 'name':
226 | value = resolve(value, context)
227 | resolved_args.append(value)
228 | for key, (kind, value) in self.kwargs.iteritems():
229 | if kind == 'name':
230 | value = resolve(value, context)
231 | resolved_kwargs[key] = value
232 | resolved_callable = resolve(self.callable, context)
233 | if hasattr(resolved_callable, '__call__'):
234 | return resolved_callable(*resolved_args, **resolved_kwargs)
235 | else:
236 | raise TemplateError("'%s' is not a callable" % self.callable)
237 |
238 |
239 | class _Text(_Node):
240 | def process_fragment(self, fragment):
241 | self.text = fragment
242 |
243 | def render(self, context):
244 | return self.text
245 |
246 |
247 | class Compiler(object):
248 | def __init__(self, template_string):
249 | self.template_string = template_string
250 |
251 | def each_fragment(self):
252 | for fragment in TOK_REGEX.split(self.template_string):
253 | if fragment:
254 | yield _Fragment(fragment)
255 |
256 | def compile(self):
257 | root = _Root()
258 | scope_stack = [root]
259 | for fragment in self.each_fragment():
260 | if not scope_stack:
261 | raise TemplateError('nesting issues')
262 | parent_scope = scope_stack[-1]
263 | if fragment.type == CLOSE_BLOCK_FRAGMENT:
264 | parent_scope.exit_scope()
265 | scope_stack.pop()
266 | continue
267 | new_node = self.create_node(fragment)
268 | if new_node:
269 | parent_scope.children.append(new_node)
270 | if new_node.creates_scope:
271 | scope_stack.append(new_node)
272 | new_node.enter_scope()
273 | return root
274 |
275 | def create_node(self, fragment):
276 | node_class = None
277 | if fragment.type == TEXT_FRAGMENT:
278 | node_class = _Text
279 | elif fragment.type == VAR_FRAGMENT:
280 | node_class = _Variable
281 | elif fragment.type == OPEN_BLOCK_FRAGMENT:
282 | cmd = fragment.clean.split()[0]
283 | if cmd == 'each':
284 | node_class = _Each
285 | elif cmd == 'if':
286 | node_class = _If
287 | elif cmd == 'else':
288 | node_class = _Else
289 | elif cmd == 'call':
290 | node_class = _Call
291 | if node_class is None:
292 | raise TemplateSyntaxError(fragment)
293 | return node_class(fragment.clean)
294 |
295 |
296 | class Template(object):
297 | def __init__(self, contents):
298 | self.contents = contents
299 | self.root = Compiler(contents).compile()
300 |
301 | def render(self, **kwargs):
302 | return self.root.render(kwargs)
303 |
--------------------------------------------------------------------------------
/Report/generateReport.py:
--------------------------------------------------------------------------------
1 | # -* - coding: UTF-8 -* -
2 |
3 | import os
4 | from Report import reportWritor
5 | import time
6 | from ResMonitor.NetworkTraffic import networkTraffic
7 |
8 |
9 | report_dir = os.path.join(os.path.dirname(__file__), 'results')
10 | report_dir = "D:/eclipse/workspace/MobilePerformance/logs/task_0304113023"
11 |
12 |
13 | def formatStr1(d):
14 | "{'duration': 2, 'crashCount': '0', 'anrCount': '0', 'pkgName': '', 'deviceID': 'HC52SWME0349'}"
15 |
16 | s = "此次测试时长%d分钟,测试设备ID%s,其中crash数量%d个,ANR数量%d个。"%(d["duration"],d["deviceID"],int(d['crashCount']),int(d['anrCount']))
17 | return s
18 |
19 | def formatStr2(d):
20 | "{'count': 10, 'max': 2369ms, 'avg': 1929ms, 'min': 1802ms}"
21 | s = "此次测试共执行%d次,其中最大时间为 %d ms,最小时间为 %d ms,平均时间(取出最大值和最小值)为 %d ms"%(d['count'],int(d['max']),int(d['min']),int(d['avg']))
22 | return s
23 |
24 |
25 | def getAvgCpuAndMemory(log_dir):
26 | memory_log_dir = os.path.join(log_dir,'memory.log')
27 | #"C:\\Users\\zhaowei\\workspace\\MobilePerformance\\logs\\task_0906144920\\memory.log"
28 | f = open(memory_log_dir, "r")
29 | cpuDatas=[]
30 | memDatas=[]
31 | for line in f:
32 | if line.strip():
33 | ss = line.split()
34 | index = 2
35 | for i in range(len(ss)):
36 | if "%" in ss[i]:
37 | index = i
38 | break
39 | cpuDatas.append(int(ss[index][0:-1]))
40 | memDatas.append(int(ss[index+4][0:-1]))
41 | cpuDatas.sort()
42 | memDatas.sort()
43 | cpus = cpuDatas[1:-1]
44 | memorys = memDatas[1:-1]
45 | avgCpu = round(float(sum(cpus))/len(cpus),2)
46 | avgMem = round(float(sum(memorys))/len(memorys)/1024,2)
47 | return [avgCpu,avgMem]
48 |
49 |
50 | def generateReportEx(resultDict,report_dir):
51 | "生成报告"
52 | "resultList-测试结果数据"
53 |
54 | # resultDict = {'testItems': {'startTime': {'count': 3, 'max': 1877L, 'avg': 1839L, 'min': 1781L}}, 'endTime': '2016/03/04 14:42:27', 'startTime': '2016/03/04 14:42:11'}
55 | start_time = resultDict["startTime"]
56 | end_time = resultDict["endTime"]
57 | use_time = resultDict["useTime"]
58 | avgCpuAndMem = getAvgCpuAndMemory(report_dir)
59 | monkeyResult = None
60 | startTimeResult = None
61 |
62 | if resultDict["testItems"].has_key("monkeyTest"):
63 | monkeyResult = resultDict["testItems"]["monkeyTest"]
64 | if resultDict["testItems"].has_key("startTime"):
65 | startTimeResult = resultDict["testItems"]["startTime"]
66 |
67 | testItemStr = "测试内容包括:"
68 | if len(resultDict["testItems"]) == 0:
69 | testItemStr += "手工操作。"
70 | else:
71 | testItemStr += ",".join(resultDict["testItems"].keys())
72 | testItemStr = testItemStr.replace("monkeyTest", "monkey测试")
73 | testItemStr = testItemStr.replace("startTime", "启动时间测试")
74 |
75 |
76 | report = reportWritor.Report(report_dir)
77 |
78 | #测试结果总结部分--begin
79 | report.write_line('')
80 | report.write_line('
Hi,all:
本次测试完成,测试开始时间:%s,结束时间:%s,共计:%s秒。%s。
'%(start_time,end_time,use_time,testItemStr))
81 | report.write_line('
')
82 | #测试结果总结部分--end
83 |
84 | #测试结果详细部分--begin
85 |
86 | #Monkey测试部分
87 | if monkeyResult is not None:
88 | report.write_line('')
89 | report.write_line('
Monkey测试结果:
%s
'%formatStr1(monkeyResult))
90 | report.write_line('
')
91 | #启动时间部分
92 | if startTimeResult is not None:
93 | report.write_line('')
94 | report.write_line('
启动时间测试结果:
%s
'%formatStr2(startTimeResult))
95 | report.write_line('
')
96 | #资源图表
97 | print os.path.join(report_dir,"Test_cpuInfo.png")
98 | if os.path.exists(os.path.join(report_dir,"Test_cpuInfo.png")):
99 |
100 | report.write_line('')
101 | report.write_line('
CPU使用统计(%):
')
102 | report.write_line('
本次测试CPU的平均值(取出最大值和最小值)为(%):'+str(avgCpuAndMem[0])+'
')
103 | report.write_line('

')
104 | report.write_line('
')
105 |
106 | if os.path.exists(os.path.join(report_dir,"Test_MemoryInfo.png")):
107 | report.write_line('')
108 | report.write_line('
内存使用统计(MB/s):
')
109 | report.write_line('
本次测试内存的平均值(取出最大值和最小值)为(MB/s):'+str(avgCpuAndMem[1])+'
')
110 | report.write_line('

')
111 | report.write_line('
')
112 |
113 | if os.path.exists(os.path.join(report_dir,"Test_networkTraffic.png")):
114 | report.write_line('')
115 | report.write_line('
流量使用统计(KB/s):
')
116 | report.write_line('
本次测试的总流量为(KB):'+str(round((networkTraffic.total_bytes/1024.0),2))+'KB
')
117 | networkTraffic.total_bytes = 0
118 | report.write_line('

')
119 | report.write_line('
')
120 |
121 | if os.path.exists(os.path.join(report_dir,"Test_powerInfo.png")):
122 | report.write_line('')
123 | report.write_line('
电量使用统计(%):
')
124 | report.write_line('

')
125 | report.write_line('
')
126 | #测试结果详细部分--end
127 |
128 | report.write_closing_html()
129 | print "报告生成完毕。".decode("utf-8")
130 | return report.fn
131 |
132 | def getReportConent(fileName=None):
133 | if fileName is not None:
134 | reportFile = os.path.join(report_dir,fileName)
135 | return open(reportFile).read()
136 | return None
137 |
138 |
139 | if __name__ == "__main__":
140 | print getAvgCpuAndMemory("C:\\Users\\zhaowei\\workspace\\MobilePerformance\\logs\\task_0906144920")
141 |
142 |
--------------------------------------------------------------------------------
/Report/generateReport.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Report/generateReport.pyc
--------------------------------------------------------------------------------
/Report/reportWritor.py:
--------------------------------------------------------------------------------
1 | # -* - coding: UTF-8 -* -
2 |
3 | import os,sys
4 | import time
5 |
6 |
7 | class Report(object):
8 |
9 |
10 | def __init__(self, results_dir):
11 | self.results_dir = results_dir
12 | timeStr = time.strftime("%Y%m%d%H%M%S", time.localtime())
13 | self.fn = os.path.join(results_dir,'result_%s.html'%timeStr)
14 | if not os.path.exists(self.fn):
15 | f = open(self.fn,'w')
16 | f.close()
17 | self.write_head_html()
18 |
19 | def write_line(self, line):
20 | with open(self.fn, 'a') as f:
21 | f.write('%s\n' % line)
22 |
23 |
24 | def write_head_html(self):
25 | with open(self.fn, 'w') as f:
26 | f.write("""\
27 |
29 |
30 |
31 | App性能测试报告(Android)
32 |
33 |
34 |
83 |
84 |
85 | """)
86 |
87 |
88 | def write_closing_html(self):
89 | with open(self.fn, 'a') as f:
90 | f.write("""\
91 |
92 |
93 | """)
94 |
--------------------------------------------------------------------------------
/Report/reportWritor.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/Report/reportWritor.pyc
--------------------------------------------------------------------------------
/ResMonitor/MemoryCPUMonitor.py:
--------------------------------------------------------------------------------
1 | #-*- coding: UTF-8 -*-
2 |
3 | import threading
4 | import os
5 | import time
6 | import subprocess
7 | import sys
8 | import signal
9 | import re
10 | from Common import const
11 | from Common.userConf import UserConf
12 |
13 | class memoryCPUMonitor(threading.Thread):
14 | over = False
15 |
16 | def __init__(self,logFolder,packageName,caseID=None,deviceID=None):
17 | threading.Thread.__init__(self)
18 | self.over = False
19 | self.package = packageName
20 | self.logFolder = logFolder
21 |
22 | if caseID is None:
23 | self.picPre = "Test"
24 | self.logFile = os.path.join(self.logFolder,"memory.log")
25 | else:
26 | self.picPre = caseID
27 | self.logFile = os.path.join(self.logFolder,"%s_memory.log"%caseID)
28 | if deviceID is None:
29 | self.cmdStr = 'adb shell "top -d 1 -s cpu | grep %s$" > "%s"'%(self.package,self.logFile )#间隔1秒获取一次
30 | else:
31 | self.cmdStr = 'adb -s %s shell "top -d 1 -s cpu | grep %s$" > "%s"'%(deviceID,self.package,self.logFile)
32 |
33 | self.over = False
34 |
35 | @staticmethod
36 | def terminate():
37 | memoryCPUMonitor.over = True
38 |
39 |
40 | def run(self):
41 | "开始执行"
42 | print "CPU/Memory监控启动...".decode("utf-8")
43 | print self.cmdStr
44 | sub_process = subprocess.Popen(self.cmdStr,shell=True)
45 | memoryCPUMonitor.over = False
46 | while not memoryCPUMonitor.over:
47 | time.sleep(1)
48 |
49 | else:
50 | time.sleep(10)
51 | print "数据收集结束。".decode("utf-8")
52 | os.system("taskkill /F /IM adb.exe")
53 | time.sleep(2)
54 |
55 | #处理文件路径中带空格的情况
56 | if " " in const.jarFile:
57 | cmdStr = 'java -jar "'+const.jarFile+'" "'+self.logFile+'" '+self.picPre+' "'+self.logFolder+'" 0 '+UserConf.packageName
58 | else:
59 | cmdStr = 'java -jar '+const.jarFile+' '+self.logFile+' '+self.picPre+' '+self.logFolder+' 0 '+UserConf.packageName
60 | if sys.platform.startswith("win"):
61 | subprocess.call(cmdStr)
62 | elif sys.platform.startswith('linux'):
63 | subprocess.call(cmdStr,shell=True)
64 | print "制图完毕。".decode("utf-8")
65 |
66 |
67 |
68 | if __name__ == "__main__":
69 |
70 | print "over"
--------------------------------------------------------------------------------
/ResMonitor/MemoryCPUMonitor.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/ResMonitor/MemoryCPUMonitor.pyc
--------------------------------------------------------------------------------
/ResMonitor/NetworkTraffic.py:
--------------------------------------------------------------------------------
1 | #-*- coding: UTF-8 -*-
2 | '''
3 | Created on 2016-2-25
4 |
5 | @author: zhaowei
6 | '''
7 | import os
8 | import platform
9 | import threading
10 | import time
11 | import sys
12 | import subprocess
13 | from Common import const
14 | from Common.userConf import UserConf
15 |
16 |
17 | class networkTraffic(threading.Thread):
18 | thread_stop = False
19 | total_bytes = 0
20 | def __init__(self,logFolder,deviceID,interval=1):
21 | threading.Thread.__init__(self)
22 | self.deviceNo = deviceID
23 | self.picPre = "Test"
24 | self.logFolder = logFolder
25 | self.pid = self.__getPid()
26 | self.uid = self.getAppUID()
27 | self.interval = interval
28 | bytesByUID = self.getBytesByUID()
29 | self.start_receive_bytes = bytesByUID[0]
30 | self.start_send_bytes = bytesByUID[1]
31 | # self.thread_stop = False
32 | self.logFile = logFolder+"/network.log"
33 | if os.path.exists(self.logFile):
34 | os.remove(self.logFile)
35 | self.networkLog = open(self.logFile,"a")
36 | self.networkLog.write("receiveBytes\tsendBytes\n")
37 |
38 | def run(self):
39 | print "流量监控启动...".decode("utf-8")
40 | networkTraffic.thread_stop = False
41 | time.sleep(3)
42 | while not networkTraffic.thread_stop:
43 | time.sleep(self.interval)
44 | bytesByUID = self.getBytesByUID()
45 | end_receive_bytes = bytesByUID[0]
46 | end_send_bytes = bytesByUID[1]
47 | receive_bytes = end_receive_bytes - self.start_receive_bytes
48 | send_bytes = end_send_bytes - self.start_send_bytes
49 | networkTraffic.total_bytes+= (receive_bytes+send_bytes)
50 | self.networkLog.write(str(receive_bytes)+"\t"+str(send_bytes)+"\n")
51 | self.start_receive_bytes = end_receive_bytes
52 | self.start_send_bytes = end_send_bytes
53 | else:
54 | self.networkLog.flush()
55 | self.networkLog.close()
56 |
57 | time.sleep(2)
58 | #处理文件路径中带空格的情况
59 | if " " in const.jarFile:
60 | cmdStr = 'java -jar "'+const.jarFile+'" "'+self.logFile+'" '+self.picPre+' "'+self.logFolder+'" 1 '+UserConf.packageName
61 | else:
62 | cmdStr = 'java -jar '+const.jarFile+' '+self.logFile+' '+self.picPre+' '+self.logFolder+' 1 '+UserConf.packageName
63 | if sys.platform.startswith("win"):
64 | subprocess.call(cmdStr)
65 | elif sys.platform.startswith('linux'):
66 | subprocess.call(cmdStr,shell=True)
67 | print "制图完毕。".decode("utf-8")
68 |
69 | @staticmethod
70 | def terminate():
71 | networkTraffic.thread_stop = True
72 |
73 | def isWindowsSystem(self):
74 | return 'windows' in platform.system().lower()
75 |
76 |
77 | def __scanDevices(self):
78 | targets = []
79 | if self.isWindowsSystem():
80 | result = os.popen("adb devices").read()
81 | devices = result.split("\n")[1:]
82 |
83 | for device in devices:
84 | if device.strip():
85 | tmp = device.split()
86 | if len(tmp)==2 and tmp[1]=='device':
87 | targets.append(tmp[0])
88 |
89 | return targets
90 |
91 | def getDeviceNo(self):
92 | devices = self.__scanDevices()
93 | if(len(devices)==0):
94 | raise Exception("手机没有连接,请连接手机")
95 | return devices[0]
96 | def getAppUID(self):
97 | "得到APP的UID"
98 | cmdStr = 'adb -s %s shell "cat /proc/%s/status | grep Uid"' % (self.deviceNo,self.pid)
99 | uid = os.popen(cmdStr).read().split()[1]
100 | return uid
101 |
102 | def __getPid(self):
103 | "获取的PID,APP必须已经启动"
104 | try:
105 | cmdStr = 'adb -s %s shell "ps | grep %s$"' % (self.deviceNo,UserConf.packageName)
106 | pidStr = os.popen(cmdStr).read()
107 | pid = pidStr.split()[1]
108 | return pid
109 | except Exception as e:
110 | print "APP没有启动,启动APP...".decode("utf-8")
111 | self.app_start(UserConf.packageName,UserConf.activityName)
112 | time.sleep(5)
113 | return self.__getPid()
114 |
115 |
116 | def __getAppUIDByPackage(self):
117 | app_uid = os.popen('adb -s %s shell su -c "cat /data/system/packages.list | grep %s"' % (self.deviceNo,UserConf.packageName)).read().split()[1]
118 | return app_uid
119 |
120 | def getReceiveBytes(self):
121 | "获取APP的接收的总字节数,手机重启后该数据会被清零,建议及时保存数据"
122 | cmdStr = "adb -s %s shell cat /proc/uid_stat/%s/tcp_rcv" % (self.deviceNo,self.uid)
123 | receiveBytes = os.popen(cmdStr).read().split("\n")[0]
124 | return long(receiveBytes)
125 |
126 |
127 | def getReceiveBytesByPid(self):
128 | "获取APP的接收的总字节数,手机重启后该数据会被清零,建议及时保存数据"
129 | self.pid = self.__getPid()
130 | cmdStr = 'adb -s %s shell "cat /proc/%s/net/dev |grep wlan0"' % (self.deviceNo,self.pid)
131 | receiveBytes = os.popen(cmdStr).read().split()[1]
132 | return long(receiveBytes)
133 |
134 | def getSendBytesByPid(self):
135 | "获取APP发送的总字节数,手机重启后该数据会被清零,建议及时保存数据"
136 | self.pid = self.__getPid()
137 | cmdStr = 'adb -s %s shell "cat /proc/%s/net/dev |grep wlan0"' % (self.deviceNo,self.pid)
138 | sendBytes = os.popen(cmdStr).read().split()[9]
139 | return long(sendBytes)
140 |
141 | def getBytesByUID(self):
142 | "获取APP的接收的总字节数,手机重启后该数据会被清零,建议及时保存数据"
143 | cmdStr = 'adb -s %s shell "cat /proc/net/xt_qtaguid/stats | grep %s | grep wlan0"' % (self.deviceNo,self.uid)
144 | rec_rows = os.popen(cmdStr).read().replace("\r","").split("\n")
145 | receiveBytes = 0
146 | sendBytes = 0
147 | for i in range(0,len(rec_rows)-1):
148 | row = rec_rows[i]
149 | receiveBytes+=long(row.split()[5])
150 | sendBytes+=long(row.split()[7])
151 | return [receiveBytes,sendBytes]
152 |
153 | def getSendBytes(self):
154 | "获取APP发送的总字节数,手机重启后该数据会被清零,建议及时保存数据"
155 | cmdStr = "adb -s %s shell cat /proc/uid_stat/%s/tcp_snd" % (self.deviceNo,self.uid)
156 | sendBytes = os.popen(cmdStr).read().split("\n")[0]
157 | return long(sendBytes)
158 |
159 | def app_start(self,packageName=UserConf.packageName,activityName=UserConf.activityName):
160 | "启动APP"
161 | cmdStr = "adb shell am start -n %s/%s"%(packageName,activityName)
162 | os.system(cmdStr)
163 |
164 | if __name__ == "__main__":
165 | t = networkTraffic(r"C:\Users\zhaowei\Desktop\temp","9bae9a99")
166 | t.getBytesByUID()
167 |
--------------------------------------------------------------------------------
/ResMonitor/NetworkTraffic.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/ResMonitor/NetworkTraffic.pyc
--------------------------------------------------------------------------------
/ResMonitor/PowerMonitor.py:
--------------------------------------------------------------------------------
1 | #-*- coding: UTF-8 -*-
2 |
3 | import threading
4 | import os
5 | from Common.userConf import UserConf
6 |
7 | class powerMonitor(threading.Thread):
8 | over = False
9 |
10 | def __init__(self,logFolder,deviceNo=None,packageName=UserConf.packageName):
11 | threading.Thread.__init__(self)
12 | self.packageName = packageName
13 | self.deviceNo = deviceNo
14 | self.over = False
15 |
16 | @staticmethod
17 | def terminate():
18 | powerMonitor.over = True
19 |
20 | def getCurrentBattery(self):
21 | "获取当前手机的电量"
22 | if self.deviceNo:
23 | cmdStr = 'adb -s %s shell "dumpsys battery | grep level"' % (self.deviceNo)
24 | else:
25 | cmdStr = 'adb shell "dumpsys battery | grep level"'
26 |
27 | current_battery = os.popen(cmdStr).read().split(": ")[1]
28 | return current_battery
29 | def run(self):
30 | "执行监控"
31 | print "电量监控启动...".decode("utf-8")
32 | while not powerMonitor.over:
33 | print "AAA"
34 |
35 | if __name__ == "__main__":
36 | p = powerMonitor("353BCJMKJEF3")
37 | print p.getCurrentBattery()
--------------------------------------------------------------------------------
/ResMonitor/PowerMonitor.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/ResMonitor/PowerMonitor.pyc
--------------------------------------------------------------------------------
/ResMonitor/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/ResMonitor/__init__.py
--------------------------------------------------------------------------------
/ResMonitor/__init__.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/ResMonitor/__init__.pyc
--------------------------------------------------------------------------------
/StartTime/StartTime.py:
--------------------------------------------------------------------------------
1 | #-*- coding: UTF-8 -*-
2 | '''
3 | Created on 2016-2-26
4 |
5 | @author: zhaowei
6 | '''
7 | import os
8 | from threading import Thread
9 | import time
10 | from Common.userConf import UserConf
11 |
12 |
13 | class startTime(object):
14 | def __init__(self,times,packageName=UserConf.packageName,activityName=UserConf.activityName):
15 | self.packageName = packageName
16 | self.activityName = activityName
17 | self.times = times
18 |
19 | def getStartTime(self):
20 | "获取App一次启动的时间(应用关闭已经关闭,不在后台)单位:毫秒"
21 | self.stopAPP()
22 | cmd = 'adb shell "am start -W -n %s/%s | grep TotalTime"' % (self.packageName,self.activityName)
23 | time = os.popen(cmd).read().split(": ")[1]
24 | return long(time)
25 |
26 | def stopAPP(self):
27 | stopCmd = "adb shell am force-stop %s" % self.packageName
28 | os.system(stopCmd)
29 |
30 | def execute(self):
31 | "根据给定的次数进行启动APP,获取APP的启动时间,以字典的形式返回,key分别为:max:最大时间,min最小时间,avg:平均时间,count:次数 ,单位:毫秒,默认次数为5次"
32 | r = []
33 | appStartTime = {}
34 |
35 | for i in xrange(self.times):
36 | startTime = self.getStartTime()
37 | r.append(startTime)
38 | print ("第"+str(i+1)+"次的启动时间为:"+str(startTime)).decode("utf-8")
39 | time.sleep(1)
40 |
41 | appStartTime['max'] = max(r)
42 | appStartTime['min'] = min(r)
43 | appStartTime['avg'] = sum(r)/self.times
44 | if len(appStartTime)>2:
45 | r.sort()
46 | appStartTimeNotMaxAndNotMin = r[1:-1]
47 | appStartTime['avg'] = sum(appStartTimeNotMaxAndNotMin)/(self.times-2)
48 | appStartTime['count'] = self.times
49 | print appStartTime
50 | return appStartTime
51 |
52 |
53 |
54 | if __name__ == "__main__":
55 | s = startTime(9)
56 | result = s.execute()
57 | print result
--------------------------------------------------------------------------------
/StartTime/StartTime.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/StartTime/StartTime.pyc
--------------------------------------------------------------------------------
/StartTime/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/StartTime/__init__.py
--------------------------------------------------------------------------------
/StartTime/__init__.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/StartTime/__init__.pyc
--------------------------------------------------------------------------------
/logs/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/logs/.DS_Store
--------------------------------------------------------------------------------
/res/logo.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BaiCe/AndroidAppPerformance/1612e90d020d22397ba7bbfdb3875f5d4dcec872/res/logo.ico
--------------------------------------------------------------------------------
/run.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | python MainWindow.py
3 | pause
--------------------------------------------------------------------------------