Skip to content

Commit

Permalink
support PK Model
Browse files Browse the repository at this point in the history
  • Loading branch information
rafa0128 committed Sep 1, 2022
1 parent 170b01c commit c7aba1d
Show file tree
Hide file tree
Showing 17 changed files with 1,851 additions and 62 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,14 @@ http://{ip}:50003/apm/collect?platform=Android&deviceid=ca6bd5a5&pkgname=com.bil
apm_type in ['cpu','memory','network','fps','battery']
```

## PK Model
- 2-devices: test the same app on two different phones
- 2-apps: test two different apps on two phones with the same configuration

<img src="./image/pk.png" width="100%">


## Thanks
- https://github.com/alibaba/mobileperf

- https://github.com/alibaba/taobao-iphone-device

Expand Down
Binary file removed image/analysis.png
Binary file not shown.
Binary file modified image/home.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image/pk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion solox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

from __future__ import absolute_import

__version__ = '2.1.8'
__version__ = '2.2.0'
191 changes: 191 additions & 0 deletions solox/public/apm_pk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
import datetime
import re
import time
from functools import reduce
from logzero import logger
from solox.public.adb import adb
from solox.public.common import Devices, file
from solox.public.fps import FPSMonitor, TimeUtils

d = Devices()
f = file()


class CPU_PK:

def __init__(self, pkgNameList: list, deviceId1, deviceId2):
self.pkgNameList = pkgNameList
self.deviceId1 = deviceId1
self.deviceId2 = deviceId2
self.apm_time = datetime.datetime.now().strftime('%H:%M:%S.%f')

def getprocessCpuStat(self, pkgName, deviceId):
"""get the cpu usage of a process at a certain time"""
pid = d.getPid(pkgName=pkgName, deviceId=deviceId)
cmd = f'cat /proc/{pid}/stat'
result = adb.shell(cmd=cmd, deviceId=deviceId)
r = re.compile("\\s+")
toks = r.split(result)
processCpu = float(int(toks[13]) + int(toks[14]))
return processCpu

def getTotalCpuStat(self, deviceId):
"""get the total cpu usage at a certain time"""
cmd = f'cat /proc/stat |{d._filterType()} ^cpu'
result = adb.shell(cmd=cmd, deviceId=deviceId)
r = re.compile(r'(?<!cpu)\d+')
toks = r.findall(result)
totalCpu = float(reduce(lambda x, y: int(x) + int(y), toks))
return totalCpu


def getIdleCpuStat(self, deviceId):
"""get the idle cpu usage at a certain time"""
cmd = f'cat /proc/stat |{d._filterType()} ^cpu'
result = adb.shell(cmd=cmd, deviceId=deviceId)
r = re.compile(r'(?<!cpu)\d+')
rList = result.split('\n')
IdleCpuList = []
IdleCpu = 0
for i in range(len(rList)):
toks = r.findall(rList[i])
IdleCpuList.append(toks[3])
IdleCpu = IdleCpu + float(reduce(lambda x, y: int(x) + int(y), IdleCpuList))
return IdleCpu

def getAndroidCpuRate(self):
"""get the Android cpu rate of a process"""
processCpuTime1_first = self.getprocessCpuStat(pkgName=self.pkgNameList[0], deviceId=self.deviceId1)
totalCpuTime1_first = self.getTotalCpuStat(deviceId=self.deviceId1)
time.sleep(1)
processCpuTime1_second = self.getprocessCpuStat(pkgName=self.pkgNameList[0], deviceId=self.deviceId1)
totalCpuTime1_second = self.getTotalCpuStat(deviceId=self.deviceId1)

if len(self.pkgNameList) == 1:
processCpuTime2_first = self.getprocessCpuStat(pkgName=self.pkgNameList[0], deviceId=self.deviceId2)
totalCpuTime2_first = self.getTotalCpuStat(deviceId=self.deviceId2)
time.sleep(1)
processCpuTime2_second = self.getprocessCpuStat(pkgName=self.pkgNameList[0], deviceId=self.deviceId2)
totalCpuTime2_second = self.getTotalCpuStat(deviceId=self.deviceId2)
else:
processCpuTime2_first = self.getprocessCpuStat(pkgName=self.pkgNameList[1], deviceId=self.deviceId2)
totalCpuTime2_first = self.getTotalCpuStat(deviceId=self.deviceId2)
time.sleep(1)
processCpuTime2_second = self.getprocessCpuStat(pkgName=self.pkgNameList[1], deviceId=self.deviceId2)
totalCpuTime2_second = self.getTotalCpuStat(deviceId=self.deviceId2)

appCpuRate1 = round(float((processCpuTime1_second - processCpuTime1_first) / (totalCpuTime1_second - totalCpuTime1_first) * 100), 2)
appCpuRate2 = round(float((processCpuTime2_second - processCpuTime2_first) / (totalCpuTime2_second - totalCpuTime2_first) * 100), 2)

f.add_log(f'{f.report_dir}/cpu_app1.log', self.apm_time, appCpuRate1)
f.add_log(f'{f.report_dir}/cpu_app2.log', self.apm_time, appCpuRate2)


return appCpuRate1, appCpuRate2


class MEM_PK:
def __init__(self, pkgNameList: list, deviceId1, deviceId2):
self.pkgNameList = pkgNameList
self.deviceId1 = deviceId1
self.deviceId2 = deviceId2
self.apm_time = datetime.datetime.now().strftime('%H:%M:%S.%f')

def getAndroidMem(self, pkgName, deviceId):
"""Get the Android memory ,unit:MB"""
pid = d.getPid(pkgName=pkgName, deviceId=deviceId)
cmd = f'dumpsys meminfo {pid}'
output = adb.shell(cmd=cmd, deviceId=deviceId)
m_total = re.search(r'TOTAL\s*(\d+)', output)
totalPass = round(float(float(m_total.group(1))) / 1024, 2)
return totalPass

def getProcessMem(self):
"""Get the app memory"""
if len(self.pkgNameList) == 1:
totalPass1 = self.getAndroidMem(self.pkgNameList[0], self.deviceId1)
totalPass2 = self.getAndroidMem(self.pkgNameList[0], self.deviceId2)
else:
totalPass1 = self.getAndroidMem(self.pkgNameList[0], self.deviceId1)
totalPass2 = self.getAndroidMem(self.pkgNameList[1], self.deviceId2)

f.add_log(f'{f.report_dir}/mem1.log', self.apm_time, totalPass1)
f.add_log(f'{f.report_dir}/mem2.log', self.apm_time, totalPass2)

return totalPass1, totalPass2


class Flow_PK:

def __init__(self, pkgNameList: list, deviceId1, deviceId2):
self.pkgNameList = pkgNameList
self.deviceId1 = deviceId1
self.deviceId2 = deviceId2
self.apm_time = datetime.datetime.now().strftime('%H:%M:%S.%f')

def getAndroidNet(self, pkgName, deviceId):
"""Get Android upflow and downflow data, unit:KB"""
pid = d.getPid(pkgName=pkgName, deviceId=deviceId)
cmd = f'cat /proc/{pid}/net/dev |{d._filterType()} wlan0'
output_pre = adb.shell(cmd=cmd, deviceId=deviceId)
m_pre = re.search(r'wlan0:\s*(\d+)\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*(\d+)', output_pre)
sendNum_pre = round(float(float(m_pre.group(2)) / 1024), 2)
recNum_pre = round(float(float(m_pre.group(1)) / 1024), 2)
time.sleep(1)
output_final = adb.shell(cmd=cmd, deviceId=deviceId)
m_final = re.search(r'wlan0:\s*(\d+)\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*(\d+)', output_final)
sendNum_final = round(float(float(m_final.group(2)) / 1024), 2)
recNum_final = round(float(float(m_final.group(1)) / 1024), 2)
sendNum = round(float(sendNum_final - sendNum_pre), 2)
recNum = round(float(recNum_final - recNum_pre), 2)
network = round(float(sendNum + recNum), 2)
return network

def getNetWorkData(self):
"""Get the upflow and downflow data, unit:KB"""
if len(self.pkgNameList) == 1:
network1 = self.getAndroidNet(self.pkgNameList[0], self.deviceId1)
network2 = self.getAndroidNet(self.pkgNameList[0], self.deviceId2)
else:
network1 = self.getAndroidNet(self.pkgNameList[0], self.deviceId1)
network2 = self.getAndroidNet(self.pkgNameList[1], self.deviceId2)
f.add_log(f'{f.report_dir}/network1.log', self.apm_time, network1)
f.add_log(f'{f.report_dir}/network2.log', self.apm_time, network2)
return network1, network2


class FPS_PK:

def __init__(self, pkgNameList: list, deviceId1, deviceId2):
self.pkgNameList = pkgNameList
self.deviceId1 = deviceId1
self.deviceId2 = deviceId2
self.apm_time = datetime.datetime.now().strftime('%H:%M:%S.%f')

def getAndroidFps(self, deviceId, pkgName):
"""get Android Fps, unit:HZ"""
monitors = FPSMonitor(device_id=deviceId, package_name=pkgName, frequency=1,
start_time=TimeUtils.getCurrentTimeUnderline())
monitors.start()
fps, jank = monitors.stop()
return fps


def getFPS(self):
"""get fps"""
if len(self.pkgNameList) == 1:
logger.info(self.deviceId1)
logger.info(self.deviceId2)
fps1 = self.getAndroidFps(pkgName=self.pkgNameList[0], deviceId=self.deviceId1)
fps2 = self.getAndroidFps(pkgName=self.pkgNameList[0], deviceId=self.deviceId2)

else:
fps1 = self.getAndroidFps(pkgName=self.pkgNameList[0], deviceId=self.deviceId1)
fps2 = self.getAndroidFps(pkgName=self.pkgNameList[1], deviceId=self.deviceId2)

f.add_log(f'{f.report_dir}/fps1.log', self.apm_time, fps1)
f.add_log(f'{f.report_dir}/fps2.log', self.apm_time, fps2)

return fps1, fps2


38 changes: 37 additions & 1 deletion solox/public/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,13 @@ def add_log(self, path, log_time, value):
with open(path, 'a+', encoding="utf-8") as file:
file.write(f'{log_time}={str(value)}' + '\n')

def make_report(self, app, devices, platform='Android'):
def make_report(self, app, devices, platform='Android', model='normal'):
current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
result_dict = {
"app": app,
"icon": "",
"platform": platform,
"model": model,
"devices": devices,
"ctime": current_time
}
Expand Down Expand Up @@ -299,6 +300,41 @@ def _setiOSPerfs(self, scene):

return apm_dict

def _setpkPerfs(self, scene):
"""Aggregate APM data for pk model"""
cpuAppData1 = self.readLog(scene=scene, filename=f'cpu_app1.log')[1]
cpuAppRate1 = f'{round(sum(cpuAppData1) / len(cpuAppData1), 2)}%'
cpuAppData2 = self.readLog(scene=scene, filename=f'cpu_app2.log')[1]
cpuAppRate2 = f'{round(sum(cpuAppData2) / len(cpuAppData2), 2)}%'

totalPassData1 = self.readLog(scene=scene, filename=f'mem1.log')[1]
totalPassAvg1 = f'{round(sum(totalPassData1) / len(totalPassData1), 2)}MB'
totalPassData2 = self.readLog(scene=scene, filename=f'mem2.log')[1]
totalPassAvg2 = f'{round(sum(totalPassData2) / len(totalPassData2), 2)}MB'

fpsData1 = self.readLog(scene=scene, filename=f'fps1.log')[1]
fpsAvg1 = f'{int(sum(fpsData1) / len(fpsData1))}HZ/s'
fpsData2 = self.readLog(scene=scene, filename=f'fps2.log')[1]
fpsAvg2 = f'{int(sum(fpsData2) / len(fpsData2))}HZ/s'

networkData1 = self.readLog(scene=scene, filename=f'network1.log')[1]
network1 = f'{round(float(sum(networkData1) / 1024), 2)}MB'
networkData2 = self.readLog(scene=scene, filename=f'network2.log')[1]
network2 = f'{round(float(sum(networkData2) / 1024), 2)}MB'

apm_dict = {
"cpuAppRate1": cpuAppRate1,
"cpuAppRate2": cpuAppRate2,
"totalPassAvg1": totalPassAvg1,
"totalPassAvg2": totalPassAvg2,
"network1": network1,
"network2": network2,
"fpsAvg1": fpsAvg1,
"fpsAvg2": fpsAvg2
}

return apm_dict


class Method:

Expand Down
Binary file added solox/static/image/readme/home.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added solox/static/image/readme/pk.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion solox/templates/analysis.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{% extends 'base.html' %}

{% block title %}SoloX - Analysis{% endblock %}

{% block css %}{% endblock %}
Expand Down
Loading

0 comments on commit c7aba1d

Please sign in to comment.