We profile Unity project with Android Studio

Good day to all! This article is about how to profile Unity games on Android with Android Studio. I will talk about how to set up Android Studio and get the maximum amount of data. The questions of analysis and conclusions based on the result obtained are beyond the scope of this article.

Requirements


For full profiling of the application, you need a phone with Android 8 or newer (API 27). By experience, profiling with Android of older versions carries more adventures than benefits. For this reason, I recommend to get a full line of Nexus devices, as they have old hardware and the latest Android updates.

Setting up the Unity project


To get the result, you have to set up a Unity project in a certain way.

Settings in Build Settings


image

  • First of all, you should switch the Build System to “Gradle” and tick the “Export Project” . Thus, we will get a ready-made Android Studio project, which we will further profile. Profiling a finished APK is also possible, but more limited and requires more preparation.
  • It is advisable to turn off the Development Build mode , since the resulting timings in the profiler will be as close to real as possible.

Settings in Player Settings


image

  • Install Scripting Backend in IL2CPP . If we leave Mono, then with native profiling we will see many Mono functions, without information on how they relate to C # code.
  • The option 'C ++ Compiler Configuration' for Android does not affect anything (in Unity 2018.3). You can put it in 'Release', perhaps in future versions of the Unity Android toolchain this setting will affect the compiler settings.
  • It is advisable to limit the 'Target Architecture' to ARMv7 . So you save on compile time and from experience a lot of architectures sometimes introduces Android Studio into a stupor.
  • It is also worth setting a number of additional settings:
    • Install Location - 'Prefer external'
    • Internet Access - 'Require'
    • Write Permission - 'External (SDCard)'

    Android Studio and other profilers use simpleperf to collect statistics, and it will need access to a memory card to write temporary files.

Gradle project preparation


After you have installed all the settings, build the Unity project. You should get a folder with the Gradle project.
image

Unity by default collects the project at the rate that you plan to build the final APK from it. Therefore, all debug information has been removed from it, but fortunately it can be returned. To do this, you need to replace libil2cpp.so and libunity.so with debug information.

libil2cpp.so


This is the file that contains all the C ++ code that IL2CPP generated from your C # code. Unity generates all the necessary information for profiling, but cuts it out for the optimization of the APK size. To return it:
  • Go to your project folder
  • Find in it the Temp subfolder and go to the Temp / StagingArea / symbols / armeabi-v7a subfolder.
  • Find in it 'libil2cpp.so.debug' . This is the debug version of 'libil2cpp.so'.
  • Now go to the Gradle project and find the folder '\ src \ main \ jniLibs \ armeabi-v7a' in it
  • Replace 'libil2cpp.so' with the file 'libil2cpp.so.debug'

libunity.so


This is the file that contains the low-level part of the Unity Player. Since we are doing a release build, Unity put a file without debugging information into your project. You need to replace libunity.so with a file with symbols.

  • Go to the folder where you have Unity installed
  • Navigate to the "\ Data \ PlaybackEngines \ AndroidPlayer \ Variations \ il2cpp \ Development \ Libs \ armeabi-v7a \" folder
  • Take from there the file libunity.so , and replace the file in your project, which lies in the folder '\ src \ main \ jniLibs \ armeabi-v7a'

Profiling


Now you can start profiling in Android Studio, just press the profiler launch button.

image

Android Studio launches the application and starts the profiling session.

image

By default, Android Studio shows graphs, but does not sample the data. To start the process, you need to click on the CPU track so that the profiler switches to the CPU view. At the same time, a dropdown and a 'Record' button will appear on top of the window.

image

Select Sampled 'Native' (In Android Studio 3.3 - C / C ++ Native), and tap the 'Record' button.
Since the recording is made on the device's disk, it is better not to record more than 5-8 seconds from experience, many devices will fade on a smaller amount of data (see the list of tested devices at the end of the article).

To get the result, click 'Stop' and then a red square to interrupt the session. It is difficult to understand the idea of ​​the authors, but if you do not stop the recording completely, then the profiler does not always start analyzing the obtained data and your segment with this data will go far away.

image

After that, it remains only to wait a bit, after 30-50 seconds the profiler will give you the result. If everything is set up correctly, you will get capture with all the function names.

image

Known features


  • The most stable results can be obtained on root devices.
  • Do not use Samsung, and they have a lot of security features that interfere with debugging
  • In many places your kolstek will go to functions like 'kernel.kptr + address'. These are calls inside the Android Kernel that are protected due to security policy. You can disable protection on a rooted device:
    • Run `adb shell`
    • Run `su` to get root permissions
    • Run 'sysctl -w kernel.kptr_restrict = 0' - this will remove the protection from the kernel
    • [!] After debugging is finished, execute 'sysctl -w kernel.kptr_restrict = 1'. Some devices will not load the OS when rebooting. In many cases, it is treated only by flashing the clean kernel.
  • If Android Studio crashes often, you can try to increase the heap Java VM:
    • 2Gb - for medium-sized projects ('-Xmx2g')
    • 4Gb - for large projects ('-Xmx4g')
  • On non-rooted devices, the situation sometimes improves by switching the kernel in 'permissive mode'
    • Run the command 'adb shell setenforce 0'

Unity specifics


  • The main Unity thread is called UnityMain, but you can see a lot of UnityMain when profiling. These are custom threads that you create inside C # code. By default, they get the same name. The main stream of Unity is usually easy to distinguish, since it will be the most loaded.
  • The graphics stream is called UnityGfxWorkerW
  • Unity Job System threads are called Worker Thread.
  • Unfortunately, some of the wait-functions that Unity uses (futex-s), Android Studio shows and considers not as a wait-time, but as an activity.
  • When you watch the call graph in the Top Down view, you will have to go through many levels with a Java call, unfortunately you can’t filter it in Android Studio.

image

Recommended devices


We used the following devices for experiments:
  • Samsung Galaxy S8
  • Google Pixel 2XL
  • Google pixel
  • Sony Xperia XA1
  • Huawei Honor 7
  • Huawei Nexus 6P
  • Moto G5P
  • Asus Nexus 7 (2013)

All devices have been installed, for Huawei Nexus 6P, we have assembled a core and AOSP . According to the result, Google and Sony turned out to be the most trouble-free and easy-to-work. Sony has an excellent site for developers - Open Devices . Huawei no longer allows you to unlock devices in an easy way, Samsung causes constant difficulties with additional levels of protection. Moto G5P often led to a drop in the profiler data collection process (simpleperf).

Also popular now: