Bug 56896 - ListViews for lists with many elements regressed in performance on iOS
Summary: ListViews for lists with many elements regressed in performance on iOS
Alias: None
Product: Forms
Classification: Xamarin
Component: iOS ()
Version: 2.3.5
Hardware: Macintosh Mac OS
: Highest critical
Target Milestone: ---
Assignee: Samantha Houts [MSFT]
Depends on:
Reported: 2017-05-26 22:14 UTC by Frank Schwieterman
Modified: 2017-07-20 20:43 UTC (History)
12 users (show)

Tags: ac, ios, listview, performance, xamexttriage, fr, xamextfollowed
Is this bug a regression?: Yes
Last known good build:

Attached are the logs generated during defect verification (4.14 KB, application/x-zip-compressed)
2017-06-28 12:41 UTC, Saurabh Paunikar

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Frank Schwieterman 2017-05-26 22:14:01 UTC
# Steps to reproduce

Pull the project: https://github.com/trainerroad/ListviewBugRepro
Run it on iOS

# Expected behavior

The listview should load quickly.  The debug output should show a small number of calls to the InstrumentedViewCell and InstrumentedGrid.

# Actual behavior

The listview loads slowly.  Rather than constructor <100 InstrumentedViewCells, it creates over 25000.

# Supplemental info (logs, images, videos)

Watching the debug output, running Xamarin Forms with Mono Runtime on iOS I see:

InstrumentedViewCell counts: constructor: 25029, OnPropertyChanged NameScope: 25029, OnPropertyChanged Height: 25027, OnPropertyChanged RenderHeight: 25027, OnPropertyChanged View: 25027, OnPropertyChanged BindingContext: 25027, OnBindingContextChanged: 25027, OnPropertyChanged Index: 25027, OnParentSet: 25027, OnPropertyChanged Parent: 25027, OnPropertyChanged RealCell: 13, OnAppearing: 13
InstrumentedGrid counts: constructor: 25027, InvalidateLayout: 25027, OnSizeAllocated: 25053, OnParentSet: 25027, OnBindingContextChanged: 25027, LayoutChildren: 26

This is the InstrumentedViewCell and InstrumentedGrid counting the number of times a method was called (for all instances in the process).  This is way too hay.

If I run on Android, its much better (still Xamarin Forms, Mono Runtime

InstrumentedGrid counts: constructor: 20, InvalidateLayout: 20, OnSizeAllocated: 39, OnParentSet: 20, OnBindingContextChanged: 38, OnMeasure: 19, OnSizeRequest: 19, LayoutChildren: 19
InstrumentedViewCell counts: constructor: 22, OnPropertyChanged NameScope: 22, OnPropertyChanged Height: 20, OnPropertyChanged RenderHeight: 20, OnPropertyChanged View: 20, OnPropertyChanged BindingContext: 38, OnBindingContextChanged: 38, OnPropertyChanged Index: 38, OnParentSet: 20, OnPropertyChanged Parent: 20, OnPropertyChanged Renderer: 19, OnAppearing: 19

If I run iOS on a previous version of Xamarin Forms, its better (Xamarin, Mono Runtime 4.8.1):

InstrumentedViewCell counts: constructor: 69, OnPropertyChanged NameScope: 69, OnPropertyChanged Height: 67, OnPropertyChanged RenderHeight: 67, OnPropertyChanged View: 67, OnPropertyChanged BindingContext: 67, OnBindingContextChanged: 67, OnPropertyChanged Index: 67, OnParentSet: 67, OnPropertyChanged Parent: 67, OnPropertyChanged RealCell: 33, OnAppearing: 33
InstrumentedGrid counts: constructor: 67, InvalidateLayout: 67, OnSizeAllocated: 133, OnParentSet: 67, OnBindingContextChanged: 67, OnMeasure: 1, OnSizeRequest: 1, LayoutChildren: 66

The differences between iOS and Android (all are <100) are likely due to the display size of the different devices, and not a problem.  When it has to create 25000 instances to render a <20 rows, thats a problem.

# Test environment (full version information)

I hit this issue on our original application running Visual Studio 2015.  The isolated repro in the github issue was put together on Visual Studio for Mac.
Comment 1 Frank Schwieterman 2017-05-26 22:21:50 UTC
The problematic list looks like:

	<ListView HasUnevenRows="true" CachingStrategy="RecycleElement" x:Name="TheListView">
						<local:InstrumentedViewCell Height="50">
								<Label Text="{Binding .}" BackgroundColor="Green" />
                        <local:InstrumentedViewCell Height="60">
                                <Label Text="{Binding .}" />

The issue still repros without the DataTemplateSelector (replaced with just the InstrumentedViewCell/InstrumentedGrid/Label).  I included the DataTemplateSelector so the repro is closer to our original application.

  The InstrumentedViewCell.Height is included to make it easier for the ListView to determine the row heights (this was needed on the earlier version of Xamarin Forms to get good performance on iOS).  For this repro removing the Height attribute causes the problem to go away, but that doesn't work for our original application.  So removing the Height property is not a work-around that works for us.
Comment 2 Frank Schwieterman 2017-05-26 22:27:34 UTC
Oh yeah, the master branch has the repro.  Branch 'earlier-xamarin-forms' has an earlier version of Xamarin that doesn't repro the problem, demonstrating this is a regression.

Frank Schwieterman
Trainer Road LLC
Comment 3 Jimmy [MSFT] 2017-06-02 00:03:03 UTC
I ran the repro project on an iPhone device and I can confirm this issue. This seems to only be occurring on iOS.

When I launched the app, there was a significant loading time for the ListView to display. The project uses an ItemSource with 5000 items and it took about four and half minutes for the ListView to load.

As mentioned in comment 1, minimizing the ListView to use a single ItemTemplate instead of a DataTemplateSelector does not make a difference.

Downgrading the project back to Forms showed a significant difference in loading time. Now the list loaded in a couple of seconds with the original 5000 item list so this does appear to be a regression in Forms and not Xamarin.iOS itself.

### Regression Status   BAD
2.3.5-pre3  BAD   BAD   GOOD
Comment 4 Samantha Houts [MSFT] 2017-06-15 17:26:30 UTC
Comment 5 Rui Marinho 2017-06-23 10:53:32 UTC
Should be fixed on 2.3.5-pre5
Comment 9 Frank Schwieterman 2017-07-20 20:43:17 UTC
In case anyone wants to look at the original repro, it is in branch bugzilla-56896 at https://github.com/trainerroad/ListviewBugRepro