思路
Python 拉取手机应用的内存占用的信息到本地,思路:
1、拉取手机应用内存占用的信息到本地
2、用关键字匹配你要查询的应用
3、并将物理内存、虚拟内存等信息存到csv中
代码实现
开始:
先简单封装个执行adb命令的方法
def execute_hdc_std_cmd(command):
s = subprocess.Popen(f'adb shell {command}',
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
ex_info, ex_err = s.communicate()
s.wait()
s.kill()
return ex_info.decode('utf8'), ex_err.decode('utf8')
封装个执行命令行的方法
def execute_cmd(command: str):
s = subprocess.Popen(command,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
ex_info, ex_err = s.communicate()
s.wait()
s.kill()
return ex_info.decode('utf8'), ex_err.decode('utf8')
以下是查询应用使用的内存信息,tag是输入的关键字
结果写入log文件
这里用到了top命令
在Linux操作系统中,top几乎是使用频率最高,也是展示信息比较全的这么一个指令,他的作用是将当前系统中所有正在运行的所有进程提供概览信息,包括系统负载、内存使用、CPU利用分布情况、每个进程的基本信息等数据,而且他是可以不断更新的。
top -b -n 1 |grep xxx > /data/log/top.log
这个命令就是将当前所有进程展示,并通过管道筛选出目标进程信息重定向为log文件
def get_top_log(tag):
# 重定向
execute_hdc_std_cmd(f'top -b -n 1 |grep {tag} > /data/log/top.log')
# 拉取
pull_command = r'adb pull /data/log/top.log ./'
execute_cmd(pull_command)
读取log文件,将其整理成csv,更直观
def get_mem_into_csv(logfile):
flag = False
with open(logfile, 'r') as f_log:
for i in f_log:
if 'grep' not in i:
# 存在所查询的关键字时
flag = True
top_list = re.split(r'\s+', i.strip())
virtual_mem = top_list[4]
real_mem = top_list[5]
share_mem = top_list[6]
mem_per = f'{top_list[9]}%'
t = time.strftime("%Y-%m-%d %X", time.localtime())
with open('mem_log.csv', 'a+') as f_csv:
f_csv.write(f'{test_name},{t},{virtual_mem},{real_mem},{share_mem},{mem_per}\n')
f_csv.close()
print(t, test_name)
print('virtual_memory:', virtual_mem, 'real_memory:', real_mem,
'share_memory:', share_mem, 'memory_percent:', mem_per)
f_log.close()
return flag
调用下整个流程
def main(test_case, interval_time, log_file='./top.log', csv_path='./mem_log.csv'):
if os.path.exists(csv_path):
os.remove(csv_path)
with open(csv_path, 'a+') as f:
f.write(f'test_name,time,virtual_memory,real_memory,share_memory,memory_percent\n')
f.close()
while True:
get_top_log(test_case)
done_flag = get_mem_into_csv(log_file)
if not done_flag:
print('test done')
break
time.sleep(int(interval_time))
if __name__ == '__main__':
# 匹配字符
test_name = 'system'
# test_name = '123'
# 刷新间隔
interval_t = 5
# test_name = sys.argv[0]
# interval_t = sys.argv[1]
# 文件路径
mem_file = './top.log'
csv_file = './mem_log.csv'
# 输出一个csv表
main(test_name, interval_t, log_file=mem_file, csv_path=csv_file)
手机内存的几个概念:
VSS - Virtual Set Size 虚拟耗用内存(包含共享库占用的内存)
RSS - Resident Set Size 实际使用物理内存(包含共享库占用的内存)
PSS - Proportional Set Size 实际使用的物理内存(比例分配共享库占用的内存)
USS - Unique Set Size 进程独自占用的物理内存(不包含共享库占用的内存)
VSS:Virtual Set Size,虚拟耗用内存。它是一个进程能访问的所有内存空间地址的大小。这个大小包含了
一些没有驻留在RAM中的内存,就像mallocs已经被分配,但还没有写入。VSS很少用来测量程序的实际使
用内存。
RSS:Resident Set Size,实际使用物理内存。RSS是一个进程在RAM中实际持有的内存大小。RSS可能会
产生误导,因为它包含了所有该进程使用的共享库所占用的内存,一个被加载到内存中的共享库可能有很
多进程会使用它。RSS不是单个进程使用内存量的精确表示。
PSS:Proportional Set Size,实际使用的物理内存,它与RSS不同,它会按比例分配共享库所占用的内存。
例如,如果有5个进程共享一个占50页内存控件的共享库,每个进程在计算PSS的时候,只会计算10页。
PSS是一个非常有用的数值,如果系统中所有的进程的PSS相加,所得和即为系统占用内存的总和。当一个
进程被杀死后,它所占用的共享库内存将会被其他仍然使用该共享库的进程所分担。在这种方式下,PSS
也会带来误导,因为当一个进程被杀后,PSS并不代表系统回收的内存大小。
USS:Unique Set Size,进程独自占用的物理内存。这部分内存完全是该进程独享的。USS是一个非常有用
的数值,因为它表明了运行一个特定进程所需的真正内存成本。当一个进程被杀死,USS就是所有系统回
收的内存。USS是用来检查进程中是否有内存泄露的最好选择。
一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS