天天看點

PerfDog4.0探索,支援使用者自建web雲

經過一段時間的優化,PerfDog4.0全新來襲,先來看看都更新了神馬

一,新版功能初探

  • 【新增】新增圖表常見操作提示功能
  • 【新增】新增高階功能,子程序幀率精準測試
  • 【優化】徹底解決部分Android手機無法擷取電量和記憶體等問題
  • 【優化】解決iOS低版本無法擷取FPS等問題
  • 【修複】修複一些已知問題

我們發現新版增加了一些常用tip

PerfDog4.0探索,支援使用者自建web雲

優化了一些安卓以及ios部分機型或者系統版本無法擷取部分資料的問題,如果還有一些擷取不到資料或者連接配接的問題,請檢視

PerfDog使用連接配接相關說明

二,子程序幀率精準測試說明

這個子程序幀率擷取對于目前來說使用多程序的應用來說非常有用哦,可能有些同學對于這個概念不是很清晰,我們來一步步探索;

PerfDog4.0探索,支援使用者自建web雲

這是啥?幹啥用?怎麼用?

多程序簡介:

Android平台,一般大型APP,比如遊戲有時候是多程序協作運作(微信小遊戲,微視等APP及王者榮耀等遊戲多子程序),可選擇目标子程序進行針對性測試。預設是主程序。如圖王者榮耀

PerfDog4.0探索,支援使用者自建web雲

弄清出子程序幀率之前先需要搞清楚Android視窗是是啥。下面簡要的概述下,具體還不了解的請度娘SurfaceFliger,或者檢視這篇文章扒一扒安卓渲染原理

簡單來說surfaceflinger是安卓系統的一個服務,作用是接受多個來源的圖形顯示資料,将他們合成,然後發送到顯示裝置;

我們來看看官方的描述

大類去看,一般Android主視窗Activity和與之對應的View,有一種特殊的View,如SurfaceView,他會獨享一個Surface,不與主視窗共享Surface,獨立渲染非常高效,支援OpenglES渲染。也就是說可能會出現兩類視窗FPS。一個是Activety視窗幀率和SurfaceView視窗幀率。

在什麼情況下會出現兩種類型視窗都有的情況呢?一般是遊戲類型、直播類、視屏流、小遊戲等類型應用會出現有兩種視窗。特殊情況下,可能會出現多個Activity和多個SurfaceView,對統計幀率造成很大困難,需要一定政策擷取幀率。

遊戲、直播、視訊、小遊戲等類型應用,PerfDog預設擷取的是SurfaceView的FPS。其他傳統應或Web用擷取的是Activity幀率。

同時PerfDog高階功能,支援使用者自己選擇視窗類型幀率,特别針對小程式,小遊戲等,能更精準測試目标視窗幀率,如下圖(微信小遊戲-歡樂鬥地主)

小遊戲、直播、視訊、遊戲等類型應用,請選擇SurfaceView

PerfDog4.0探索,支援使用者自建web雲

我們來總結一下:

如果我們子程序的View是SurfaceView,那麼子程序會獨享一個Surface,不與主視窗共享Surface;

PerfDog4.0探索,支援使用者自建web雲
PerfDog4.0探索,支援使用者自建web雲

這裡拿一個視訊頁舉例,主線程和子線程實際上可以了解為疊加的狀态,二者互不幹擾;也就是說我們擷取主線程的幀率是下面主程序的資料,而子程序幀率是中間的一小塊輪播圖的幀率資料,二者是獨立的

三,使用者自建Web雲擷取性能資料

在更新4.0後,我們在setting界面可以發現可以自定義上傳的雲平台了

PerfDog4.0探索,支援使用者自建web雲

這裡要怎麼使用呢,如果我們有自己的雲平台,那我們自定義一個連結請求就可以了;

下面我用Tornado架構做個簡單的例子

首先定義路由:

 (r"/", GetPerfDogData),
 (r"/icon", GetPerfDogIcon),
 (r"/screenshots", GetPerfDogScreenShots),
 (r"/done", GetPerfDogDone),           

複制

接下來處理方法

class GetPerfDogData(tornado.web.RequestHandler):
    """
    :fuc:擷取PerfDog性能資料
    """
    def post(self):
        data = self.request.body.decode('utf8')
        data = parse.unquote(data)
        print("性能資料:",data)
        self.finish(
            {
                "errCode": 0,
                "errStr": "",
                "reportId": ""
        })           

複制

完整代碼:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import tornado.web, tornado.ioloop
from urllib import parse

def Set_Ima(data):
    with open("img.jpg", "wb") as f:
        f.write(data["body"])  # 生成一張img.jpg的圖檔
class GetPerfDogData(tornado.web.RequestHandler):
    """
    :fuc:擷取PerfDog性能資料
    """
    def post(self):
        data = self.request.body.decode('utf8')
        data = parse.unquote(data)
        print("性能資料:",data)
        self.finish(
            {
                "errCode": 0,
                "errStr": "",
                "reportId": ""
        })
class GetPerfDogIcon(tornado.web.RequestHandler):
    """
    :fuc:擷取PerfDog應用圖示
    """
    def put(self):
        data = self.request.files['icon']
        print("Icon圖示:", data)
        for imadata in data:
            Set_Ima(imadata)
        self.finish(
            {
                "errCode": 0,
                "errStr": "",
                "reportId": ""
        })
class GetPerfDogScreenShots(tornado.web.RequestHandler):
    """
    :fuc:擷取PerfDog測試過程中生成的應用截圖
    """
    def post(self):
        pass
class GetPerfDogDone(tornado.web.RequestHandler):
    """
    :fuc:完成上傳測試資料
    """
    def put(self):
        pass

if __name__ == '__main__':
    CONTENTS_LIST = []
    settings = {
        'template_path': 'template',
        'static_path': 'static',
    }

    application = tornado.web.Application([
        (r"/", GetPerfDogData),
        (r"/icon", GetPerfDogIcon),
        (r"/screenshots", GetPerfDogScreenShots),
        (r"/done", GetPerfDogDone),
    ], **settings)
    application.listen(8868)
    tornado.ioloop.IOLoop.instance().start()           

複制

運作腳本,把ip位址+端口号填進server裡,如果有域名就填寫域名,

PerfDog4.0探索,支援使用者自建web雲

點選上傳資料,就可以看到資料資訊啦

PerfDog4.0探索,支援使用者自建web雲
PerfDog4.0探索,支援使用者自建web雲

這裡貼出一下目前的接口文檔:

接口說明
baseURL
需要配置,例如:http://abc.com/report
開始上傳測試資料
•    path:
•    method: post
•    header:
–    Content-Type: 'multipart/form-data'
•    req
–    file_format: json/pb
–    data: file
•    resp
     {
    errCode: 0,
    errStr: "",
    reportId: ""
}
上傳測試過程中生成性能資料,如fps、卡頓等等
設定測試應用圖示
•    path: /icon
•    method: put
•    header:
–    Content-Type: 'multipart/form-data'
•    req
–    reportId
–    icon: file
•    resp
     {
    errCode: 0,
    errStr: ""    
}
上傳測試過程中生成的應用截圖
•    path: /screenshots
•    method: post
•    header:
–    Content-Type: 'multipart/form-data'
•    req
–    reportId
–    file1: file
–    file2: file
–    file3: file
–    file4: file
–    file5: file
–    ...
•    resp
     {
    errCode: 0,
    errStr: ""    
}
一次可以上傳多張 或者使用zip壓縮多張圖檔上傳
完成上傳測試資料
•    path: /done
•    method: put
•    header:
–    Content-Type: 'multipart/form-data'
•    req
–    reportId
•    resp
     {
    errCode: 0,
    errStr: ""    
}           

複制

注意這是4.0版本的接口文檔哦。以後沒準會變得喲 !

再貼一份flask架構完整的demo吧

report檔案

# coding: utf-8

import os
import uuid

from werkzeug.utils import secure_filename


class Report(object):
    def __init__(self, base_dir):
        self.base_dir = base_dir

    def set_data_by_pb(self, file):
        filename = self.get_filename('data.pb')
        file.save(filename)

    def set_data_by_json(self, file):
        filename = self.get_filename('data.json')
        file.save(filename)

    def set_icon(self, file):
        filename = self.get_filename('icon.png')
        file.save(filename)

    def add_screenshots(self, files):
        for file in files:
            filename = self.get_filename(secure_filename(file.filename))
            file.save(filename)

    def done(self):
        filename = self.get_filename('done')
        with open(filename, 'wb'):
            pass

    def get_filename(self, filename):
        return '%s%s%s' % (self.base_dir, os.sep, filename)


class ReportManager(object):
    def __init__(self):
        self.base_dir = os.path.split(os.path.realpath(__file__))[0] + os.sep + 'data'
        if not os.path.exists(self.base_dir):
            os.mkdir(self.base_dir)

    def create_report(self):
        report_id = str(uuid.uuid4())
        report_dir = self.get_report_dir(report_id)
        os.mkdir(report_dir)
        return report_id, Report(report_dir)

    def get_report(self, report_id):
        report_dir = self.get_report_dir(report_id)
        return Report(report_dir)

    def get_report_dir(self, report_id):
        return '%s%s%s' % (self.base_dir, os.sep, report_id)


reportManager = ReportManager()


def create_by_pb(file):
    (report_id, report) = reportManager.create_report()
    report.set_data_by_pb(file)
    return report_id


def create_by_json(file):
    (report_id, report) = reportManager.create_report()
    report.set_data_by_json(file)
    return report_id


def set_icon(report_id, value):
    report = reportManager.get_report(report_id)
    report.set_icon(value)


def add_screenshots(report_id, screenshots):
    report = reportManager.get_report(report_id)
    report.add_screenshots(screenshots)


def done(report_id):
    report = reportManager.get_report(report_id)
    report.done()           

複制

demo檔案

#! /usr/bin/python
# coding: utf-8

from flask import Flask, request, jsonify

import report

app = Flask(__name__)


@app.route('/report', methods=['POST'])
def create_report():
    file_format = request.form['file_format']
    if file_format == 'pb':
        report_id = report.create_by_pb(request.files['data'])
    elif file_format == 'json':
        report_id = report.create_by_json(request.files['data'])

    if report_id is None:
        res = {'errCode': -1, 'errStr': 'invalid arguments'}
    else:
        res = {'errCode': 0, 'errStr': 'success', 'reportId': report_id}

    return jsonify(res)


@app.route('/report/icon', methods=['PUT'])
def set_icon():
    report_id = request.form['reportId']
    report.set_icon(report_id, request.files['icon'])
    return jsonify({'errCode': 0, 'errStr': 'success'})


@app.route('/report/screenshots', methods=['POST'])
def add_screenshots():
    report_id = request.form['reportId']
    files = []
    for name in request.files:
        files.append(request.files[name])

    report.add_screenshots(report_id, files)
    return jsonify({'errCode': 0, 'errStr': 'success'})


@app.route('/report/done', methods=['PUT'])
def done():
    report_id = request.form['reportId']
    report.done(report_id)
    return jsonify({'errCode': 0, 'errStr': 'success'})           

複制

好啦,可以開始愉快的玩耍啦!

延伸閱讀:

如何自定義資料檔案伺服器位址,建構自己web雲

https://bbs.perfdog.qq.com/detail-217.html

點贊(0)