使用Android Studio剖析Unity项目

祝大家有美好的一天! 本文是关于如何使用Android Studio在Android上分析Unity游戏的。 我将讨论如何配置Android Studio并获取最大数据量。 基于结果的分析和结论问题不在本文讨论范围之内。

要求条件


要完全分析应用程序,您需要一部配备Android 8或更高版本(API 27)的手机。 根据经验,使用较旧的Android版本进行分析比尝试好多了。 因此,我建议您购买一整套Nexus设备,因为它们具有旧的硬件和最新的Android更新。

设置一个Unity项目


为了获得结果,您必须以某种方式配置Unity项目。

构建设置中的设置


图片

  • 首先,您应该将构建系统切换为“ Gradle”,然后选中“ Export Project”旁边的框。 因此,我们将获得一个现成的Android Studio项目,并将继续进行介绍。 也可以对完成的APK进行性能分析,但功能有限,需要更多的准备工作。
  • 建议关闭“开发构建”模式,因为探查器中生成的时序将尽可能接近实际时序。

播放器设置中的设置


图片

  • IL2CPP中安装脚本后端 。 如果您离开Mono,那么通过本机分析,我们将看到许多Mono函数,而没有有关它们与C#代码的关系的信息。
  • Android的“ C ++编译器配置”选项无效(在Unity 2018.3中)。 您可以将其放在“发布”中,也许在Unity Android工具链的将来版本中,此设置会影响编译器设置。
  • 建议将“目标体系结构”限制为ARMv7 。 因此,您可以节省编译时间,并可以体验许多架构,有时会使Android Studio陷入僵局。
  • 还值得设置一些其他设置:
    • 安装位置-“首选外部”
    • 互联网访问-“需要”
    • 写入权限-'外部(SDCard)'

    Android Studio和其他探查器使用simpleperf收集统计信息,并且需要访问存储卡来记录临时文件。

准备Gradle项目


安装所有设置后,构建一个Unity项目。 您应该使用Gradle项目获得一个文件夹。
图片

Unity默认情况下会构建一个项目,以便您计划从中构建最终的APK。 因此,已从其中删除所有调试信息,但幸运的是可以将其返回。 为此,您需要使用带有调试信息的版本替换libil2cpp.so和libunity.so。

libil2cpp.so


该文件包含IL2CPP从C#代码生成的所有C ++代码。 Unity会生成分析所需的所有信息,但为了优化APK的大小,它会在构建过程中将其删除。 退货:
  • 转到您的项目文件夹
  • 在其中找到Temp子文件夹,然后转到Temp / StagingArea /符号/ armeabi-v7a子文件夹
  • 在其中寻找“ libil2cpp.so.debug” 。 这是带有调试信息的“ libil2cpp.so”的版本。
  • 现在转到Gradle项目并在其中找到文件夹“ \ src \ main \ jniLibs \ armeabi-v7a”
  • “ libil2cpp.so”替换文件“ libil2cpp.so.debug”

libunity.so


这是包含Unity Player的低级部分的文件。 由于我们正在执行发布版本,因此Unity将文件放入您的项目中,而没有调试信息。 您需要用字符文件替换libunity.so。

  • 转到安装了Unity的文件夹
  • 转到文件夹“ \ Data \ PlaybackEngines \ AndroidPlayer \ Variations \ il2cpp \ Development \ Libs \ armeabi-v7a \”
  • 从那里获取libunity.so文件,然后替换项目中的文件,该文件位于文件夹'\ src \ main \ jniLibs \ armeabi-v7a'中

剖析


现在,您可以在Android Studio中开始分析,只需单击“启动事件探查器”按钮。

图片

Android Studio启动应用程序,并开始分析会话

图片

默认情况下,Android Studio显示图形,但不采样数据。 要开始该过程,您需要单击CPU轨道,以便探查器切换到CPU视图。 在这种情况下,下拉菜单和“记录”按钮将出现在窗口顶部。

图片

选择采样的“本机”(在Android Studio 3.3-C / C ++ Native中),然后单击“记录”按钮。
由于记录是在设备的磁盘上完成的,因此最好不要记录超过5-8秒的时间,许多设备也将因较少的数据而失败(请参阅文章末尾的经过测试的设备列表)。

要获得结果,请单击“停止”,然后单击一个红色正方形以中断会话。 很难理解作者的想法,但是,如果您没有完全停止录制,则探查器将不会总是开始分析接收到的数据,并且包含该数据的段会走得很远。

图片

之后,只需等待一会儿,在30-50秒后,探查器将为您提供结果。 如果一切设置正确,您将捕获所有函数名称

图片

已知功能


  • 可以在根设备上获得最稳定的结果
  • 请勿使用三星,三星有许多保护性的铃铛和口哨声,会干扰调试
  • 在许多地方,您的集体堆栈将进入形式为“ kernel.kptr +地址”的函数。 这些是Android内核中的调用,这些调用由于安全策略而受到保护。 在有根设备上,可以禁用保护:
    • 运行`adb shell`
    • 运行`su`以获得root权限
    • 运行'sysctl -w kernel.kptr_restrict = 0'-这将从内核中删除保护
    • [!]调试完成后,执行'sysctl -w kernel.kptr_restrict = 1'。 某些设备将无法启动操作系统,否则将在重新启动时启动。 在许多情况下,仅通过闪烁干净的内核即可对其进行处理。
  • 如果Android Studio经常崩溃,则可以尝试增加Java VM的堆:
    • 2Gb-用于中型项目('-Xmx2g')
    • 4Gb-用于大型项目('-Xmx4g')
  • 在非root用户的设备上,有时将内核切换到“许可模式”可以改善这种情况。
    • 运行命令“ adb shell setenforce 0”

Unity细节


  • Unity主线程称为UnityMain,但分析时会看到很多UnityMain。 这些是您在C#代码内部创建的用户线程。 默认情况下,它们具有相同的名称。 Unity的主线程通常很容易区分,因为它的负载最大。
  • 图形流称为UnityGfxWorkerW
  • Unity Job系统线程称为工作线程。
  • 不幸的是,Android Studio展示了Unity使用的某些等待功能(futex-s),并没有将其视为等待时间,而是将其视为活动。
  • 当您在“自上而下”视图中查看调用图时,必须通过Java调用来遍历多个级别,很遗憾,您无法在Android Studio中对其进行过滤。

图片

推荐设备


我们使用以下设备进行实验:
  • 三星Galaxy S8
  • 谷歌Pixel 2XL
  • 谷歌像素
  • 索尼Xperia XA1
  • 华为荣誉7
  • 华为Nexus 6P
  • 摩托G5P
  • 华硕Nexus 7(2013)

所有设备均已安装,对于华为Nexus 6P,我们已经组装了核心和AOSP 。 结果,谷歌和索尼被证明是最无故障且易于使用的。 索尼为开发人员提供了一个不错的网站- 开放设备 。 华为不再允许您以简单的方式解锁设备,三星通过附加的保护级别不断带来麻烦。 Moto G5P经常使探查器数据收集过程(simpleperf)崩溃。

Source: https://habr.com/ru/post/zh-CN437602/


All Articles