[译]Android 模拟器:Project Marble 中的改进

这是 Android Studio 团队一系列博客文章中第三篇,深刻探讨了 Project Marble 中的细节和幕后状况。本文是由模拟器团队的 Sam Lin(产品经理),Lingfeng Yang(技术主管)和 Bo Hu(技术主管)撰写的。html

今天咱们很高兴地向您介绍咱们在 Project Marble 期间在 Android 模拟器上取得的最新进展。咱们的核心目标之一是使 Android 模拟器成为应用程序开发的必选设备。物理 Android 设备很是棒,但咱们的目标是增长功能和性能,使您在开发和测试 Android 应用程序时更加高效。前端

咱们据说不少应用程序开发者喜欢咱们最近对模拟器所作的改进,从 2 秒的启动时间,GPU 图形加速,再到屏幕快照。然而,咱们也据说 Android 模拟器消耗了您开发电脑上的太多系统资源。为了解决这个问题,咱们在 Project Marble 中建立了一个任务来优化 Android 模拟器的 CPU 使用率。在过去几个月的 Project Marble 中,在不违背本来设计原则的状况下,Android 模拟器的能效和绘制速度有了显著提高。在本文中,咱们将介绍到目前为止在 Canary Channel 上 Android Emulator 28.1 发布的一些进展。android

在减小开销的同时保持本来设计原则

Android 模拟器的最大好处在于为开发者提供了一种可扩展的方法,经过各类设备配置和屏幕分辨率来测试最新 Android API,而无需为每一个配置购买物理设备。所以,在 Android 模拟器上测试应用程序应该尽量贴近在物理设备上的测试,并同时保持虚拟设备的优点。ios

为了支持最新的系统映像,咱们特地设计一个尽量接近物理设备的 Android 模拟器,而不仅是一个仿真器,这种方法能够确保 API 的正确性以及 Android 系统行为和交互的高保真度。当一个新的 Android 版本推出时,咱们只须要确保咱们的硬件抽象层(HALs)和内核与模拟器和新的系统映像兼容,而不须要从头开始为新的 Android 版本从新实现 Android API 中的全部更改。这种体系结构最终大大地加快了模拟器采用新的系统映像的速度。git

然而,这种完整的系统模拟方法在 CPU 周期和内存访问上的开销都会增长。相比之下,基于模拟器的方法在主机系统上包装相似的 API,开销可能会更低。所以,咱们的挑战在于,在下降 CPU 和内存开销的同时,保持完整系统模拟的准确性和维护优点。github

对 Android 模拟器架构的研究

Android 模拟器在称为 Android 虚拟设备(AVD)的虚拟机上运行 Android 操做系统。AVD 包含了完整的 Android 软件栈,运行时就像在物理设备上同样。整体架构图以下。shell

因为整个 Android 操做系统的运行和主机的操做系统彻底分离,所以运行 Android 模拟器可能会致使主机机器上的后台活动,即使没有任何输入。在进行了一些技术调查以后发现,当 AVD 空闲时,以下一些任务是 CPU 周期的主要消耗者:

  • Google Play Store —— 当有新版本时,应用程序会自动更新。
  • 后台服务 —— 当它认为设备在充电时,一些响应式的服务会使 CPU 使用率保持在较高水平。
  • 动画 —— 例如实况壁纸

对于这些领域咱们进行了更深刻的技术研究并找到了如下 5 个解决方案来优化 Android 模拟器。后端

  1. 默认电池模式
  2. 模拟器的暂停/恢复
  3. 减小绘制调用的开销
  4. 减小 macOS 上主循环的 IO 开销
  5. Headless 构建

改进 #1 —— 默认电池模式

以前,Android 模拟器把 AVD 的电池模式设置为充电模式。通过深思熟虑的讨论和数据分析,咱们得出结论,最好将 AVD 默认设置为电池模式。由于大多数 Android framework,服务和应用程序都通过了优化以节省电池寿命,这些优化都只在设备(物理设备或虚拟设备)认为它在使用电池而不是充电时才开始。android-studio

然而,仅仅默认 AVD 使用电池还不够。由于处于电池模式会致使屏幕在一段时间以后自动关闭。这对于在笔记本电脑或者台式机上使用 Android 模拟器的用户来讲会有一点困惑,由于他们指望应用程序不会随机进入睡眠状态,须要被唤醒。为了防止这种状况,Android 模拟器将在每次冷启动完成时用 ADB shell 命令将屏幕关闭的时间设置为最大值(~24 天)。网络

有了这些改变,Google Play Store 不会在电池模式再自动更新应用程序,避免了系统开销。然而,在切回充电模式以后,[应用程序的自动升级] (support.google.com/googleplay/…) 仍然能够被触发。这实际上让开发者能够控制什么时候自动更新应用程序。这能够防止对关键用例的干扰,好比当用户只想构建和测试单个应用程序的时候。下表比较了电池模式和充电模式下的 CPU 使用情况:

改进 #2 —— 模拟器暂停/恢复

在不少状况下,你可能须要当即保证模拟器不会在关键任务期间(好比编辑/生成/部署)在后台占用 CPU 周期。为了解决这个问题,咱们正在研究一个控制台命令和接口,用于彻底暂停模拟器 CPU 的使用。这能够经过如下控制台命令显示暂停/恢复 AVD 来完成。

这里的挑战是如何协调 Android Studio 和 Android 模拟器状态的改变。因此当在部署应用程序时,咱们会自动恢复模拟器。咱们还在研究这个机制,很高兴听到您的想法和反馈

改进 #3 —— 减小绘制调用的开销

咱们还对 Android 模拟器的引擎进行了修改,使其更高效的绘图,从而在测试屏幕上有不少对象的图形密集型应用程序时得到更流畅的用户体验。好比,模拟器 v28.1.10 在GPU 模拟压力测试应用程序上的绘制速度比 v28.0.23 提高了 8%。咱们还在 Android Q 上进行进一步的优化,并将在 Android Q preview 期间共享其余更新。

改进 #4 —— 减小 macOS 上主循环的 IO 开销

完整的系统模拟器必须维护一些方法,以通知虚拟操做系统磁盘和网络上的 I/O 已经完成。Android 模拟器基于 QEMU,使用主循环和 IO 线程来作到这一点。这在 Linux 和 Windows 上的开销都比较低。然而在 macOS 上咱们看到,因为使用了 select() 系统调用,主循环的 CPU 使用率更高。这一般没有高效的实现方式。macOS 提供了一个低开销的方式来等待 I/O:kqueue。咱们发现当前基于 select() 主 I/O 循环,能够替换为基于 kqueue 的主 I/O 循环。这大幅下降了主循环中的 CPU 使用率,从 10% 下降到 3%。因为这并不能说明全部空闲 CPU 使用率的状况,下面的图表没有显示太多的变化。然而,这种差别仍然是能够观察到的。

改进 #5 —— Headless 构建

对于那些在 Android 应用程序构建中使用持续集成系统的用户,咱们也在这方面进行了性能改进。经过关闭 Android 模拟器的用户界面,您可使用新的模拟器 Headless 模式。这种新的模式在后台运行测试,并使用更少的内存。它大概还须要 100MB,主要是由于咱们在用户界面使用的 Qt 库没有加载。当不须要用户界面和交互时,这也是运行自动化测试的一个好选择。增量能够相似以下那样启动两个模拟器 AVD 实例来测量。注意,命令行示范显式地指定主机的 GPU 模式,以确保在相同的条件下进行比较。

接下来

要使用本文中介绍的性能和资源优化,请在 Canary Channel 下载 Android Emulator 28.1。咱们很高兴能与您分享此次提早的进展,但咱们确定尚未完成。咱们今天邀请您尝试 Android Emulator 的最新更新,并向咱们发送您的反馈

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索