性能测试工具 python+monkey+ 监控 crash,性能统计

测试小书童 · 2017年07月12日 · 最后由 ddup 回复于 2024年04月03日 · 7812 次阅读
本帖已被设为精华帖!

之前写过 monkey 方面的测试,这次刚好有项目用到,并且需要监控性能信息,所以重构了一次

monkey 压力测试 android

  • python3
  • 统计性能信息 cpu,men,fps,battery,flow
  • 支持 wifi,gprs 统计
  • 统计 crash 信息
  • 查看源码

monkey.ini 配置文件


cmd=adb shell monkey -p com.jianshu.haruki --throttle 500 --ignore-timeouts --ignore-crashes   --monitor-native-crashes -v -v -v 200 >
package_name=com.jianshu.haruki
activity = com.baiji.jianshu.account.SplashScreenActivity
net = wifi 
  • throttle 每次事件等待 500 毫秒
  • net 支持 gprs 和 wifi

代码分析

主要监控代码

def get_cpu(pkg_name):
    cmd = "adb  shell dumpsys cpuinfo | findstr " + pkg_name
    print(cmd)
    output = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.readlines()
    for info in output:
        if info.split()[1].decode().split("/")[1][:-1] == pkg_name:  # 只有包名相等
            # print("cpu=" + info.split()[2].decode())
            cpu.append(float(info.split()[2].decode().split("%")[0]))
            print("----cpu-----")
            print(cpu)
            return cpu


def get_men(pkg_name):
    cmd = "adb shell  dumpsys  meminfo %s" % (pkg_name)
    print(cmd)
    men_s = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.readlines()
    for info in men_s:
        if len(info.split()) and info.split()[0].decode() == "TOTAL":
            # print("men="+info.split()[1].decode())
            men.append(int(info.split()[1].decode()))
            print("----men----")
            print(men)
            return men


# 得到fps
'''
@author fenfenzhong
'''


def get_fps(pkg_name):
    _adb = "adb shell dumpsys gfxinfo %s" % pkg_name
    print(_adb)
    results = os.popen(_adb).read().strip()
    frames = [x for x in results.split('\n') if validator(x)]
    frame_count = len(frames)
    jank_count = 0
    vsync_overtime = 0
    render_time = 0
    for frame in frames:
        time_block = re.split(r'\s+', frame.strip())
        if len(time_block) == 3:
            try:
                render_time = float(time_block[0]) + float(time_block[1]) + float(time_block[2])
            except Exception as e:
                render_time = 0


        if render_time > 16.67:
            jank_count += 1
            if render_time % 16.67 == 0:
                vsync_overtime += int(render_time / 16.67) - 1
            else:
                vsync_overtime += int(render_time / 16.67)

    _fps = int(frame_count * 60 / (frame_count + vsync_overtime))
    fps.append(_fps)
    # return (frame_count, jank_count, fps)
    print("-----fps------")
    print(fps)
    return fps


def get_battery():
    _batter = subprocess.Popen("adb shell dumpsys battery", shell=True, stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE).stdout.readlines()
    for info in _batter:
        if info.split()[0].decode() == "level:":
            battery.append(int(info.split()[1].decode()))
            print("-----battery------")
            print(battery)
            return int(info.split()[1].decode())


def get_pid(pkg_name):
    pid = subprocess.Popen("adb shell ps | findstr " + pkg_name, shell=True, stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE).stdout.readlines()
    for item in pid:
        if item.split()[8].decode() == pkg_name:
            return item.split()[1].decode()


def get_flow(pkg_name, type):
    pid = get_pid(pkg_name)
    if pid is not None:
        _flow = subprocess.Popen("adb shell cat /proc/" + pid + "/net/dev", shell=True, stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE).stdout.readlines()
        for item in _flow:
            if type == "wifi" and item.split()[0].decode() == "wlan0:":  # wifi
                # 0 上传流量,1 下载流量
                flow[0].append(int(item.split()[1].decode()))
                flow[1].append(int(item.split()[9].decode()))
                print("------flow---------")
                print(flow)
                return flow
            if type == "gprs" and item.split()[0].decode() == "rmnet0:":  # gprs
                print("--------------")
                flow[0].append(int(item.split()[1].decode()))
                flow[1].append(int(item.split()[9].decode()))
                return flow
    else:
        flow[0].append(0)
        flow[1].append(0)
        return flow

  • 代码入口:
if ba.attached_devices():
       mc = BaseMonkeyConfig.monkeyConfig(PATH("monkey.ini"))
       # 打开想要的activity
       ba.open_app(mc["package_name"], mc["activity"])
       temp = ""
        # monkey开始测试
       start_monkey(mc["cmd"], mc["log"])
       time.sleep(1)
       starttime = datetime.datetime.now()
       while True:
           with open(mc["monkey_log"], encoding='utf-8') as monkeylog:
               BaseMonitor.get_cpu(mc["package_name"])
               BaseMonitor.get_men(mc["package_name"])
               BaseMonitor.get_fps(mc["package_name"])
               BaseMonitor.get_battery()
               BaseMonitor.get_flow(mc["package_name"], mc["net"])
               time.sleep(1) # 每1秒采集检查一次
               if monkeylog.read().count('Monkey finished') > 0:
                   endtime = datetime.datetime.now()
                   print("测试完成咯")
                   app = {"beforeBattery": BaseMonitor.get_battery(), "net": mc["net"], "monkey_log": mc["monkey_log"]}
                   report(app, str((endtime - starttime).seconds) + "秒")
                   bo.close()

2.0 版本更新

  • 优化了统计性能数据的代码
  • 支持多设备
  • 用了持久化记录信息,删除全局变量统计性能信息
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 98 条回复 时间 点赞

Mac 下报错的小伙伴看过来啦!
Mac 下运行会报这个错误:

提示文件路径错误,解决办法为在 BaseMonkeyConfig.py 文件中的下段:

替换为图中显示的字样😊

def avgMen(men, total):
if len(men):
_men = [math.ceil(((men[i]) / total) * 1024) for i in range(len(men))]
return str(math.ceil(sum(_men) / len(_men))) + "%"
return "0%"

百分比的话 为什么要 *1024?这里应该不需要 *1024 吧

Forkey 回复

我解决了 output = subprocess.check_output(cmd,shell=True).decode(),源代码少一个 shell=True

嗯,我优化了下,我这里跑了一台小米和华为,暂时没有发现问题,很感谢你分享的帖子

feng 回复

你解决了这个问题了吗????

海韵 回复

你好,请问你那个问题解决了吗?

能出个使用文档么?方便大家使用

重来看雨 回复

自带的,你确定下是不是环境问题,我用的 py3

这个会自动生成 report 么

感谢楼主分享,不知道为什么刚开始执行是 OK 的,但是后面执行的时候一直报错,list index out of range,我打印了 item.split(),结果时列表中有 9 个参数,也就是 0-8,但是还是会数组越界?请问能怎么解决呢?

老马 monkeyTest 工具使用排坑记 中提及了此贴 02月05日 15:13
海韵 回复

用 py3 试试,修改了批处理文件

lb 回复

我刚刚还试过了,应该不会

KIki 回复

直接修改 monkey.ini 中的 net = gprs(或者 wifi),手机安装简书,然后运行 monkeytest.py

匿名 #34 · 2018年03月20日

能不能支持下 mac 或是 linux 平台

你好,版主。
一直用数据线插着充电,跑测试。
里面的电量分析还有意义吗

William 回复

嗯,没有意义,就是简单练习下,耗电量测试可以用其他方式测,我之前这样测试的:adb reset 电量后,锁屏应用后台运行,然后再读取耗电量

运行报错了

multiprocessing.pool.RemoteTraceback:
"""
Traceback (most recent call last):
File "D:\Anaconda3\lib\multiprocessing\pool.py", line 119, in worker
result = (True, func(*args, **kwds))
File "D:\Anaconda3\lib\multiprocessing\pool.py", line 44, in mapstar
return list(map(*args))
File "D:\monkeyTest\monkeyTest.py", line 99, in start
pid = BaseMonitor.get_pid(mc["package_name"], devices)
File "D:\monkeyTest\Base\BaseMonitor.py", line 114, in get_pid
if item.split()[8].decode() == pkg_name:
IndexError: list index out of range
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "D:/monkeyTest/monkeyTest.py", line 153, in
runnerPool()
File "D:/monkeyTest/monkeyTest.py", line 77, in runnerPool
pool.map(start, devices_Pool)
File "D:\Anaconda3\lib\multiprocessing\pool.py", line 266, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "D:\Anaconda3\lib\multiprocessing\pool.py", line 644, in get
raise self._value
IndexError: list index out of range

大海 回复

你的问题解决了吗? 我也遇到这种问题了

夏杰 回复

没有,弃用了

Scofell 回复

FPS 是 60 的问题你解决了嘛?我的也一直是 60

FPS 是一直是 60 是不是因为

图上圈起来的解析返回数据那段代码有问题?依照那个逻辑可能 vsync_overtime 一直都是 0

Doraly 回复

你好,一直是 60 的问题你解决了吗?

楼主,方便给下微信或者其他联系方式吗?

夏杰 回复

看返回的数据很难解析出来的样子...

Doraly 回复

你 CPU 的打印正常吗?

你好,你的 fps 和 cpu 打印正常吗?

楼主,虚拟机能用吗?
我在夜神上没跑起来啊

不错,可以配置多个 activity 的吗?

使用过程中,发现不准确。我网络使用的 wifi,给我统计的为 gprs,流量值都是 0KB

loneyao 回复

配置文件里配置的什么:
net = wifi

可以代码自行扩展 打开不同的 activity

楼主你好,能帮我解答一下 FPS 一直是 60,怎么处理这个问题,蟹蟹

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 20:49
simple [精彩盘点] TesterHome 社区 2018 年 度精华帖 中提及了此贴 01月07日 12:08

在终端执行 “adb -s 25acc8ee shell wm size” 可以获取分辨率,但是在代码中就不行了

FileNotFoundError: [Errno 2] No such file or directory: 'adb -s 25acc8ee shell wm size': 'adb -s 25acc8ee shell wm size'

@lose 麻烦帮我看下,具体是什么问题

楼主,
1、点击数设置 1000,手机还在模拟点击时,代码已经崩了。越界了,这是什么原因,没查到

@ 测试小书童 楼主,我怎么着了半天也找不到程序入口啊😂 !!

请问楼主,monkey 事件执行完之前可以手动停止吗?我用 ctrl+C, exit 都没有停止

cmd = "adb -s " + devices + " shell cat /system/build.prop"

这个命令报错
cat: /system/build.prop: Permission denied
是手机的问题还是 Mac 电脑的问题

未夕 回复

cat: /system/build.prop: Permission denied
我也遇到了这个问题,请问楼主需要怎么解决?

Forkey 回复

我跟你一样,请问解决了吗?

代码报错:

*** liyu 2015-01-15***

*** v1.0.0 ***


Checking adb port...
成功: 已终止 PID 为 15828 的进程。
adb devices
cannot connect to daemon at tcp:5037: cannot connect to 127.0.0.1:5037: 由于目标计算机积极拒绝,无法连接。 (10061)

  • daemon not running; starting now at tcp:5037 adb -s 053260ec7d23 unauthorized shell wm size adb: usage: unknown command unauthorized multiprocessing.pool.RemoteTraceback: """ Traceback (most recent call last): File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\pool.py", line 119, in worker result = (True, func(*args, **kwds)) File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\pool.py", line 44, in mapstar return list(map(*args)) File "F:\my_tools\monkeyTest\monkeyTest.py", line 88, in start mkdirInit(devices, app, num) File "F:\my_tools\monkeyTest\monkeyTest.py", line 54, in mkdirInit app[devices] = {"cpu": cpu, "men": men, "flow": flow, "battery": battery, "fps": fps, "header": get_phome(devices)} File "F:\my_tools\monkeyTest\monkeyTest.py", line 38, in get_phome bg = BasePhoneMsg.get_phone_Kernel(devices) File "F:\my_tools\monkeyTest\Base\BasePhoneMsg.py", line 66, in get_phone_Kernel pix = get_app_pix(devices) File "F:\my_tools\monkeyTest\Base\BasePhoneMsg.py", line 62, in get_app_pix return subprocess.check_output(cmd).split()[2].decode() File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 336, in check_output **kwargs).stdout File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\subprocess.py", line 418, in run output=stdout, stderr=stderr) subprocess.CalledProcessError: Command 'adb -s 053260ec7d23 unauthorized shell wm size' returned non-zero exit status 1. """

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "monkeyTest.py", line 153, in
runnerPool()
File "monkeyTest.py", line 77, in runnerPool
pool.map(start, devices_Pool)
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\pool.py", line 266, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python36-32\lib\multiprocessing\pool.py", line 644, in get
raise self._value
subprocess.CalledProcessError: Command 'adb -s 053260ec7d23 unauthorized shell wm size' returned non-zero exit status 1.

大佬我运行代码报

能加你的微信和 qq 咨询一下吗?

大佬,看了你多手机运行的帖子,我自己运行的时候发现 subprocess.Popen 调用 cmd 命令返回的内容是错误的,导致后面解码的代码执行错误,能帮忙看看什么问题吗?

直接用答应出来的 cmd 命令手动执行是没问题的


我遇到了这么个问题

感谢分享,学习了!

先学习下~

思寒_seveniruby 将本帖设为了精华贴 07月13日 19:48

非常好 谢谢

—— 来自 TesterHome 官方 安卓客户端



github 上面,是不是漏了 configparser

这个很不多,尝试用用

不错,我有个建议,如果做成,不需要 monkey,可以自己手动操作,进行性能数据收集的会更好。配上 monkey 还是有局限性的~

楼主你好,电量测试曲线 y 轴是电量百分比吗?看起来是越来越高,是因为测试过程中连接数据线导致的吗?

试了下,我这边存在这个问题

dabao 回复

是的,一直连着电脑充电

chenyouan 回复

你自己调试下:

  • 打印下 pid 为多少
  • 打印下获取电量那里的 split 信息
  • 手动命令获取电量信息

您好,为什么内存会是 151%,超过 100%

开始跑 monkey 等的命令,是否需要 +&

那我有空再去试试,谢谢啦~

那为什么一直是 60 尼?这样子不科学,实际应该掉帧应该是挺严重的哦~

chenyouan 回复

同样问题,你解决了吗?

UDLD 回复

不用的

jierong01 回复

对的,打开开发者里面的 GPU 呈现模式分析 - 在 adb shell dumpsys gcxinfo 中

首先感谢楼主,真的很好用,我已经跑起来了,但是发现 ftp 的值一直是 60,是不是因为我没有打开开发者模式里面显示掉帧的按钮尼???

测试完成后,形成的图表怎么没有变化?还是楼主之前的 demo 图表

jierong01 回复

一直是 60,这个我测试出来的也是这种情况

想请教下:
1、adb shell dumpsys cpuinfo | findstr " + pkg_name 这种形式获取 cpu 经常会超过 100%,这是为什么?
2、dumpsys cpuinfo 和 top 取 cpu 使用率的区别是什么?

未来来 回复

你打印下取值情况,或者你用下面的方式排除下:

jierong01 回复
  • 打开开发者里面的 GPU 呈现模式分析 - 在 adb shell dumpsys gcxinfo 中
  • 生成的 excel 报告数据没有变化?应该不可能,你清空下 excel 里面的所有数据,看看生成结果
chenyouan 回复

打印一下 print(item.split())
[b'u0_a186', b'27282', b'880', b'1276836', b'106252', b'0000000000', b'R', b'com.roobo.pudding']
只有 8 个 你取 if item.split()[8].decode() == pkg_name: 肯定超出边界值了。改成 7 就可以了

yu 回复

边界值的问题,想请教下,是开始执行 ok,执行到后面,数据多了,就报边界问题了

