@ClayZuvich said:
I've seen several posts about the latest Mono update slowing down Android apps. I can confirm this behavior, and I have found that Newtonsoft deserialization is where my issue is at. However, the slowdown only happens the first time an object is deserialized (for each unique class).
I don't think it's related to Newtonsoft since it was working fine before, but I am positive others will start seeing this issue since it's pretty much the goto library.
My gut tells me something has completely broken Reflection Android. Can anyone please confirm this behavior?
I have the latest Forms release (2.3.4.247). Using Newtonsoft 10.0 is completely broken now on Android, so I downgraded to 8.0.3 and the performance is better.
They are aware of the issue working on a hot fix, Miquel responded to my tweet yesterday. They tend to fix these critical issues pretty quickly.
I could confirm that Android seems to have slowed down recently. My performance issues were nowhere near what others have reported in the past, but after updating to VS 2017 preview with the latest Xamarin dlls and XF 2.3.5, navigating each page seems to take ~3 secs for first time load. Profiler shows a lot of time is being spent on Reflection.
@AdrianKnight Strange. I have a schedule control that shows a lot of objects on the screen based on a time frame(gant chart) and I noticed real slow down recently. It came down to creating new bindings in the custom control's constructors instead of in XAML. I have been wanting to go through Xamarin's Bindings code but I bet there is some significant reflection going on. BTW not creating the bindings and changing the child control's properties on the OnChanged call speeds it up dramatically. I am talking about from 1-4 seconds to create a row down to 4-5 rows a second!
I just discovered this thread, and it's somewhat therapeutic to discover others struggling with this, as I have for nearly 2 years now.
@EZHart yeah, my tweet did not have sufficient context. I've thrown my test projects up here. You'll notice I even added support libraries to the Android project, which is one of the things I meant by "comparable project".
Some ideas I've been pondering, but haven't had time to try/investigate:
Would merging all assemblies (with ILMerge or ILRepack) help? It seems a huge amount of time is spent just loading assemblies and I'm wondering whether there's an overhead per load that could be amortized by merging.
How does XF resolve renderers? My intuition is that it must be reflection looking for the ExportRenderer attributes. Surely this is expensive?
@KentBoogaart I've been advocating for XF to abandon the attribute-based renderer designations in favour of a DI container-based approach. It makes no sense to me to use reflection (which is static and can't change at runtime) when DI containers exist to solve this exact problem - and give the ability to update renderers dynamically at runtime into the bargain.
At 35:30, Miguel de Icaza, did talk about full AOT for Andorid. My question are:
a) When is this feature available
b) Will that feature be available for all VS Editions?
If I look at the rather slow navigation and animations of my XF app, this makes me somewhat nervous... I can't even check the device location (on a task) without slowing down my app. I hope they won't be as tough as this makes it sound.
I hope they won't be as tough as this makes it sound
I hope they will! This will really help to force through perf improvements. And I'm not just talking about Xamarin improving XF performance (though that's certainly something I'm craving) - I'm also talking about me being allocated the time to work on perf in my own apps. Being able to point at these strict measures and the implications if they're not met will perhaps mean that perf is treated as a feature by clients instead of something to address "sometime in the future" (i.e. never).
If I read the Xamarin.Forms.Platform.cs and FormsAppCompatActivity.LoadApplication correctly, then the AppCompat.ButtonRenderer is not used anymore. Also the AppCompat.FrameRenderer has been changed to inherit from FastRenderers.FrameRenderer.
Did you just forget to change the AppCompat.ButtonRenderer to inherit from FastRenderers.ButtonRenderer or has this some reason I don't see?
@KentBoogaart said:
Some ideas I've been pondering, but haven't had time to try/investigate:
Would merging all assemblies (with ILMerge or ILRepack) help? It seems a huge amount of time is spent just loading assemblies and I'm wondering whether there's an overhead per load that could be amortized by merging.
How does XF resolve renderers? My intuition is that it must be reflection looking for the ExportRenderer attributes. Surely this is expensive?
I think #1 was mentioned upthread; there has been some work done on merging all of the XF assemblies into one, but that's on hold for the moment. My (admittedly very preliminary) testing suggests that assembly merging doesn't make a huge difference, but it's still worth exploring (especially for projects with a lot of dependencies).
As for 2, yes, the renderers are resolved using reflection. It's not that expensive. That said, there's room for improvement there - we could shave some time off of that operation by trimming down the searched assemblies list, reducing the number of attributes we need to search for, and getting rid of some "intermediate" renderer types.
If I read the Xamarin.Forms.Platform.cs and FormsAppCompatActivity.LoadApplication correctly, then the AppCompat.ButtonRenderer is not used anymore.
The AppCompat.ButtonRenderer is no longer used by default. It's still available to be subclassed (so we don't break anyone's custom renderers).
Also the AppCompat.FrameRenderer has been changed to inherit from FastRenderers.FrameRenderer.
Did you just forget to change the AppCompat.ButtonRenderer to inherit from FastRenderers.ButtonRenderer or has this some reason I don't see?
Most of the "fast" renderers are new renderers built from the ground up, so they don't inherit from the older renderers. FrameRenderer is the odd one out because it's basically always been a "fast" renderer - when the AppCompat stuff was added, FrameRenderer was built without the container ViewGroup and base class hierarchy that the other renderers used. It was the prototypical "fast" renderer.
To reduce confusion, a FastRenderers.FrameRenderer class was added (so all the "fast" renderers would share a namespace), but it's just a subclass of the old AppCompat version.
At 35:30, Miguel de Icaza, did talk about full AOT for Andorid. My question are:
a) When is this feature available
b) Will that feature be available for all VS Editions?
You can turn on AOT in VS for Mac and VS for Windows right now. It's been available for a while, but it's still considered "experimental". I do not know when it will be out of the "experimental" stage.
In nuget, I see the XF 2.3.5Pre3 package. In the Xamarin nightly builds, I see XF 2.3.6. What is 2.3.6? Is it another set of bits in the 2.3.4 to 2.3.5 train? is it an early version 3.0?
@wallym 2.3.6 is basically master... it's from our CI builds, at the time we are not yet working on 3.0 on the main branch. But 2.3.6 is basically the bleeding edge version to be released from master.
@rmarinho said: @wallym 2.3.6 is basically master... it's from our CI builds, at the time we are not yet working on 3.0 on the main branch. But 2.3.6 is basically the bleeding edge version to be released from master.
Aside from the issues with DataTrigger and UWP native builds, we have been encouraged to see a definite performance improvement in XF 2.3.4 over 2.3.3. We noticed in particular that memory usage on UWP dropped significantly on XF 2.3.4, possibly due to performance enhancements and fixing memory leaks.
But,
can you post on github example of project before and after the optional settings/methods to do
and to see visually the changed Startup times?
Thanks a lot!
First, thanks for posting the link to your performance comparison.
You wrote, the tests were done with .forms 2.3.0.49.
It would be interesting, how the performance compares with the latest .forms (not only to Java, also to 2.3.0.49 )
I further would be interesting, if some specific test-pages would be added in your test (e.g. a page with 10'000 labels only, as by tests in history, this was horrible slow)
Finally it would be really nice (for all users) , if the test results to old .forms-versions would be stay stored (so that on can see the difference (ahhh progress ) between the .forms versions.
This only as input from my side
@ChristianFalch said: @EZHart: When you say "The real startup issue is the time to JIT compile the code" - could you please elaborate on how JIT'ing is performed on Android (see my previous question) - Can JIT'ed code be cached on the device?
Caching the JIT compilation results doesn't really make sense; the results would contain addresses which won't be correct on subsequent process restarts. Also, I suspect re-using JIT results would defeat some of the optimizations JIT compiler can make.
Starting on Android 7, Google has switched from plain AOT to profile guided compilation, that is a mix of JIT and AOT.
The idea is to create a profile containing the most used methods from the application and then compile them when the device idle and charging. This approach has the benefits of both JIT and AOT: smaller APKs and also the speed of a compiled code.
I'm not aware of how Xamarin compilation works for Android, but it does not seem to benefit from the profile guided compilation since it is always slow when the app is started from scratch. Also, if Android has a JIT cache mechanism, why is that not possible on Xamarin?
it does not seem to benefit from the profile guided compilation
The feature you're talking about deals with Java code and the Android Runtime. So no, it likely wouldn't benefit a Xamarin Android application. Keep in mind that Xamarin Android is IL running on MonoVM; the JIT we're referring to here is happening in Mono, not in the Android Runtime.
if Android has a JIT cache mechanism, why is that not possible on Xamarin?
Again, we're talking about two different JIT mechanisms for two different languages and runtimes. When we were discussing a "JIT cache" mechanism upthread, we were talking about caching JIT compiled code to storage between application runs (and why that idea doesn't work for Mono JIT).
That's not what what Android does, either. As I understand it (and correct me if I'm wrong), Android JIT compiles code where appropriate/necessary, caches the JIT compiled code in memory, and writes JIT profiling data to storage for guided AOT compilation later. It's not loading actual JIT compiled code from disk on subsequent application runs.
The feature you're talking about deals with Java code and the Android Runtime. So no, it likely wouldn't benefit a Xamarin Android application. Keep in mind that Xamarin Android is IL running on MonoVM; the JIT we're referring to here is happening in Mono, not in the Android Runtime.
Yeah, I see now. After posting, I realized that you were talking about Mono JIT, not Java.
That's not what what Android does, either. As I understand it (and correct me if I'm wrong), Android JIT compiles code where appropriate/necessary, caches the JIT compiled code in memory, and writes JIT profiling data to storage for guided AOT compilation later. It's not loading actual JIT compiled code from disk on subsequent application runs.
You're right. The profiled data is compiled using AOT, it is not using a JIT cache on Android.
this can be perfect example. it is only one PCL shared , and it's demonstrating all good features of XF.
But, when i installed it on my nexus4 phone , IT TAKES 12 sec TO LOAD - Unbearable!
So, as a good excercise , can you Xamarin guys work on this demo app on version before and after?
Can you make this app load at 3sec-5sec max?
This is your example , so it's a good practice to show on it XF as fast loading.
No @DH_HA1 , I didn't , but i don't need to.
All of my checking and also as i red of @DavidOrtinau shows there is no big
difference between release mode and debug regarding start time.
If it takes 12sec to load on debug , maybe it will take 11sec on release. still horrible.
I know the answer , though.
The problem is that on MainActivity and in App.cs there are a lot of inits running before the load
of first page. this can be cut.
I started to place stopwatch everywhere and i see if i remove all userdialog inits and all DI inits from MainActivity and App,
things starting to be acceptable in range of 6sec startup time.
So.
I think the workaround for now is to start with a simple page without DI injection and only the second page should be init all the services and Di etc.
Great improvment!
I managed to reduce my XF app startup time from 9sec to 4sec via AOT+LLVM on release mode
with full linking (sdk + user)!
Great! @DH_HA1 , I don't have time to chech EshopOnContainer, but i believe this is the way for now....
Not so horrible currently @DH_HA1 ,
from app size 15M without AOT to 24M or 45M (depends on device type) , I also checking 'generate one package fore each ABI' on android settings.
But on the device itself App Info showing double size (50M or 90M).
I also gonna check the 'partialAOT' thing mentioned earlier ....
I see that there are good discussions on the performance and bugs fixes. May I know if there is any initiative from Microsoft/Xamarin to reduce the compiled Android app size?.
As an example, a simple "Hello World" Xamarin Forms , with all the optimization and proguard setting, the smallest I manage to get is 11Mb+.
The AOT speed improvement sounds exactly what my android app needs. The only reason I have been put off enabling it is because the documentation says its an "experimental feature" and has been disabled in recent releases.
AOT is currently an experimental feature. It is not recommended for production use. AOT and LLVM was available in Xamarin.Android 5.1, but it is no longer available in later Xamarin.Android versions. For more information, please see the Xamarin.Android 6.1 release notes
LLVM needs AOT to be activated first.
Is the documentation correct. has this feature been phased out / not supported?
AOT and AOT+LLVM support has always been experimental. It has been discovered that AOT+LLVM support hasn't worked since at least Xamarin.Android 6.0; the AOT+LLVM compiler executed but didn't do anything. During QA, it was determined that in attempting to fix the "AOT+LLVM didn't do anything" issue, the AOT+LLVM compiler instead crashed.
Unfortunately, AOT support is experimental at the moment:
LLVM can't be used when building for x86_64, because of an Android NDK bug.
AOT and AOT+LLVM on x86 are known to be unstable.
AOT+LLVM on arm64-v8a is known to be unstable.
From the notes found my conclusion would be AOT and LLVM should not be used in release builds
Interesting point @JKay ,
I think for normal XF app for now it's the only option.
I just checked Xamarin and Microsoft full blown App https://github.com/dotnet-architecture/eShopOnContainers, on normal build (Release) it takes 16sec startup, and after AOT+LLVM it takes....
7sec.
I didn't check all the app options in that copilation, so let Xamarin guys do this work: @DavidOrtinau@EZHart@rmarinho
Posts
They are aware of the issue working on a hot fix, Miquel responded to my tweet yesterday. They tend to fix these critical issues pretty quickly.
I could confirm that Android seems to have slowed down recently. My performance issues were nowhere near what others have reported in the past, but after updating to VS 2017 preview with the latest Xamarin dlls and XF 2.3.5, navigating each page seems to take ~3 secs for first time load. Profiler shows a lot of time is being spent on Reflection.
@AdrianKnight Strange. I have a schedule control that shows a lot of objects on the screen based on a time frame(gant chart) and I noticed real slow down recently. It came down to creating new bindings in the custom control's constructors instead of in XAML. I have been wanting to go through Xamarin's Bindings code but I bet there is some significant reflection going on. BTW not creating the bindings and changing the child control's properties on the OnChanged call speeds it up dramatically. I am talking about from 1-4 seconds to create a row down to 4-5 rows a second!
@NMackay and others. Thanks for the updates!
@AdrianKnight
Think this is the bug
https://bugzilla.xamarin.com/show_bug.cgi?id=56240
Thanks! At least we know it's a known bug, but from the looks of it, it's going to take a while to fix it. sigh.
All bugzilla take a while. There is basic need items a year old, and older, still in bugzilla.
Hopefully not on this one as a hot fix is apparently been worked on.
I just discovered this thread, and it's somewhat therapeutic to discover others struggling with this, as I have for nearly 2 years now.
@EZHart yeah, my tweet did not have sufficient context. I've thrown my test projects up here. You'll notice I even added support libraries to the Android project, which is one of the things I meant by "comparable project".
Some ideas I've been pondering, but haven't had time to try/investigate:
ExportRenderer
attributes. Surely this is expensive?@KentBoogaart I've been advocating for XF to abandon the attribute-based renderer designations in favour of a DI container-based approach. It makes no sense to me to use reflection (which is static and can't change at runtime) when DI containers exist to solve this exact problem - and give the ability to update renderers dynamically at runtime into the bargain.
Hi,
I just watched the recorded Xamarin Session at Build 2017 (https://channel9.msdn.com/Events/Build/2017/B8103).
At 35:30, Miguel de Icaza, did talk about full AOT for Andorid. My question are:
a) When is this feature available
b) Will that feature be available for all VS Editions?
Regarding performance:
https://www.engadget.com/2017/05/19/google-has-a-new-way-to-call-out-poorly-made-android-apps/
If I look at the rather slow navigation and animations of my XF app, this makes me somewhat nervous... I can't even check the device location (on a task) without slowing down my app. I hope they won't be as tough as this makes it sound.
I hope they will! This will really help to force through perf improvements. And I'm not just talking about Xamarin improving XF performance (though that's certainly something I'm craving) - I'm also talking about me being allocated the time to work on perf in my own apps. Being able to point at these strict measures and the implications if they're not met will perhaps mean that perf is treated as a feature by clients instead of something to address "sometime in the future" (i.e. never).
For me, performance also involves memory consumption and allocation.
So, will be nice to take a look at bugs like this.
@EZHart One more question regarding the fast renderers.
There are now three renderers for Button.
https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ButtonRenderer.cs
https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/AppCompat/ButtonRenderer.cs
https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/FastRenderers/ButtonRenderer.cs
If I read the Xamarin.Forms.Platform.cs and FormsAppCompatActivity.LoadApplication correctly, then the AppCompat.ButtonRenderer is not used anymore. Also the AppCompat.FrameRenderer has been changed to inherit from FastRenderers.FrameRenderer.
Did you just forget to change the AppCompat.ButtonRenderer to inherit from FastRenderers.ButtonRenderer or has this some reason I don't see?
I think #1 was mentioned upthread; there has been some work done on merging all of the XF assemblies into one, but that's on hold for the moment. My (admittedly very preliminary) testing suggests that assembly merging doesn't make a huge difference, but it's still worth exploring (especially for projects with a lot of dependencies).
As for 2, yes, the renderers are resolved using reflection. It's not that expensive. That said, there's room for improvement there - we could shave some time off of that operation by trimming down the searched assemblies list, reducing the number of attributes we need to search for, and getting rid of some "intermediate" renderer types.
The
AppCompat.ButtonRenderer
is no longer used by default. It's still available to be subclassed (so we don't break anyone's custom renderers).Most of the "fast" renderers are new renderers built from the ground up, so they don't inherit from the older renderers.
FrameRenderer
is the odd one out because it's basically always been a "fast" renderer - when the AppCompat stuff was added,FrameRenderer
was built without the container ViewGroup and base class hierarchy that the other renderers used. It was the prototypical "fast" renderer.To reduce confusion, a
FastRenderers.FrameRenderer
class was added (so all the "fast" renderers would share a namespace), but it's just a subclass of the old AppCompat version.You can turn on AOT in VS for Mac and VS for Windows right now. It's been available for a while, but it's still considered "experimental". I do not know when it will be out of the "experimental" stage.
Probably when they figure out how to make it work without bloating your APK by 300% or more.
In nuget, I see the XF 2.3.5Pre3 package. In the Xamarin nightly builds, I see XF 2.3.6. What is 2.3.6? Is it another set of bits in the 2.3.4 to 2.3.5 train? is it an early version 3.0?
@wallym 2.3.6 is basically master... it's from our CI builds, at the time we are not yet working on 3.0 on the main branch. But 2.3.6 is basically the bleeding edge version to be released from master.
Thanks Rui. That is what I thought.
Aside from the issues with DataTrigger and UWP native builds, we have been encouraged to see a definite performance improvement in XF 2.3.4 over 2.3.3. We noticed in particular that memory usage on UWP dropped significantly on XF 2.3.4, possibly due to performance enhancements and fixing memory leaks.
Here are @BrandonMinnick's build optimization tips he shared recently on Twitter.
https://github.com/brminnick/ImproveXamarinBuildTimes
Thanks @DavidOrtinau for your great post:
https://blog.xamarin.com/5-ways-boost-xamarin-forms-app-startup-time/
But,
can you post on github example of project before and after the optional settings/methods to do
and to see visually the changed Startup times?
Thanks a lot!
@ClintStLaurent
First, thanks for posting the link to your performance comparison.
)
) between the .forms versions.
You wrote, the tests were done with .forms 2.3.0.49.
It would be interesting, how the performance compares with the latest .forms (not only to Java, also to 2.3.0.49
I further would be interesting, if some specific test-pages would be added in your test (e.g. a page with 10'000 labels only, as by tests in history, this was horrible slow)
Finally it would be really nice (for all users) , if the test results to old .forms-versions would be stay stored (so that on can see the difference (ahhh progress
This only as input from my side
Starting on Android 7, Google has switched from plain AOT to profile guided compilation, that is a mix of JIT and AOT.
The idea is to create a profile containing the most used methods from the application and then compile them when the device idle and charging. This approach has the benefits of both JIT and AOT: smaller APKs and also the speed of a compiled code.
I'm not aware of how Xamarin compilation works for Android, but it does not seem to benefit from the profile guided compilation since it is always slow when the app is started from scratch. Also, if Android has a JIT cache mechanism, why is that not possible on Xamarin?
The feature you're talking about deals with Java code and the Android Runtime. So no, it likely wouldn't benefit a Xamarin Android application. Keep in mind that Xamarin Android is IL running on MonoVM; the JIT we're referring to here is happening in Mono, not in the Android Runtime.
More info on how XA works:
https://developer.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/part_1_-_understanding_the_xamarin_mobile_platform/#Compilation
Again, we're talking about two different JIT mechanisms for two different languages and runtimes. When we were discussing a "JIT cache" mechanism upthread, we were talking about caching JIT compiled code to storage between application runs (and why that idea doesn't work for Mono JIT).
That's not what what Android does, either. As I understand it (and correct me if I'm wrong), Android JIT compiles code where appropriate/necessary, caches the JIT compiled code in memory, and writes JIT profiling data to storage for guided AOT compilation later. It's not loading actual JIT compiled code from disk on subsequent application runs.
Yeah, I see now. After posting, I realized that you were talking about Mono JIT, not Java.
You're right. The profiled data is compiled using AOT, it is not using a JIT cache on Android.
Hello again @DavidOrtinau @EZHart @rmarinho
Regarding Example project, your new architecture example EshopOnConainer here:
https://github.com/dotnet-architecture/eShopOnContainers
But, when i installed it on my nexus4 phone , IT TAKES 12 sec TO LOAD - Unbearable!
So, as a good excercise , can you Xamarin guys work on this demo app on version before and after?
Can you make this app load at 3sec-5sec max?
This is your example , so it's a good practice to show on it XF as fast loading.
Many thanks.
@zahikramer have you run this in release mode?
No @DH_HA1 , I didn't , but i don't need to.
All of my checking and also as i red of @DavidOrtinau shows there is no big
difference between release mode and debug regarding start time.
If it takes 12sec to load on debug , maybe it will take 11sec on release. still horrible.
I know the answer , though.
The problem is that on MainActivity and in App.cs there are a lot of inits running before the load
of first page. this can be cut.
I started to place stopwatch everywhere and i see if i remove all userdialog inits and all DI inits from MainActivity and App,
things starting to be acceptable in range of 6sec startup time.
So.
I think the workaround for now is to start with a simple page without DI injection and only the second page should be init all the services and Di etc.
@zahikramer now run in release mode and see what it drops to
Great improvment!
I managed to reduce my XF app startup time from 9sec to 4sec via AOT+LLVM on release mode
with full linking (sdk + user)!
Great!
@DH_HA1 , I don't have time to chech EshopOnContainer, but i believe this is the way for now....
@zahikramer excellent! be aware that AOT bloats your apk on the device. I am guessing over 100MB for your app
Not so horrible currently @DH_HA1 ,
from app size 15M without AOT to 24M or 45M (depends on device type) , I also checking 'generate one package fore each ABI' on android settings.
But on the device itself App Info showing double size (50M or 90M).
I also gonna check the 'partialAOT' thing mentioned earlier ....
I see that there are good discussions on the performance and bugs fixes. May I know if there is any initiative from Microsoft/Xamarin to reduce the compiled Android app size?.
As an example, a simple "Hello World" Xamarin Forms , with all the optimization and proguard setting, the smallest I manage to get is 11Mb+.
The AOT speed improvement sounds exactly what my android app needs. The only reason I have been put off enabling it is because the documentation says its an "experimental feature" and has been disabled in recent releases.
Is the documentation correct. has this feature been phased out / not supported?
It also says for more information see the Xamarin.Android 6.1 Release notes which says the following:
from Xamarin.Android 6.1 Release notes:
and AOT Support
From the notes found my conclusion would be AOT and LLVM should not be used in release builds
Interesting point @JKay ,
I think for normal XF app for now it's the only option.
I just checked Xamarin and Microsoft full blown App https://github.com/dotnet-architecture/eShopOnContainers, on normal build (Release) it takes 16sec startup, and after AOT+LLVM it takes....
7sec.
I didn't check all the app options in that copilation, so let Xamarin guys do this work: @DavidOrtinau @EZHart @rmarinho
Let's not forget that AOT is an Enterprise feature only,