用 SoloX 测 APP 性能:5 步定位 CPU / 内存瓶颈

前言

在移动应用开发与测试中,性能监测是保障用户体验的关键环节。本文将详细介绍如何结合Python、uiautomator2与SoloX工具,对DeepSeek应用进行自动化操作并同步监测其性能指标,为APP性能优化提供数据支持。


SoloX 工具简介

1. 功能背景

SoloX 是一款 Android/iOS 应用性能监控工具,主要用于:

  • 实时采集 应用的 CPU、内存、GPU、FPS、网络、电量等性能数据。
  • 自动化测试 结合 ADB(Android Debug Bridge)或 iOS 工具链,无需 Root/Jailbreak。
  • 性能分析 提供图表、日志、报告,帮助开发者定位卡顿、内存泄漏、高耗电等问题。

适用场景

  • 移动应用性能测试(如游戏、社交 App)。
  • 竞品性能对比分析。
  • 持续集成(CI)中的自动化性能监控。

2. 实现逻辑

SoloX 的核心实现分为 数据采集数据分析 两部分:

(1)数据采集
  • Android 端
    • 通过 ADB 命令 获取系统级数据(如 dumpsys cpuinfo, procstats)。
    • 使用 Android 性能接口(如 SurfaceFlinger 获取 FPS)。
    • 注入 Java Agent(可选)监控应用内方法耗时。
  • iOS 端
    • 依赖 Xcode Instruments(如 sysmon 采集 CPU/Memory)。
    • 通过 libimobiledevice 工具链获取基础数据。
(2)数据分析
  • 实时计算:对采集的原始数据(如 CPU%、内存 MB)进行聚合计算(平均值、峰值)。
  • 可视化展示:生成曲线图(如 FPS 波动)、表格(如 Excel 报告)。
  • 卡顿检测:基于 FPS 下降主线程阻塞时间 判定 Jank(卡顿)。

3. 关键特性

特性 说明
低侵入性 无需修改应用代码,通过系统接口采集数据。
多维度监控 覆盖 CPU、内存、GPU、网络、电量、温度等全链路指标。
跨平台支持 支持 Android 和 iOS(部分功能需适配)。
自动化报告 生成 Excel/JSON/图表,便于团队协作分析。

4. 对比同类工具

工具 优势 局限性
SoloX 轻量级、支持 iOS/Android 深度定制需结合其他工具
Perfetto 系统级追踪(如内核事件) 配置复杂,适合高级用户
GT 腾讯开源,功能全面 仅支持 Android

总结

SoloX 通过 系统接口+自动化脚本 实现性能数据采集,并以可视化报告帮助开发者快速定位问题,适合移动端性能优化初、中级需求。solox和weditor一样。本质是一个 Web 应用(基于 Python 的 Flask 框架),通过浏览器访问使用。所以启动后,会在浏览器中打开solox的网页界面,如下图:
image


示例测试场景

本文将以 DeepSeek 应用的 5 次问答场景为实例,实战演示如何使用 SoloX 进行性能测试与分析。



前置准备

1、手机安装DeepSeek应用APP

确保测试手机已成功安装DeepSeek应用,版本建议为最新稳定版,以保证测试环境的一致性。

2、安装并配置adb环境

  • Android SDK Platform Tools下载链接:https://adbdownload.com/
  • 解压到任意目录(如:C:\adb\adb.exe),将该目录(C:\adb\)添加到系统环境变量PATH中。
  • 终端输入 adb version 验证,显示版本信息即配置成功。
  • 手机与电脑连接后,开启开发者模式中的USB调试,授权设备调试。
  • 输入 adb devices,若出现设备序列号,则说明连接成功(需记录该序列号,后续会用到)。

3、安装并配置PyCharm工具 + Python环境

4、安装配置UI自动化测试环境

uiautomator2是Android原生UI自动化工具,通过ADB将Python指令发送到手机的atx-agent服务,实现点击、输入等操作;weditor是可视化UI元素查看器,类似浏览器F12工具,用于抓取页面元素。

打开命令行(Win+R输入cmd),在CMD命令行中 依次 执行以下命令:

pip install uiautomator2==3.4.0  # 作者验证可用版本
pip install weditor  # 安装weditor
python -m uiautomator2 init  # 初始化设备,自动部署atx-agent服务

5、Python的APP UI自动化脚本编写

以下是通过Python+uiautomator2实现的自动化脚本,功能为向DeepSeek发送问题并重复5次:

import time
import datetime
import uiautomator2 as u2
import subprocess
from loguru import logger


def element_operation(element, element_name, pre_wait, post_wait):
    """
    元素操作前后等待一段时间
    :param element: 元素
    :param element_name: 元素命名
    :param pre_wait: 操作前等待时间
    :param post_wait: 操作后等待时间
    :return: bool 操作是否成功
    """
    try:
        # 等待元素加载
        if element.wait(timeout=pre_wait):
            element.click()
            logger.info(f"点击元素[{element_name}]")
            time.sleep(post_wait)
            return True
        else:
            logger.warning(f"在 {pre_wait} 秒内未找到元素[{element_name}]")
            return False
    except Exception as e:
        logger.error(f"点击元素[{element_name}]时出现异常: {e}")
        return False


