xamarin 应用程序启动缓慢
Slow startup of xamarin app
我们正在 PCL 上开发跨平台应用程序,但目前我们只使用 android 台设备进行测试。
我们担心的是,它需要大约 6 到 8 秒(取决于我们测试的设备)来启动应用程序,这非常慢。
放置几个断点后,我们看到时间消耗相当均匀。
我们确实注意到这个特定部分花费了更长的时间:
- 1 秒后到达 MainActivity 上的 onCreate()(有一个初始屏幕,之前只有一个图像和一个背景颜色)
- 1 秒
base.OnCreate(bundle);
- 1 秒
global::Xamarin.Forms.Forms.Init(this, bundle);
- 1.5 秒
Page mainPage = new LogScreen();
(创建主页然后将其设置为主导航页面)。
这是使用时的常见问题 Xamarin.Forms 有很多与此相关的线程,特别是这个:
https://forums.xamarin.com/discussion/93178/lets-talk-performance/p6
好消息是 Xamarin 团队正在努力。
以下是您可以改进它的一些技巧:
https://blog.xamarin.com/5-ways-boost-xamarin-forms-app-startup-time/
我建议的第一件事是不要对应用程序的调试版本进行基准测试,Mono 运行时和 Jit 代码的代码路径与发布版本不同,共享运行时的使用,程序集大小等等等等都会影响启动和执行时间。
以下是 "very large" 积极调整的 Android 基于表单的应用程序在高端和低端设备上的启动时间示例,使用内部基准测试程序(有条件地编译,而不是注入,并使用 OS 的系统时钟)。
应用概览:
- Xamarin.Forms v2.4.0.269-pre2
- 混合编码和 XAML 基于页面、控件等...
- XAML 编译器已启用
- "Splash screen" 禁用
MainActivity
上基于主题的启动将添加:
- 在快速设备上启动时间超过 200 毫秒,
- 在具有慢速闪存访问的设备上需要 1-2 秒
- 只是不要使用基于 Activity 的闪屏 ;-)
- 多索引
- Proguard'd(通过 UI 带有自动反馈循环的测试积极减少了 jar)
- Linker(Link 所有,使用通过 UI 自动反馈测试生成的自定义 link 描述文件积极减小组件尺寸)
- 100% 源代码构建以允许折叠命名空间和程序集缩减
- 没有第 3 方的 Viper 架构 DI/IoC
- 使用数据、资源广告网络优先级队列的延迟加载设计
- Realm 实时对象和用于所有数据的查询(数据库最小大小:250MB,最大大小 1.2GB)
时间是通过 shell 脚本生成的,该脚本会重启设备、监控启动以等待系统稳定、启动一系列应用程序(GApps、Facebook、Instagram、Twitter 等... ), 等待系统稳定下来,然后通过以下方式启动 Forms 应用程序:
export deviceTime=$(echo "$(adb -s $deviceID shell cat /proc/uptime | awk '{print }') * 1000" | bc -l)
adb -s $deviceID shell am start -n com.sushihangover.GeneticCancerDNAMapper/com.sushihangover.GeneticCancerDNAMapper.DevOpsDashboard --el startTime ${deviceTime%.*}
Google Pixel(基于 Oreo 的)设备(应用可在 ~430 毫秒内使用):
I GeneticCancerDNAMapper: 0.162 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.OnCreate
I GeneticCancerDNAMapper: 0.164 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.base.SetTheme
I GeneticCancerDNAMapper: 0.201 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.base.OnCreate
I GeneticCancerDNAMapper: 0.244 : Xamarin.Forms.Forms.Init
I GeneticCancerDNAMapper: 0.266 : Realms.Realm.GetInstanceAsync ~Get Instance & Data~
I GeneticCancerDNAMapper: 0.324 : Realms.Realm.GetInstanceAsync ~Obtained Instance & Data~
I GeneticCancerDNAMapper: 0.324 : Xamarin.Forms.Application Content
I GeneticCancerDNAMapper: 0.349 : Xamarin.Forms.Application Content ~Creation Completed~
I GeneticCancerDNAMapper: 0.353 : Xamarin.Forms.Application.MainPage ~Displayed~
I GeneticCancerDNAMapper: 0.43 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.LoadApplication
低端 "Android One" 512MB 设备,带 非常慢 闪存(应用程序可在 ~4.5 秒内使用):
回复:https://en.wikipedia.org/wiki/Android_One
I/GeneticCancerDNAMapper(10904): 2.453 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.OnCreate
I/GeneticCancerDNAMapper(10904): 2.467 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.base.SetTheme
I/GeneticCancerDNAMapper(10904): 2.731 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.base.OnCreate
I/GeneticCancerDNAMapper(10904): 3.016 : Xamarin.Forms.Forms.Init
I/GeneticCancerDNAMapper(10904): 3.166 : Realms.Realm.GetInstanceAsync ~Get Instance & Data~
I/GeneticCancerDNAMapper(10904): 3.571 : Realms.Realm.GetInstanceAsync ~Obtained Instance & Data~
I/GeneticCancerDNAMapper(10904): 3.571 : Xamarin.Forms.Application Content
I/GeneticCancerDNAMapper(10904): 3.772 : Xamarin.Forms.Application Content ~Creation Completed~
I/GeneticCancerDNAMapper(10904): 3.799 : Xamarin.Forms.Application.MainPage ~Displayed~
I/GeneticCancerDNAMapper(10904): 4.457 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.LoadApplication
我会把我们为此找到的所有解决方案放在一起,所以它都在一个地方。
其中一个答案 linked this post,非常有用.
除此之外我们还做了以下事情:
- 选中所有项目属性上的“优化代码”框。不确定这是否会具体缩短启动时间,但它似乎对整体性能有所帮助。
- 添加 AOT 和 LLVM。我们找到了一种方法来执行此操作,即使该选项在我们的 IDE 上不可用。这会大大增加构建时间,所以如果你想这样做,我建议只对发布版本这样做。
- 启用Xamarin 快速渲染。这是一个实验性的东西,所以你应该阅读一些关于它的文档,但它是通过在
MainActivity.OnCreate()
方法上添加这一行 global::Xamarin.Forms.Forms.SetFlags("FastRenderers_Experimental");
,在 global::Xamarin.Forms.Forms.Init(this, bundle);
之前完成的
- 更新我们的 Xamarin.Forms Nuget 版本。这需要在您的解决方案的所有项目上使用相同的版本,我们在点击手势方面遇到了一些问题,这些问题也因此得到了改善。
- Link SDK 程序集。在 Linking 下的属性 > Android 选项中,您可以设置为 link "SDK Assemblies Only"。您也可以设置为所有程序集,但如果您使用的是自定义程序集,则不建议这样做。
- 预加载屏幕。这大大提高了应用程序本身的性能,我们所做的是在每个屏幕、背景、下一个需要的地方加载视图和视图模型,因此当将它们推送到导航堆栈时,它们已经加载。这大大减少了页面之间的转换时间。
我找到了解决方案。例如,我们有 5 个选项卡。我们有 5 个视图模型或 5 个代码隐藏。我们定义了启动计时器方法的每个选项卡视图模型构造函数。第一个选项卡构造函数在计时器启动后 700 毫秒初始化。第二个选项卡在 1 秒后开始。让我们为此编写代码:
第一个选项卡主页和主页视图模型是 HomeViewModel。
public void HomeTimer()
{
timer.Interval = 700;
timer.Elapsed += (sender, e) => OnTimedEvent(sender, e);
timer.AutoReset = false;
timer.Enabled = true;
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
timer.Enabled = false;
Yap(); // yap command all the page listview and get api.
}
System.Timers.Timer timer = new System.Timers.Timer();
public HomeViewModel()
{
HomeTimer(); // hometimer starting
}
第二个选项卡是 MyPage,viewmodel 是 MyPageViewModel,构造函数是相同的:
public void MyPageTimer()
{
timer.Interval = 1000; //look. home page starting 0.7 seconds after and mypage starting 1 seconds after.
timer.Elapsed += (sender, e) => OnTimedEvent(sender, e);
timer.AutoReset = false;
timer.Enabled = true;
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
timer.Enabled = false;
GetMypage(); // and getmypage method all the initialize the page and listview and webapi works.
}
System.Timers.Timer timer = new System.Timers.Timer();
public MyPageViewModel()
{
MyPageTimer();
}
并且这个操作我从启动时删除了 1 秒。在此操作之前,我的应用程序开始 3.2 秒,现在开始 2.2 秒。
我们正在 PCL 上开发跨平台应用程序,但目前我们只使用 android 台设备进行测试。
我们担心的是,它需要大约 6 到 8 秒(取决于我们测试的设备)来启动应用程序,这非常慢。
放置几个断点后,我们看到时间消耗相当均匀。
我们确实注意到这个特定部分花费了更长的时间:
- 1 秒后到达 MainActivity 上的 onCreate()(有一个初始屏幕,之前只有一个图像和一个背景颜色)
- 1 秒
base.OnCreate(bundle);
- 1 秒
global::Xamarin.Forms.Forms.Init(this, bundle);
- 1.5 秒
Page mainPage = new LogScreen();
(创建主页然后将其设置为主导航页面)。
这是使用时的常见问题 Xamarin.Forms 有很多与此相关的线程,特别是这个:
https://forums.xamarin.com/discussion/93178/lets-talk-performance/p6
好消息是 Xamarin 团队正在努力。
以下是您可以改进它的一些技巧:
https://blog.xamarin.com/5-ways-boost-xamarin-forms-app-startup-time/
我建议的第一件事是不要对应用程序的调试版本进行基准测试,Mono 运行时和 Jit 代码的代码路径与发布版本不同,共享运行时的使用,程序集大小等等等等都会影响启动和执行时间。
以下是 "very large" 积极调整的 Android 基于表单的应用程序在高端和低端设备上的启动时间示例,使用内部基准测试程序(有条件地编译,而不是注入,并使用 OS 的系统时钟)。
应用概览:
- Xamarin.Forms v2.4.0.269-pre2
- 混合编码和 XAML 基于页面、控件等...
- XAML 编译器已启用
- "Splash screen" 禁用
MainActivity
上基于主题的启动将添加:- 在快速设备上启动时间超过 200 毫秒,
- 在具有慢速闪存访问的设备上需要 1-2 秒
- 只是不要使用基于 Activity 的闪屏 ;-)
- 多索引
- Proguard'd(通过 UI 带有自动反馈循环的测试积极减少了 jar)
- Linker(Link 所有,使用通过 UI 自动反馈测试生成的自定义 link 描述文件积极减小组件尺寸)
- 100% 源代码构建以允许折叠命名空间和程序集缩减
- 没有第 3 方的 Viper 架构 DI/IoC
- 使用数据、资源广告网络优先级队列的延迟加载设计
- Realm 实时对象和用于所有数据的查询(数据库最小大小:250MB,最大大小 1.2GB)
时间是通过 shell 脚本生成的,该脚本会重启设备、监控启动以等待系统稳定、启动一系列应用程序(GApps、Facebook、Instagram、Twitter 等... ), 等待系统稳定下来,然后通过以下方式启动 Forms 应用程序:
export deviceTime=$(echo "$(adb -s $deviceID shell cat /proc/uptime | awk '{print }') * 1000" | bc -l)
adb -s $deviceID shell am start -n com.sushihangover.GeneticCancerDNAMapper/com.sushihangover.GeneticCancerDNAMapper.DevOpsDashboard --el startTime ${deviceTime%.*}
Google Pixel(基于 Oreo 的)设备(应用可在 ~430 毫秒内使用):
I GeneticCancerDNAMapper: 0.162 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.OnCreate
I GeneticCancerDNAMapper: 0.164 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.base.SetTheme
I GeneticCancerDNAMapper: 0.201 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.base.OnCreate
I GeneticCancerDNAMapper: 0.244 : Xamarin.Forms.Forms.Init
I GeneticCancerDNAMapper: 0.266 : Realms.Realm.GetInstanceAsync ~Get Instance & Data~
I GeneticCancerDNAMapper: 0.324 : Realms.Realm.GetInstanceAsync ~Obtained Instance & Data~
I GeneticCancerDNAMapper: 0.324 : Xamarin.Forms.Application Content
I GeneticCancerDNAMapper: 0.349 : Xamarin.Forms.Application Content ~Creation Completed~
I GeneticCancerDNAMapper: 0.353 : Xamarin.Forms.Application.MainPage ~Displayed~
I GeneticCancerDNAMapper: 0.43 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.LoadApplication
低端 "Android One" 512MB 设备,带 非常慢 闪存(应用程序可在 ~4.5 秒内使用):
回复:https://en.wikipedia.org/wiki/Android_One
I/GeneticCancerDNAMapper(10904): 2.453 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.OnCreate
I/GeneticCancerDNAMapper(10904): 2.467 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.base.SetTheme
I/GeneticCancerDNAMapper(10904): 2.731 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.base.OnCreate
I/GeneticCancerDNAMapper(10904): 3.016 : Xamarin.Forms.Forms.Init
I/GeneticCancerDNAMapper(10904): 3.166 : Realms.Realm.GetInstanceAsync ~Get Instance & Data~
I/GeneticCancerDNAMapper(10904): 3.571 : Realms.Realm.GetInstanceAsync ~Obtained Instance & Data~
I/GeneticCancerDNAMapper(10904): 3.571 : Xamarin.Forms.Application Content
I/GeneticCancerDNAMapper(10904): 3.772 : Xamarin.Forms.Application Content ~Creation Completed~
I/GeneticCancerDNAMapper(10904): 3.799 : Xamarin.Forms.Application.MainPage ~Displayed~
I/GeneticCancerDNAMapper(10904): 4.457 : Xamarin.Forms.Platform.Android.FormsAppCompatActivity.LoadApplication
我会把我们为此找到的所有解决方案放在一起,所以它都在一个地方。
其中一个答案 linked this post,非常有用.
除此之外我们还做了以下事情:
- 选中所有项目属性上的“优化代码”框。不确定这是否会具体缩短启动时间,但它似乎对整体性能有所帮助。
- 添加 AOT 和 LLVM。我们找到了一种方法来执行此操作,即使该选项在我们的 IDE 上不可用。这会大大增加构建时间,所以如果你想这样做,我建议只对发布版本这样做。
- 启用Xamarin 快速渲染。这是一个实验性的东西,所以你应该阅读一些关于它的文档,但它是通过在
MainActivity.OnCreate()
方法上添加这一行global::Xamarin.Forms.Forms.SetFlags("FastRenderers_Experimental");
,在global::Xamarin.Forms.Forms.Init(this, bundle);
之前完成的
- 更新我们的 Xamarin.Forms Nuget 版本。这需要在您的解决方案的所有项目上使用相同的版本,我们在点击手势方面遇到了一些问题,这些问题也因此得到了改善。
- Link SDK 程序集。在 Linking 下的属性 > Android 选项中,您可以设置为 link "SDK Assemblies Only"。您也可以设置为所有程序集,但如果您使用的是自定义程序集,则不建议这样做。
- 预加载屏幕。这大大提高了应用程序本身的性能,我们所做的是在每个屏幕、背景、下一个需要的地方加载视图和视图模型,因此当将它们推送到导航堆栈时,它们已经加载。这大大减少了页面之间的转换时间。
我找到了解决方案。例如,我们有 5 个选项卡。我们有 5 个视图模型或 5 个代码隐藏。我们定义了启动计时器方法的每个选项卡视图模型构造函数。第一个选项卡构造函数在计时器启动后 700 毫秒初始化。第二个选项卡在 1 秒后开始。让我们为此编写代码:
第一个选项卡主页和主页视图模型是 HomeViewModel。
public void HomeTimer()
{
timer.Interval = 700;
timer.Elapsed += (sender, e) => OnTimedEvent(sender, e);
timer.AutoReset = false;
timer.Enabled = true;
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
timer.Enabled = false;
Yap(); // yap command all the page listview and get api.
}
System.Timers.Timer timer = new System.Timers.Timer();
public HomeViewModel()
{
HomeTimer(); // hometimer starting
}
第二个选项卡是 MyPage,viewmodel 是 MyPageViewModel,构造函数是相同的:
public void MyPageTimer()
{
timer.Interval = 1000; //look. home page starting 0.7 seconds after and mypage starting 1 seconds after.
timer.Elapsed += (sender, e) => OnTimedEvent(sender, e);
timer.AutoReset = false;
timer.Enabled = true;
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
timer.Enabled = false;
GetMypage(); // and getmypage method all the initialize the page and listview and webapi works.
}
System.Timers.Timer timer = new System.Timers.Timer();
public MyPageViewModel()
{
MyPageTimer();
}
并且这个操作我从启动时删除了 1 秒。在此操作之前,我的应用程序开始 3.2 秒,现在开始 2.2 秒。