之前呢,写了个脚本看内存占用的,https://testerhome.com/topics/18400 地址在这。但是有个问题当时并不能解决:所有的数据都是写进了 excel 中,只能在制表后看看内存走向,峰值等,看表的时候并不能知道内存攀升的时候做了什么操作,就比较鸡肋。
这次呢!有去了解大佬推荐的 pyecharts 这个库,很好的解决了这个问题。并且能节省很多人工的操作。
现在的实现思路是:依然使用 adb 去获得时间节点的内存数据,将这些数据都保存在对应的 list 中,并使用 pyecharts 将数据做成折现图保存为 html 文件,为了实现类似于即时查看的功能,引入了 selenium 库,打开这个 html 文件,并且在新数据写入并覆盖 html 文件后能刷新页面,实现每次数据获得后都能即时看到变化。
先看下具体的实现效果
那这个库在使用上上手很容易,基本上 2 小时就能基本会用。
# -*- coding: utf-8 -*-
import subprocess
import time
import os
from pyecharts import Line
from selenium import webdriver
time_value = []
JavaHeap_value = []
NativeHeap_value = []
Code_value = []
Stack_value = []
Graphics_value = []
PrivateOther_value = []
System_value = []
TOTAL_value = []
TOTAL_SWAP_PSS_value = []
# cmd命令执行代码
def run_cmd(cmd):
"""执行CMD命令"""
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
return [i.decode() for i in p.communicate()[0].splitlines()]
# 获取APK的名称
def get_apk_info():
"""获取apk的package,activity名称
:return: list eg ['com.android.calendar',
'com.meizu.flyme.calendar.AllInOneActivity']
"""
result = os.popen(
'adb shell dumpsys activity top | find "ACTIVITY"').read()
return result.splitlines()[-1].split()[1].split('/')
# 内存占用情况
def get_mem_using(package_name=None):
"""查看apk的内存占用
:param package_name:
:return: 单位KB
"""
if not package_name:
package_name = get_apk_info()[0]
results = run_cmd("adb shell dumpsys meminfo {}".format(package_name))
for index, result in enumerate(results):
if result.strip().startswith('Java Heap'):
return results[index:index + 9]
# 对cmd格式进行重组,返回成dict
def main():
dicts = {}
result = get_mem_using()
for i in result[:len(result) - 2]:
if i.strip():
dicts[i.split(':')[0].strip()] = i.split(':')[1].strip()
p = result[-1].split('TOTAL')
dicts[('TOTAL' + p[1]).split(':')[0]
] = ('TOTAL' + p[1]).split(':')[1].strip()
dicts[('TOTAL' + p[2]).split(':')[0]
] = ('TOTAL' + p[2]).split(':')[-1].strip()
return dicts
# pyecharts方法
def pyecharts_set(dicts, i):
time_value.append(i * 5)
# 获得的数据均为KB在图表中不能显示微小变化,以四舍五入方式转为MB
JavaHeap_value.append(round(int(dicts['Java Heap']) / 1024))
NativeHeap_value.append(round(int(dicts['Native Heap']) / 1024))
Code_value.append(round(int(dicts['Code']) / 1024))
Stack_value.append(round(int(dicts['Stack']) / 1024))
Graphics_value.append(round(int(dicts['Graphics']) / 1024))
PrivateOther_value.append(round(int(dicts['Private Other']) / 1024))
System_value.append(round(int(dicts['System']) / 1024))
TOTAL_value.append(round(int(dicts['TOTAL']) / 1024))
TOTAL_SWAP_PSS_value.append(round(int(dicts['TOTAL SWAP PSS']) / 1024))
line = Line('APP_Summary HTML')
line.add('Java Heap', time_value, JavaHeap_value, is_smooth=True)
line.add('Native Heap', time_value, NativeHeap_value, is_smooth=True)
line.add('Code', time_value, Code_value, is_smooth=True)
line.add('Stack', time_value, Stack_value, is_smooth=True)
line.add('Graphics', time_value, Graphics_value, is_smooth=True)
line.add('Private Other', time_value,
PrivateOther_value, is_smooth=True)
line.add('System', time_value, System_value, s_smooth=True)
line.add('TOTAL', time_value, TOTAL_value,
is_smooth=True, mark_point=['average', 'max'])
line.add('TOTAL SWAP PSS', time_value,
TOTAL_SWAP_PSS_value, is_smooth=True)
line.render('APP_Summary.html')
if __name__ == '__main__':
i = 1
driver = webdriver.Chrome()
while True:
print("写入第 {} 次数据!".format(i))
dicts = main()
if i == 1:
# init_to_excel(dicts)
pyecharts_set(dicts, i)
driver.get(
r'C:\...\...\APP_Summary.html') # 这里需要填写绝对路径,相对路径是相对与chromedriver的
else:
# add_to_excel(dicts, i)
pyecharts_set(dicts, i)
driver.refresh() # 刷新html
time.sleep(5)
i += 1
代码里面的 get_apk_info() 方法和之前的写法有区别,主要是我的手机使用之前的 adb 代码 adb shell dumpsys activity top 会多出来两个 com.miui 之类的东西,类似于
导致在打开应用的时候代码尝试获取的是 miui 的内存占用。于是就会报错。所以换用了新的 adb 命令。并且实验了下,你当前打开的 app 就是这个命令结果的最后一个
https://testerhome.com/topics/1462adb参考地址
现在还想解决下来的问题:
1、有没有更好的打开 html 这个文件的手段,费劲用了 selenium 只用了个 refresh() 方法,感觉很蠢
2、在这个代码里面的循环是否可以有种手段监听下我的键盘操作好暂停或者直接结束代码
3、其实这样的字段数据还是过多,想问下一般的数据参考是哪些,想把其他的字段数据去掉,看起来更简洁些,虽说这个 html 中可以隐藏其他字段数据 233333