## Introduction This is a tutorial of FPS testing. ## How to Build (iOS) In order to achieve the best test results, Please build a completely release version ### Build Dependencies Setting up the Engine development environment Please follow https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment. Check out repo and update dependencies: ``` cd $FLUTTER_ROOT/flutter git checkout flutter-1.17-candidate.5 gclient sync -D ``` Apply following to end of `flutter/third_party/txt/BUILD.gn` ``` diff --git a/third_party/txt/BUILD.gn b/third_party/txt/BUILD.gn index 56b73a020..d42e88045 100644 --- a/third_party/txt/BUILD.gn +++ b/third_party/txt/BUILD.gn @@ -141,6 +141,7 @@ source_set("txt") { "//third_party/harfbuzz", "//third_party/icu", "//third_party/skia", + "//third_party/skia/modules/skottie", ] deps = [ @@ -339,3 +340,10 @@ executable("txt_benchmarks") { deps += [ "//third_party/skia/modules/skparagraph" ] } } + +static_library("txt_lib") { + complete_static_lib = true + deps = [ + ":txt", + ] +} ``` Comiple engine: ``` cd $FLUTTER_ROOT ./flutter/tools/gn --ios --runtime-mode=release //disable bitcode ./flutter/tools/gn --ios --runtime-mode=release --bitcode //enable bitcode ``` There is a special settings, namely "Enable bitcode". You need to set properly when building an ios native plugin. Generally, the program is possible to run faster when "Enable bitcode" is true while the size of the plugin will also become bigger. You can choose to build the library with enabled or disabled "Enable bitcode" using different build commands. You can also build UIWidgets engine with enabled or disabled "Enable bitcode" by changing the value of "ios_bitcode_enabled" in "Build.bee.cs". Note that the value is set to false by default. You can also change the setting of "Enable bitcode" in the XCode project generated by Unity. Specifically, you can find this setting in "Build Settings/Build Options/Enable Bitcode". This value is true by default. `You should always keep the "Enable bitcode" settings the same in the built library, the UIWidgets engine and the XCode project generated by your UIWidget project.` add this line to the end of out/ios_release/args.gn: ``` icu_use_data_file=false ``` finally run ninja: ``` ninja -C out/ios_release/ flutter/third_party/txt:txt_lib ``` If the compilation fails because "no available Mac SDK is found" (in flutter-1.17 the build tool will only try to find Mac 10.XX SDKs), please modify the file "/src/build/Mac/find_sdk.py" under flutter root by setting "sdks" as your current sdk, e.g., ['11.0']. If the compilation fails because "'Foundation/NSURLHandle.h' file not found" (flutter-1.17 assumes that you are using some low iphone SDK (e.g., older than 12.2), in which some platform-dependent Macros are defined differently from new SDKs like 12.2), please modify the file "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/TargetConditionals.h" in your system by making "TARGET_OS_EMBEDDED = 1" and "TARGET_OS_MACCATALYST = 0" for arm64-iphone architecture. You can also work-around this issue by checking out a new version of flutter (e.g., "flutter-1.18-candidate.6") and run "gclient sync -D" to get dependencies on newer iphone SDKs. Then switch back and build. ### Build Engine Please change ``` var codegens = new[] { CodeGen.Debug }; ``` to ``` var codegens = new[] { CodeGen.Release }; ``` in "Build.bee.cs" Please remove Timeline logs in /engine/src/runtime/mono_api.cc as below: ``` // if (timestamp1_or_async_id) { // uiwidgets::UIWidgetsSystem::GetInstancePtr()->printf_console( // "uiwidgets Timeline [Thread:%d] [%lld ms] [%lld] [%s]: %s\n", // GetCurrentThreadId(), (timestamp0 - timestamp_begin) / 1000, // timestamp1_or_async_id, TimelineEventToString(type), label); // } else { // uiwidgets::UIWidgetsSystem::GetInstancePtr()->printf_console( // "uiwidgets Timeline [Thread:%d] [%d ms] [%s]: %s\n", // GetCurrentThreadId(), (timestamp0 - timestamp_begin) / 1000, // TimelineEventToString(type), label); // } ``` This will output Timeline logs continuously, which has a great inlfuence on the test results. Please close assert function in /Runtime/foundation/Debug.cs as below: ``` [Conditional("UNITY_ASSERTIONS")] public static void assert(Func result, Func message = null) { // if ( enableDebug && !result() ) { // throw new AssertionError(message != null ? message() : ""); // } } [Conditional("UNITY_ASSERTIONS")] public static void assert(bool result, Func message = null) { // if ( enableDebug && !result ) { // throw new AssertionError(message != null ? message() : ""); // } } ``` then ``` cd \engine mono bee.exe ios ``` ### Build Project Duo to some unknown reasons, the project build to iOS devices is limited to less than 30 FPS. To remove the restriction, add this to OnEnable function of UIWdgets script ``` Application.targetFrameRate = 120; ``` And also ``` using UnityEngine; ``` is required, too. Please open the Project Settings, and in the Quality tab, set the "V Sync Count" option of the target platform to "Don't Sync". You should remove the FPS restriction on the Master branch, too. Apply the changes to /Runtime/ui/window.cs ``` diff --git a/com.unity.uiwidgets/Runtime/ui/window.cs b/com.unity.uiwidgets/Runtime/ui/window.cs index 860e35aa..5f4e24d6 100644 --- a/com.unity.uiwidgets/Runtime/ui/window.cs +++ b/com.unity.uiwidgets/Runtime/ui/window.cs @@ -294,11 +294,12 @@ namespace Unity.UIWidgets.ui { } static void defaultFrameRateSpeedUp() { -#if UNITY_2019_3_OR_NEWER - OnDemandRendering.renderFrameInterval = defaultMinRenderFrameInterval; -#else - Application.targetFrameRate = defaultMaxTargetFrameRate; -#endif + Application.targetFrameRate = 120; +// #if UNITY_2019_3_OR_NEWER +// OnDemandRendering.renderFrameInterval = defaultMinRenderFrameInterval; +// #else +// Application.targetFrameRate = defaultMaxTargetFrameRate; +// #endif } static Action _onFrameRateCoolDown = defaultFrameRateCoolDown; @@ -316,11 +317,12 @@ namespace Unity.UIWidgets.ui { } static void defaultFrameRateCoolDown() { -#if UNITY_2019_3_OR_NEWER - OnDemandRendering.renderFrameInterval = defaultMaxRenderFrameInterval; -#else - Application.targetFrameRate = defaultMinTargetFrameRate; -#endif + Application.targetFrameRate = 120; +// #if UNITY_2019_3_OR_NEWER +// OnDemandRendering.renderFrameInterval = defaultMaxRenderFrameInterval; +// #else +// Application.targetFrameRate = defaultMinTargetFrameRate; +// #endif } } } ``` After that, build your UIWidget project just like a regular unity project(Don't forget to switch the platform and set the Player Settings) Open your XXX.xcodeproj in Xcode, set the signing settings and don't forget keeping the "Enable bitcode" settings as same as build library and the UIWidgets engine Long press the build button and change to Profile option, waiting for profile build, it will take a while, please be patient. After profile build success, you can see the instruments start page. Choose the Core Animation template. If you don't have the Core Animation templete, just choose the Blank templete, click the plus sign in the upper right corner, then choose the Core Animation FPS option. Press record button and do some operations on the iOS device about 60s, press the button again can stop the record. ## Records 1st Apr 2021(gallery&&disable bitcode): | Average FPS | master | zxw/dev_ios_update_engine | |:-:|:-:| :-: | |test1 |51.9 |52.5 |test2 |50 |53.2 |test3 |50 |54.3