def chat_operation(device):
    """
    执行聊天操作流程
    :param device: uiautomator2设备对象
    :return:
    """
    # 定义所有UI元素
    app_package = "com.deepseek.chat"
    app_activity = "com.deepseek.chat.MainActivity"
    input_box = device(text="给 DeepSeek 发送消息")  # 输入框
    send_button = device(description="发送")  # 发送按钮
    copy_button = device(description="复制")  # 复制按钮(用于检测回答完成)

    for n in range(5):  # 执行5次问答
        logger.info(f"===== 开始第 {n + 1} 次问答 =====")

        # 启动应用
        device.app_start(app_package, app_activity)
        time.sleep(3)  # 等待应用初始化

        # 执行问答流程
        question = f"你好"
        if element_operation(input_box, "输入框", 3, 1):
            device.send_keys(question, clear=True)
            time.sleep(1)

            # 点击指定坐标收起输入法(相对坐标,适配不同屏幕)
            device.click(0.638, 0.975)
            logger.info("点击指定位置收起输入法")
            time.sleep(1)  # 等待输入法收起

            if element_operation(send_button, "发送按钮", 2, 1):
                # 检测回答是否完成(通过复制按钮)
                start_time = time.time()
                timeout = 60
                answer_complete = False

                while time.time() - start_time < timeout:
                    if copy_button.exists:
                        answer_complete = True
                        break
                    time.sleep(1)

                if answer_complete:
                    logger.info("回答完成")
                else:
                    logger.warning("问答超时")

        # 关闭应用(可选)
        # device.app_stop(app_package)
        # logger.info("应用已关闭")

        time.sleep(1)  # 循环间隔

    logger.info("===== 所有问答已完成 =====")


if __name__ == '__main__':
    # 连接设备
    d = u2.connect()

    # 配置日志记录器(与源代码相同格式)
    device_id = d.device_info.get('serial')
    now_time = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
    logger.add(
        f"{device_id}_{now_time}.log",
        rotation="500 MB",
        retention="7 days",
        format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}"
    )

    # 执行主流程
    chat_operation(d)

6、搭建性能测试依赖

打开命令行(Win+R输入cmd),执行以下命令安装依赖:

pip install -U solox  # 安装SoloX核心库
pip install loguru  # 安装日志输出库
  • 验证安装:
    pip list | findstr "solox"(查看solox版本)
    pip list | findstr "loguru"(查看loguru版本)
  • 也可从GitHub下载SoloX:https://github.com/smart-test-ti/SoloX(推荐使用pip安装)

开始运行环境

获取设备ID与应用包名

  1. 执行 adb devices -l 命令,获取当前连接设备的设备ID
  2. 打开DeepSeek应用,执行 adb shell dumpsys window | findstr mCurrentFocus,返回信息如:
    mCurrentFocus=Window{773270c u0 com.deepseek.chat/com.deepseek.chat.MainActivity}
    其中,com.deepseek.chat 是应用包名/ 后为当前Activity名称。

启动SoloX

在CMD中执行 python -m solox,SoloX会以Web应用形式在浏览器中打开(基于Flask框架)。

配置SoloX

  • 设备选择:下拉框中选择目标设备ID(自动识别已连接设备)。
  • 包名选择:下拉框中选择前面获取的应用包名(com.deepseek.chat)。
  • 进程号:自动填充当前应用的进程号,无需手动输入。
    image

正式运行

启动性能监控

点击SoloX右上角的Start按钮,开始监控应用性能。
image

执行自动化脚本

接下来在PyCharm中运行前文编写的UI自动化脚本,脚本将自动完成5次问答操作。

停止监控与数据保存

  • 脚本执行结束后,点击SoloX右上角的Stop按钮,停止数据采集。
  • 进入报告查看页面(Report),点击Export按钮下载性能报告,记录下载路径。
  • 点击Analyse进入图表分析页面,点击右上角Save image保存图表(建议与报告存放在同一目录)。
    image
    image
    image

性能报告解读

报告文件说明

SoloX生成的性能报告包含以下文件,分别记录不同维度的性能数据:

