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
Status: VERIFIED FIXED
Alias: None
Product: Forms
Classification: Xamarin
Component: iOS (show other bugs)
Version: 2.3.5
Hardware: Macintosh Mac OS
: Highest critical
Target Milestone: ---
Assignee: Samantha Houts [MSFT]
URL:
Depends on:
Blocks:
 
Reported: 2017-05-26 22:14 UTC by Frank Schwieterman
Modified: 2017-07-20 20:43 UTC (History)
12 users (show)

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


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

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 2.3.4.247 with Mono Runtime 5.0.1.1 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 2.3.4.247, Mono Runtime 5.0.1.1):

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 2.3.3.193, 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">
		<ListView.ItemTemplate>
			<local:ParityDataTemplateSelector>
				<local:ParityDataTemplateSelector.OddTemplate>
					<DataTemplate>
						<local:InstrumentedViewCell Height="50">
							<local:InstrumentedGrid>
								<Label Text="{Binding .}" BackgroundColor="Green" />
							</local:InstrumentedGrid>
						</local:InstrumentedViewCell>
					</DataTemplate>
				</local:ParityDataTemplateSelector.OddTemplate>
                <local:ParityDataTemplateSelector.EvenTemplate>
                    <DataTemplate>
                        <local:InstrumentedViewCell Height="60">
                            <local:InstrumentedGrid>
                                <Label Text="{Binding .}" />
                            </local:InstrumentedGrid>
                        </local:InstrumentedViewCell>
                    </DataTemplate>
                </local:ParityDataTemplateSelector.EvenTemplate>				
			</local:ParityDataTemplateSelector>
		</ListView.ItemTemplate>
	</ListView>


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.

regards,
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 2.3.3.193 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
2.3.6.109   BAD
2.3.5-pre3  BAD
2.3.4.247   BAD
2.3.3.193   GOOD
Comment 4 Samantha Houts [MSFT] 2017-06-15 17:26:30 UTC
https://github.com/xamarin/Xamarin.Forms/pull/994
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

Note You need to log in before you can comment on or make changes to this bug.