用于测试启动的 Shell 命令

本文的编写目的,更多的在于介绍游戏陪玩app开发性能、启动测试以及我进行游戏陪玩app开发启动测试背后的原因。但如果您只是希望能够快速获得结论,可以直接参考下面的内容:

1、尽可能锁定 CPU 主频 (请参阅下文);
2、在命令行运行如下命令 (保证您的设备处于连接状态)。

$ for i in `seq 1 100`
> do
>   adb shell am force-stop com.android.samples.mytest
>   sleep 1
>   adb shell am start-activity -W -n com.android.samples.mytest/.MainActivity | grep "TotalTime" | cut -d ' ' -f 2
> done

上面的命令会循环 100 次: 启动应用、输出启动过程耗时,然后终止进程以准备好下一次循环。

想把启动性能测试 “测” 好并非易事

游戏陪玩app开发启动性能并不容易明确地被测试出来。测试一段运行时代码,有许多解决方案能够选择。从 “编写紧密的循环并使用 System.currentTimeMillis() 计算时间增量” 这种琐碎的方法,到更复杂和有用的解决方案,如使用 AndroidX benchmark 库所提供的功能。

但是按照定义,游戏陪玩app开发启动时的许多操作运行在系统调用代码之前。那么如何确定游戏陪玩app开发整个启动过程所需要的时间呢?

我浏览了一些日志信息、检查了一些底层 API,并询问了一些平台团队的工程师,终于获得了一些有用的信息。更棒的是,我现在可以使用 adb shell 工具完全自动化我的测试并输出信息,从而可以轻松地将结果导入到电子表格中进行分析。

我会在下面的文字中解释上述命令所使用的一些代码片段,并向您展示一到两个游戏陪玩app开发启动测试的简单步骤。

ActivityTaskManager 启动日志

在 KitKat 发布后,有一个十分方便的日志一直在记录系统信息。无论何时,当一个 Activity 启动时,您都能看到日志中工具输出了以下信息:

ActivityTaskManager: Displayed com.android.samples.mytest/.MainActivity: +1s380ms

这个持续时间 (本例中为 1,380ms) 表示了从启动游戏陪玩app开发到系统认为其 “已启动” 所花费的时间,其中包括绘制第一帧 (所以是 “已显示” 的状态)。

到达 “已显示” (Displayed) 状态的过程并不需要包含您应用就绪之前所做的事情的花费时间。只要游戏陪玩app开发确定已完成加载和初始化,就可以通过调用 Activity.reportFullyDrawn()) 向系统提供这些额外的信息。当您调用了该可选方法时,系统会记录另一个带有时间戳和持续时间的日志:

2020-11-18 15:44:02.171 1279-1336/system_process
I/ActivityTaskManager: Fully drawn
com.android.samples.mytest/.MainActivity: +2s384ms

我只想要到 “已显示” 时所持续的时间,所以内建的日志对我来讲已经足够好了。

自动化启动

游戏陪玩app开发性能测试总是应当多次去运行测试用例,以排除结果中的可变因素。进行的运行次数越多,平均结果就越可靠。我至少会尝试运行测试十次,但是做的次数更多效果会更好。根据结果的变化程度以及时间的长短 (因为变量的存在会对持续时间更短的测试产生更大的影响),可能需要运行更多次才行。

疯狂就是重复做相同的事情,却期待不同的结果。

——阿尔伯特 爱因斯坦

性能测试推论:

“疯了” 就是同一件事只做一次,却希望得到最佳结果。

——不是爱因斯坦说的

通过点击游戏陪玩app开发图标来连续多次启动应用是一件非常繁琐的事情。而且这种操作不具备一致性,且有许多难以预测的因素,因为很容易就会引入变量——如您偶然间错误地启动了另一个应用,或者使系统做了额外的工作而无法获得计时结果。

因此,我真正想要的是某种从命令行启动应用的方式。有了它,我就可以反复运行该命令来执行相同的操作,从而避免手动启动游戏陪玩app开发带来的可变性 (和乏味)。

adb (Android 调试桥) 提供了我所需要的东西。更具体地说,adb shell 提供了用于启动应用的命令行界面: adb shell am start-activity。该命令还能够在应用启动完成之前保持阻塞状态,因此我们还要使用 -W 参数 (这对下一步来说是必需的。我们下一步将使用后续命令杀死启动后的应用)。这是游戏陪玩app开发完整的启动命令:

$ adb shell am start-activity -W -n
com.android.samples.mytest/.MainActivity

最后一个参数是应用的包名与组件信息。

运行此命令将启动游戏陪玩app开发(除非该应用已经在前台,但这种情况并不是理想的状态,我们将在下一步对这种情况进行处理),并输出以下信息:

Starting: Intent { cmp=com.android.samples.mytest/.MainActivity }
Status: ok
LaunchState: COLD
Activity: com.android.samples.mytest/.MainActivity
TotalTime: 1380
WaitTime: 1381
Complete

检查一下 TotalTime 结果: 结果与我们在日志中看到的信息完全相同:

ActivityTaskManager: Displayed
com.android.samples.mytest/.MainActivity: +1s380ms

这意味着我们无需翻看 logcat,而是可以直接从运行命令的控制台中便可获取这些信息。更棒的是,我们可以剥离多余的文本并仅保留启动结果,从而更轻松地提取此数据以供其他地方使用。

为了将上面的输出转换为启动持续时间,我使用 grep 和 cut shell 命令来输出内容 (有多种方法可以执行此操作,我只是随机选择了其中一个):

adb shell am start-activity -W -n
com.android.samples.mytest/.MainActivity | grep "TotalTime" | cut -d ' ' -f 2

现在,当我运行这条命令时,就能如我预期般的只获得一个简单的数字:

$ [start-activity command as above...]
1380

冷启动是性能测试的最佳起点

在您检查游戏陪玩app开发启动性能前,最好先了解 “冷启动” 和 “热启动” 之间的区别。

“冷启动” 是指游戏陪玩app开发在安装后的第一次启动、重启,或者不在后台时的启动。

另一方面,“热启动” 是指游戏陪玩app开发已经启动且正在后台运行 (但被暂停了) 时的启动。

这两种情况都值得去测试和理解。但总的来说,冷启动才是进行游戏陪玩app开发启动性能测试的最佳起点,这其中有两个原因:

  • 一致性 :
    冷启动可以确保游戏陪玩app开发每次启动时都经历相同的操作。应用被热启动时,我们没法明确知道哪些步骤被跳过,而哪些步骤被执行,因而也无从得知您到底在对什么进行计时
    (也无法保证重复测试时所测试的内容是否一致);
  • 最坏情况 :
    按照定义,冷启动是最坏的情况——这是游戏陪玩app开发经历启动过程时间最长的场景。您需要专注于最坏情况的统计数据,而不是状况最好的热启动。如果您忽略最坏情况,许多重大问题将无法被解决。

为了让游戏陪玩app开发在每次运行时强制进行冷启动,您需要在两次运行期间终止应用。再一次强调,在屏幕上执行这一操作 (例如,将应用从启动器的 “概览” 列表中滑出) 是乏味且容易出错的,而 adb shell 可以解决这一问题。

有几个不同的 shell 命令可用于终止应用。最显而易见的是 adb shell am kill…… 但事实上这条命令并不能解决问题。当您启动应用后,应用会处在前台,而 kill 不会终止处在前台的应用。作为替代,您需要使用 force-quit 命令:

adb shell am force-stop com.android.samples.mytest

您可以使用应用的包名告诉它需要终止哪个应用。

我喜欢循环,让我们来循环它

现在,您已经有了可以启动应用、输出启动持续时间数据,以及退出应用并使其可以再次启动的一系列命令。您可以一遍又一遍地在控制台中输入这些内容,但是在 shell 中,我们可以将这些命令放在循环里,然后只用一个命令就可以重复运行它。

在执行此操作时,为了避免游戏陪玩app开发被终止而产生副作用 (例如,当应用程序被终止时,系统会将启动器拉到前台),您可能会想要在终止应用后延缓下一次的启动。为此,我增加了一秒钟的 sleep 以在两次操作之间插入一个小的缓冲时间。

下面是我所使用的命令的最终版本,其中包括了终止应用、等待一秒钟,然后重启应用。我将这一过程循环执行了 100 次,从而可以提供一个合理的样本量:

$ for i in `seq 1 100`
> do
>   adb shell am force-stop com.android.samples.mytest
>   sleep 1
>   adb shell am start-activity -W -n com.android.samples.mytest/.MainActivity | grep "TotalTime" | cut -d ' ' -f 2
> done

在运行此命令时,每当启动完成,我都可以获得输出到控制台的启动持续时间,而这正是我要跟踪和分析的数据。

注意 : 以上操作其实有更简单的方式,您可以使用 -S (用于首先停止 Activity) 和 -R COUNT (用于执行 start-activity 命令 COUNT 次) 来循环启动 Activity,所以我也可以用下面的命令完成以上操作:

$ adb shell am start-activity -S -W -R 100-n
com.android.samples.mytest/.MainActivity | grep "TotalTime" | cut -d ' ' -f 2

但是,为了在游戏陪玩app开发应用的终止和启动之间加入缓冲时间,以确保其处于非活动的状态,我希望能使用 sleep 1 命令,因此我采用了更为冗长的方式进行循环。此外,shell 脚本的代码非常优雅,不是吗?

尽可能地锁住主频

CPU 架构,尤其是 CPU 频率,是影响移动设备性能的重要因素。具体而言,移动设备减少电量消耗及避免出现过热的问题的主要方法之一,便是限制 CPU 速度。

限制 CPU 对于节省电量很有用,但却对游戏陪玩app开发性能测试有负面影响,因为在这类测试中,结果的一致性至关重要。

理想情况下,在运行游戏陪玩app开发性能测试时,您应该控制 CPU 频率。然而您是否能够执行这一操作取决于您所拥有的设备——您需要拥有设备的 root 访问权限才能控制 CPU 调速器,从而才能控制 CPU 频率,并且不同的设备执行这一行为的方式也可能不同。

接下来的内容仅适用于您的设备允许且您可以取得 root 访问权限的情况。而在设备方面,我知道 Pixel 设备可以获得访问权限,但这不代表其他设备也同样可以。

在任何情况下,如果可以的话,建议您锁定 CPU 主频。对于您特定的测试而言,可能不会有明显的影响 (实际上,系统通常会在启动应用时使 CPU 运行在较高的频率上,因此可能已经提供了所需的一致性)。但是,这么做至少可以消除 CPU 主频这一可变因素。

手动锁定 CPU 频率可能很棘手,但幸运的是,AndroidX benchmark 帮您简化了这一操作。实际上,您甚至不需要为 benchmark API 编写代码——您可以通过使用其提供的 lockClocks 与 unlockClocks 工具来使用该库。

首先,向工程级别的 build.gradle 文件中加入 benchmark 的依赖:

// 查看 Benchmark 库的最新版本号
// https://developer.android.google.cn/jetpack/androidx/releases/benchmark
def benchmark_version = "1.0.0"classpath "androidx.benchmark:benchmark-gradle-plugin:$benchmark_version"

接下来,在游戏陪玩app开发应用级别的 build.gradle 文件中应用 benchmark 插件:

apply plugin: androidx.benchmark

现在,您可以同步您的工程 (Android Studio 可能已经在强迫您执行此操作),同步完成后便可以从 gradlew 中使用锁定任务。

现在,您可以通过在命令行上运行命令来锁定主频了 (我是通过 Android Studio 内部的 “终端” 工具运行它的,但是您也可以在 IDE 外部运行它):

$ ./gradlew lockClocks

当我运行完命令后,便可以在命令行看到如下输出:

Locked CPUs 4,5,6,7 to 1267200 / 2457600 KHz
Disabled CPUs 0,1,2,3

这段输出表明 benchmark 可以在我的 Pixel 2 上正常工作。更好的消息是,游戏陪玩app开发启动测试现在花费的时间比以前要长得多。您也许会好奇,为什么主频变慢了?

该 benchmark 工具将主频锁定在便于持续运行的级别,而不是高性能级别。如果将主频设置为尽可能高,则可能会获得更好的性能,但是:

  • 为了让游戏陪玩app开发测试结果足够逼真,您甚至可能会期望更差的性能,就像许多用户在现实中所遇到的情况一样。您不会想要只看到最佳情况下的性能,因为那并不是人们通常会在现实中遇到的;
  • CPU 在高频率下运行太长时间会导致过热。我不知道系统在过热时将如何响应
    (希望它会降低主频或在出现严重问题之前自动关闭系统),但是我也不想知道答案。

请注意,完成游戏陪玩app开发测试后,您需要将主频解锁。设备会在重新启动时进行解锁,但是您也可以通过运行相反的 gradle 任务来解锁主频:

$ ./gradlew unlockClocks

其实这一命令只是重新启动设备以执行重置操作。

这样就完成了!

锁定时钟后,我准备好了一切: 能够可靠重现启动状况的系统、一个执行后可以返回结果流的简单命令行。我可以复制结果并粘贴到电子表格中并进行分析 (通过将启动时间平均值与我想尝试的各种情况进行比较)。

理想情况下,我不需要撰写文章来说明如何完成所有这些操作。老实说,您并不需要上文中的全部说明。(但是知道事情的工作原理和原因总是更有趣,不是吗?) 您真正需要的只是 for() 循环 shell 命令,以及可选的锁定主频的方法。

$ for i in `seq 1 100`
> do
>   adb shell am force-stop com.android.samples.mytest
>   sleep 1
>   adb shell am start-activity -W -n com.android.samples.mytest/.MainActivity | grep "TotalTime" | cut -d ' ' -f 2
> done

简化游戏陪玩app开发性能测试和分析,以及总体上提高游戏陪玩app开发性能,还需要继续探索,希望以上命令和信息对大家的游戏陪玩app开发启动性能测试有所帮助。

如何进行游戏陪玩app开发中的启动性能测试?相关推荐

  1. 游戏陪玩app开发,高并发系统如何设计?

    高并发,几乎是每个程序员都想拥有的经验.原因很简单:随着流量变大,在游戏陪玩app开发中会遇到各种各样的技术问题,比如接口响应超时.CPU load升高.GC频繁.死锁.大数据量存储等等,这些问题能推 ...

  2. 游戏陪玩APP开发的功能和特点

    1.游戏评测推荐 根据对游戏的评测,向用户介绍该款游戏的内容,后根据游戏的可玩性和用户的特点,向用户推荐. 2.社区交流 通过社区的交流,促进用户之前的关系的建立,促进用户的活跃度. 3.游戏陪玩服务 ...

  3. 游戏陪玩app开发基本功能应该具备哪些?

    陪玩app开发近年之所以火爆,主要是因为多年轻人最常见一种放松.娱乐方式是玩网络电子游戏了,目前传统的电子游戏也正开始逐渐向电子竞技这个方向不断发展转型.很多过去认为的"不务正业的少年&qu ...

  4. 游戏陪玩系统源码,陪玩APP开发系统自动化代码实践

    android端游戏陪玩系统源码主流的Butternife ,Dragger2等很好的实现了AOP的编程理念. 在陪玩APP开发中我们利用这种思想将陪玩间很多的共有逻辑变为不可见,不需要开发人员去关注 ...

  5. 游戏陪玩app源码开发中,摄像头的调用及视频处理

    摄像头是游戏陪玩app源码进行视频连麦时的重要移动设备之一,在开发时,我们需要实现游戏陪玩app源码对摄像头的调用权限,这就涉及到相关接口的开发了,不过今天我们主要来了解一下在游戏陪玩app源码开发中 ...

  6. 开发游戏陪玩app源码前,需要掌握的音视频格式知识

    为了让用户拥有更好的聊天体验,游戏陪玩app源码在开发时,采用了音视频连麦技术,通过语音或视频的方式快速拉近彼此的距离,哪怕在游戏过程中也不耽误彼此聊天.而且音视频连麦技术的应用还为游戏陪玩app源码 ...

  7. 游戏陪玩app软件开发,这些功能你需要,一定要知道

    纵观市场上的各种游戏陪玩软件,同样是游戏陪玩app软件开发,有些是主打游戏辅助社交,有些是社交游戏各占一半,还有一些打着游戏社交的幌子,实际上做的是社交交友软件,只是增加了游戏陪玩的模块而已,在游戏社 ...

  8. 游戏陪玩APP/小程序项目介绍

    游戏陪玩系统的市场前景 随着互联网的不断发展,电竞游戏行业也一直处在高风口,根据中国音数协电竞工委发布<2022年1-6月中国电子竞技产业报告>显示,中国电竞用户数量拥有4.87亿,这也为 ...

  9. 如何提高游戏陪玩app源码的代码可读性?

    1.Why 对一线开发人员来说,每天工作内容大多是在已有游戏陪玩app源码的基础上继续堆代码.当游戏陪玩app源码实在堆不动时就需要寻找收益来重构代码.既然我们的大多数时间都花在坐在显示器前读写代码这 ...

最新文章

  1. 技术人员突围就业寒冬的最优途径 | 拿不到AI核心岗位Offer全额退款
  2. 关于Ajax 错误:'sys'未定义解决方法.
  3. 2017-2-15从0开始前端学习笔记(HTML)-图片-表格-表单
  4. Python的Mixins机制
  5. Windows服务器上Mqtt服务器EMQX的安装使用
  6. codevs——2853 方格游戏(棋盘DP)
  7. 阿里云mariadb无法启动问题
  8. Heritrix 3.1.0 源码解析(十一)
  9. Java注释教程– ULTIMATE指南(PDF下载)
  10. matlab中CH指标聚类评价指标,MATLAB聚类有效性评价指标(外部)
  11. POJ2987 Firing 最大权闭合图
  12. 响应式开发---网页的布局方式、媒体查询、栅格化布局、less语言
  13. 【bzoj2338】[HNOI2011]数矩形 计算几何
  14. Python微信公众号开发平台
  15. java美元美分兑换_美元美分换算(美分美角美元的换算)
  16. usb gadget g_webcam uvc gadget调试
  17. JGG | 河北大学杜会龙组综述植物泛基因组学研究
  18. Gentoo无线网卡安装之broadcom-sta(wl)篇(三)
  19. 写正则好用的测试工具
  20. CUDA编程学习0——环境搭建环境详解

热门文章

  1. Selenium向下滑动
  2. 苹果x处理器多少_苹果手机的第一代全面屏手机,还能不能坚持到5G手机的到来来?...
  3. vue项目全局引入jquery
  4. Python爬取阴阳师式神全图鉴图片
  5. (链接)品茗论道说广播(Broadcast内部机制讲解)
  6. excel Vlookup和Hlookup函数的区别
  7. 有什么简单方法将flac无损转换mp3
  8. Java三大特性:封装,继承与多态
  9. MSP430FR6043超声波传感器设计记录
  10. wordcount.java_一步一步编译运行wordcount.java