top 和 dumpsys cpuinfo 取值都能针对 pid 取值,但是后者的取值往往大于前者,而且后者还有大于 100% 的情况存在,这两个的区别是什么?

你好,fps 一直显示的是 60?这个是什么问题?开发者里面的 GPU 呈现模式分析 - 在 adb shell dumpsys gcxinfo 中 这个已经打开

@aecho 如果是长时间跑,可以先把采集数据设置时间长一点,还有现在长时间跑回出现上面朋友说的边界和数据统计问题,后续我看看怎么优化下

有时候行,有时候不行,这比较纠结

summe 回复

你确定是打开了吗?我这边试过了几天华为手机都是正常的,,你是用是什么型号手机?

hlfang 回复

打印一下 print(item.split())
[b'u0_a186', b'27282', b'880', b'1276836', b'106252', b'0000000000', b'R', b'com.roobo.pudding']
只有 8 个 你取 if item.split()[8].decode() == pkg_name: 肯定超出边界值了。改成 7 就可以了

楼上是这样回复的,我这边重现不了。。。奇怪,应该是不同手机取值可能不一样

好吧,我是 py2

75楼 已删除

非常实用,谢谢。

hlfang 回复

关闭 excel 试试

未来来 回复

dumpsys 拿到的是几个 cpu 的值,所以可能得到 100+% 的值,还是 proc/pid/stat 靠谱点,后续我优化下

关闭了还是会出现诶

未来来 回复

cpu 问题也修复了,用了新的算法,你在看看是否有问题?

你好,请问为什么经常跑到这个地方经常会报错

出错时,在 cmd 中查看这条命令,打印的值显示好像也是正常的

这个问题,好像是不同的手机查询出来的信息不一样,我这边查询出来有 4 列,分别是
Draw Prepare Process Execute,这 4 列的数据,有的只有 3 列

summe 回复

问题已经修复了,显示是正确的不应该显示%,单位应该是 M

multiprocessing.pool.RemoteTraceback: 
"""
Traceback (most recent call last):
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/pool.py", line 119, in worker
    result = (True, func(*args, **kwds))
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/multiprocessing/pool.py", line 44, in mapstar
    return list(map(*args))
  File "/Users/a/自动化相关/monkeyTest-master/monkeyTest.py", line 100, in start
    mkdirInit(devices, app, num)
  File "/Users/a/自动化相关/monkeyTest-master/monkeyTest.py", line 67, in mkdirInit
    app[devices] = {"cpu": cpu, "men": men, "flow": flow, "battery": battery, "fps": fps, "header": get_phome(devices)}
  File "/Users/a/自动化相关/monkeyTest-master/monkeyTest.py", line 41, in get_phome
    bg = BasePhoneMsg.get_phone_Kernel(devices)
  File "/Users/a/自动化相关/monkeyTest-master/Base/BasePhoneMsg.py", line 43, in get_phone_Kernel
    pix = get_app_pix(devices)
  File "/Users/a/自动化相关/monkeyTest-master/Base/BasePhoneMsg.py", line 39, in get_app_pix
    return  subprocess.check_output(cmd).split()[2].decode()
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/subprocess.py", line 336, in check_output
    **kwargs).stdout
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/subprocess.py", line 403, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/subprocess.py", line 707, in __init__
    restore_signals, start_new_session)
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/subprocess.py", line 1326, in _execute_child
    raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'adb -s 5ae50462 shell wm size'
"""

报这个错是什么原因

学习了!明天我也试试

请教楼主一个问题,首先感谢楼主提供的源码,我在多设备运行过程中遇到一个问题,就是在执行 map 调用 start 函数时遇到 adb 端口被占用的问题,不知楼主有没有碰到过,详情如下:
11111111: ['7N2SSE158U004185', 'NXTDU16923003480']
2222222222: [{'num': 2, 'devices': '7N2SSE158U004185'}]
2222222222: [{'num': 2, 'devices': '7N2SSE158U004185'}, {'num': 2, 'devices': 'NXTDU16923003480'}]
当前设备 ID:7N2SSE158U004185
当前设备数量: 2
创建持久性文件...
当前设备 ID:NXTDU16923003480
当前设备数量: 2
创建持久性文件...
error: could not install smartsocket listener: cannot bind to 127.0.0.1:5037: 通常每个套接字地址 (协议/网络地址/端口) 只允许使用一次。 (10048)
could not read ok from ADB Server

  • failed to start daemon *

另外个人在执行过程中遇到几个问题,在这里跟楼主和其他同学们分享下:

1.执行过程中如果 adb 命令被重启或者 kill 掉,在执行 def get_app_pix(dev) 得到的返回值如下,这样就会导致获得的设备分辨率异常显示为 “is”:

所以对楼主 def get_app_pix(dev) 进行了改造,代码如下:

得到手机分辨率

def get_app_pix(dev):
cmd = "adb -s " + dev + " shell wm size"
#print(cmd)
#return subprocess.check_output(cmd).split()[2].decode()
result = os.popen(cmd, "r")
line = result.readline()
while line:
if str(line).find('Physical size') != -1:
line = str(line).strip('\n')
return str(line.split("Physical size:")[1])
line = result.readline()

2.同样 def get_men_total(dev): 也会遇到类似问题,代码改造如下:

# 获取设备内存
def get_men_total(dev):
cmd = "adb -s " + dev + " shell cat /proc/meminfo"
output = subprocess.check_output(cmd).split()
items = [x.decode() for x in output]
for k,v in enumerate(items):
if str(v) == 'MemTotal:':
return int(items[k+1])

3.在启动 monkey 过程中遇到如下问题,创建持久化文件后,monkey 无法启动,提示 adb server 端口被占用,错误如下:

所以在创建文件完成后,加了两行代码来重启 adb 服务,代码如下:
mkdirInit(devices, app, num)
os.popen("adb kill-server adb")
os.popen("adb start-server")
time.sleep(5)
print("--------------开始执行 Monkey----------------")

4.在 BaseMonitor 中统计 cpu 占有率时,也遇到了个问题,在执行到获取 cpu 内核时无法继续执行了,如下图:

所以对获取内核的代码和 cpu 统计也做了修改,代码如下:
ef totalCpuTime(dev):
user = nice = system = idle = iowait = irq = softirq = 0

cmd = "adb -s " + dev + " shell cat /proc/stat"
#print(cmd)
process = (os.popen(cmd))
output = process.read()
#print(output)
res = output.split()
#print(res)
for info in res:
if info == "cpu":
user = res[1]
nice = res[2]
system = res[3]
idle = res[4]
iowait = res[5]
irq = res[6]
softirq = res[7]
"""print("user = %s"% user)
print("nice = %s" % nice)
print("system = %s" % system)
print("idle = %s" % idle)
print("iowait =%s" % iowait)
print("irq = %s" % irq)
print("softirq = %s" % softirq)"""
result = int(user) + int(nice) + int(system) + int(idle) + int(iowait) + int(irq) + int(softirq)
#print("totalCpuTime=" + str(result))
return result

'''
每一个进程快照
'''

def processCpuTime(pid, dev):
utime = stime = cutime = cstime = 0
try:
cmd = "adb -s " + dev + " shell cat /proc/" + pid + "/stat"
#print(cmd)
process = (os.popen(cmd))
output = process.read()
#print(output)
#process.close()
res = output.split()
#print(res)
utime = res[13]
stime = res[14]
cutime = res[15]
cstime = res[16]
"""print("utime = %s" % utime)
print("stime = %s" % stime)
print("cutime = %s" % cutime)
print("cstime = %s" % cstime)"""
result = int(utime) + int(stime) + int(cutime) + int(cstime)
#print("processCpuTime=" + str(result))
except:
result = 0
return result

得到几核 cpu

def get_cpu_kel(dev):
cmd = "adb -s " + dev + " shell cat /proc/cpuinfo"
#print("----cpu_kel-------")
#print(cmd)
process = (os.popen(cmd))
output = process.read()
res = output.split()
num = re.findall("processor",str(res))
#print(num)
return len(num)

