Right now I'm in the middle of porting process of my huge WinRT project from WPF to XF. I'm trying to keep same architecture and layout and that helped to find serious bottleneck.
First of all I found very long startup time on real iOS devices. You know, Apple hardware is really powerful so that was a first signal that something is wrong. But the things gone mad when I added a popup window with dynamic content.
Take a look at that picture:
Whole page is a ContentPage containing a Grid with back image, Grid with a nested Grid for a menu, Grid for misc controls and buttons and whole new ContentView for popup, sliding from the top. Popup contains Grid as a parent with back image, nested Grid for navigation and paging and 3x2 Grid for each page with thumbnails. You might already mentioned a lot of Grids here. Actually, any other Layout works the same, main idea is huge control tree in real-world project. That structure worked perfectly on Windows 8 and WPF, but on Xamarin.Forms loading thumbnails into popup lasted 5+ seconds in iOS Simulator. Even more, it took about 20 (!!) seconds on iPod 4 to do the same.
First of all I though that it might be caused by lot of grids, but changing them to AbsoluteLayouts gave nothing at all. Than I thought it might be because of image loading, but even removing thumbnails, custom fonts, frames, etc. gave no significant change.
After 6 hours struggling with the system I realized that every time I add the control to existing hierarchy there is significant lag. I made few tests and found that instead of adding each thumbnail and description directly to popup I can create 'proxy' object (i.e. Grid ), put everything inside and than add it to the page. That approach allowed me to minimize the time to 500ms on Simulator, ~1 s on iPad and ~4s on iPod.
At that point I was sure that there are some minor issues on my side and tried to optimize the hierarchy and get rid of 1/2 of Grids. I flattened the hierarchy (despite the fact that most of markup now looks like a flat cuneiform table + there is a code that layouts some of controls, instead of using aligns) and got 100ms loading time on Simulator (as you've seen in the movie), 500ms on iPad, 1s on iPod. You might call it a victory, but from my point of view it is still too much - native iOS apps can handle this in less than 15 ms without any significant delay.
Than I captured the traces with Mono Profiler. To minimize influence of other parts I just start the app, click the button to show pop-up and close the app when it ready. Session length is about ~20 seconds, popup creation took about 5 seconds, startup took ~10 seconds. Take a look what took the most time:
Method call summary Total(ms) Self(ms) Calls Method name 15433 1 608 Xamarin.Forms.Platform.iOS.VisualElementPackager:HandleChildAdded (Xamarin.Forms.VisualElement) 15001 1 4161 Xamarin.Forms.VisualElement:InvalidateMeasure () 14991 65 1327 Xamarin.Forms.Layout:OnChildMeasureInvalidated (object,System.EventArgs) 14563 29 1826 Xamarin.Forms.EnumerableExtensions:ForEach (System.Collections.Generic.IEnumerable`1,System.Action`1) 13751 4 609 Xamarin.Forms.Platform.iOS.VisualElementPackager:Load ()
Full trace here: http://paste2.org/FUBCh4hP
My popup processing is somewhere in the middle:
4558 0 1 Vkraina.MainView:MapsButton_OnClick (object,System.EventArgs)
It took 4.5 seconds, that is not as huge comparing to other parts - invalidating measures and handling collection updates took 15 seconds of total 20 seconds application run time!
After looking at the deeper trace I realized that there is nothing I can do on my side, because most of the time was spend in internals alike Xamarin.Forms.Layout:InternalChildrenOnCollectionChanged:
So I gave up and temporary suspended the project - it was great idea to use Xamarin.Forms for iOS and Android port, but now with such performance issues I'm really thinking of switching to native UI. Or I can continue porting process and pray God (or XF team?) for an urgent fix before the deadline. Because my customer will surely kill me for poor performance on real devices.
Please guys, take a look at the problem, we could benefit even from a temporary solution with pair of simple BatchLayoutBegin/BatchLayoutCommit methods that would group all internal callbacks during dynamic content creation and application loading stage.