文件名 功能描述
upflow.log 记录应用上行网络流量(KB/s),分析上传数据实时波动。
apm_xxxx-xx-xx-xx-xx-xx.xls 汇总所有性能数据的Excel文件,含CPU、内存、电池、网络等工作表,为核心分析文件。
end_net.json 测试结束时的总网络流量统计(发送/接收),用于对比测试前后消耗。
gpu.log 记录GPU占用率(%),分析图形渲染负载。
battery_level.log 记录电池电量百分比(%),监控电量消耗是否异常。
battery_tem.log 记录电池温度(℃),检测设备是否过热。
cpu_app.log 记录应用进程的CPU占用率(%),分析应用自身的CPU负载。
result.json 测试的元数据(应用名、设备型号、时间等),记录测试环境信息。
mem_total.log 记录物理内存使用量(MB),检测内存泄漏或高占用。
current_disk.log 测试结束时磁盘分区的使用情况,检查存储空间是否不足。
pre_net.json 测试开始时的总网络流量统计(发送/接收),与end_net.json对比计算流量消耗。
fps.log 记录屏幕刷新率(帧/秒),分析界面流畅度。
mem_swap.log 记录交换分区(Swap)使用量(MB),判断内存压力是否触发交换。
cpu_sys.log 记录系统总CPU占用率(%),分析系统整体负载。
initail_disk.log 测试开始时磁盘分区的使用情况,与current_disk.log对比存储变化。
jank.log 记录卡顿次数(Jank值),量化界面卡顿情况。
downflow.log 记录应用的下行网络流量(KB/s),分析下载数据的实时波动。

性能优劣判断标准

1. CPU性能

  • 应用CPU(cpu_app)
    优:均值<5%(轻载),峰值<20%;
    劣:持续>10%(如16:56:01.783062=9.56接近临界)。
  • 系统CPU(cpu_sys)
    优:均值<20%,无持续峰值;
    劣:峰值>30%(如16:56:04.818606=31.19需优化)。

2. 内存性能

  • 物理内存(mem_total)
    优:平稳无泄漏(如从140MB→151MB,轻微增长属正常);
    劣:持续上升(如>200MB可能存在泄漏)。
  • 交换内存(mem_swap)
    优:接近0(如0.39~0.4MB属正常);
    劣:>10MB(频繁交换会导致卡顿)。

3. GPU与渲染

  • GPU占用(gpu)
    优:<10%(如峰值22.99%仅初始较高,后续4~6%属良好);
    劣:持续>20%(可能导致过热或卡顿)。
  • 帧率(fps)
    优:稳定60fps(人类感知流畅阈值);
    劣:波动大(如16:55:42.698064=16掉帧严重)。

4. 网络与耗电

  • 流量(upflow/downflow)
    优:传输量小(如总接收7.6MB属正常);
    劣:突发流量过大(如16:56:36.002737=11.32KB/s上行突发)。
  • 电池(battery_level/tem)
    优:电量稳定(如全程100%),温度<35℃(如27.9~28.4℃属正常);
    劣:温度>40℃或电量骤降。

5. 卡顿分析(jank.log)

  • 优:Jank值≤1(无卡顿);
  • 劣:Jank≥3(如16:55:42.698064=5属严重卡顿)。

图表报告解读

1. CPU性能

  • 应用CPU平均占用:4.46%(低负载,表现良好)。
  • 系统CPU平均占用:19.03%(正常范围,但峰值32%需关注是否为偶发高负载)。

2. 内存使用

  • 物理内存(Total):平均146.43MB(无泄漏风险)。
  • 交换分区(Swap):0.39MB(几乎未使用,内存压力低)。

3. 渲染性能

  • FPS平均:39.82帧/秒(未达60fps理想值,存在卡顿)。
  • Jank(卡顿次数):77次(需优化界面渲染逻辑)。

4. 电池与温度

  • 电量:全程100%(未耗电,可能因测试时间较短)。
  • 温度:28.1℃(正常,无过热)。

5. 网络流量

  • 发送(Send):+0.05MB(上传数据极少)。
  • 接收(Receive):+0.13MB(下载数据量正常)。

6. GPU占用

  • 平均占用:5.37%(低负载,图形处理压力小)。

关键问题

  • 帧率不足(FPS均值39.82):需检查主线程阻塞或复杂UI渲染。
  • 卡顿频繁(Jank=77):结合CPU峰值排查代码热点。
  • 其他指标(内存、网络、电池)均表现正常,建议优先优化渲染性能。

结语

亲爱的朋友:
希望本文中描述的问题以及解决方案,可以帮助到您。当然,我们深知,问题和挑战总是层出不穷,新的情况也在不断涌现。如果读者朋友您有更好的方案,或者在实际应用中发现了文中的不足之处,请不吝分享您的宝贵建议。诚挚地邀请每一位读者加入我们的行列,共同完善这份教程。
感谢您的阅读与支持!

Dear friends,
We hope that the questions and solutions presented in this article can be of assistance to you. Of course, we are fully aware that problems and challenges are always emerging in an endless stream, and new situations are constantly arising. If you, our readers, have better solutions or have discovered any deficiencies in this article through practical application, please do not hesitate to share your valuable suggestions with us. We sincerely invite every reader to join us in continuously improving this tutorial.
Thank you for your reading and support!
See you, Parting is for better meeting!

posted @ 2025-08-11 21:06  xiaodi888  阅读(415)  评论(0)    收藏  举报