这是在我的工作机上执行过程中遇到的问题,也许是环境不同,导致我的运行结果和楼主的不同,这里贴出来,如果有遇到类似问题的朋友可以适当借鉴下,再次感谢楼主提供的源码,很棒~大赞~~,也希望楼主能帮我看下我在开头碰到的问题~万分感谢~!

谢谢楼主的建议,虽然我用了批处理,还是会有下面这个 error 提示,执行多设备的时候还是会卡住,推测楼主是在 liunx 上跑的, 我是在 windows 上,系统环境上可能有所不同。
error: could not install smartsocket listener: cannot bind to 127.0.0.1:5037: 通常每个套接字地址 (协议/网络地址/端口) 只允许使用一次。 (10048)
could not read ok from ADB Server

  • failed to start daemon *

所以我改用多线程来处理了,不过同样也是会报上面的 error 提示,不过好在虽然有提示,但是整体还是跑通了,多线程代码如下,拿出来给一些使用 windows 的同学一起分享下。(python 初学,有些不足的地方还请大神们多多指点~,再次感谢楼主~)

# 多线程启动
class MonkeyThread(threading.Thread):
def init(self, dev):
threading.Thread.init(self)
self.thread_stop = False
self.dev = dev

def run(self):
time.sleep(2)
start_monkey(self.dev)

def create_threads_monkey(device_list):
thread_instances = []
if device_list != []:
for id_device in device_list:
dev = id_device
instance = MonkeyThread(dev)
thread_instances.append(instance)
for instance in thread_instances:
instance.start()

if name == 'main':
path_bat= "D:\PyCharm\Monkey_performance\" # 批处理文件路径
os.system('start ' + os.path.join(path_bat, 'kill_port.bat')) # 批处理关闭 5037 端口
# 重启 adb 服务
os.popen("adb kill-server adb")
os.popen("adb start-server")
time.sleep(10)
device_dir = os.path.exists(Config.info_path)
if device_dir:
print("持久性目录 info 已存在,继续执行测试!")
else:
os.mkdir(Config.info_path) # 创建持久性目录
device_list = BaseMonitor.get_devices()
if ba.attached_devices():
create_threads_monkey(device_list)
else:
print("设备不存在")

谢谢分享,每次运行之前,我都会手动运行一个批处理命令,杀死所有的 5037 端口,这样就不会出现你说的问题,代码如下:

echo off
color a
title ReleaseAdbPort
echo ======================
echo *** liyu 2015-01-15***
echo *** v1.0.0 ***
echo ======================
echo ---------------------------
echo Checking adb port...
for /F "usebackq tokens=5" %%a in (`"netstat -ano | findstr "5037""`) do (
if not "%%a" =="0" call :ReleasePort %%a
)
echo ---------------------------
echo adb port has been released!
echo ---------------------------
pause

exit

:ReleasePort
TASKKILL /f /PID %1

我想问下,我这边是 python2 的版本,改到 BaseReport.py,运行是为什么报。,应该是执行 tem.close() 报的错。

summe 回复

你好,请问下问题解决了吗?我的 fps 也一直是 60,adb shell dumpsys gcxinfo 在开发者模式打开

cloudwind 回复

要用 python3 版本

洒大目 回复

我知道了…是路径的符号…

Traceback (most recent call last):
File "monkeyTest.py", line 163, in
runnerPool()
File "monkeyTest.py", line 90, in runnerPool
pool.map(start, devices_Pool)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/pool.py", line 567, in get
raise self._value
OSError: [Errno 2] No such file or directory

HI 请问这个我需要怎么解决,不甚感激~

samxupeiran 回复

你手动新建一个 log 文件夹,我忘记传上去了

频繁使用 adb 采集数据不会对性能数据有影响吗?

这个必须收藏


请问:python2,出现该出现该如何处理?在此谢过大神

lb 性能测试工具 python+monkey+ 监控 crash,性能统计 中提及了此贴 10月30日 11:44

楼主,抓取 logcat 这块,脚本会一直卡在这里,你们的不会吗?
os.popen(cmd_logcat)

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册