Bug 31170 - Xamarin.Android.Support.v7.RecyclerView version 22.1.1.1+ leaks RecyclerViews when using item decoration
Summary: Xamarin.Android.Support.v7.RecyclerView version 22.1.1.1+ leaks RecyclerViews...
Status: RESOLVED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: General ()
Version: 5.1
Hardware: PC Mac OS
: Normal major
Target Milestone: ---
Assignee: Jonathan Pryor
URL:
Depends on:
Blocks:
 
Reported: 2015-06-16 17:01 UTC by Brendan Zagaeski (Xamarin Team, assistant)
Modified: 2015-12-02 19:38 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Test case (33.94 KB, application/zip)
2015-06-16 17:01 UTC, Brendan Zagaeski (Xamarin Team, assistant)
Details
Profiler files and version information (578.89 KB, application/zip)
2015-06-16 17:03 UTC, Brendan Zagaeski (Xamarin Team, assistant)
Details
Test case (34.32 KB, application/zip)
2015-06-16 19:44 UTC, Brendan Zagaeski (Xamarin Team, assistant)
Details


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:
Status:
RESOLVED FIXED

Description Brendan Zagaeski (Xamarin Team, assistant) 2015-06-16 17:01:56 UTC
Created attachment 11627 [details]
Test case

Xamarin.Android.Support.v7.RecyclerView version 21.1.1.1+ leaks RecyclerViews when using item decoration


Regression status: regression between RecyclerView version 21.0.3.0 and RecyclerView version 21.1.1.1




## Steps to reproduce

1. Launch the Xamarin Android Player (Nexus 4, KitKat) emulator.


2. Enable heapshot profiling:
> $ adb shell setprop 'debug.mono.profile' 'log:heapshot'


3. Launch the attached test case in the "Debug" configuration on the emulator.


4. Tap the "Hello World, Click Me!" button 10 times.


5. Download the "profile.mlpd" file from the device:
> $ adb pull /data/data/com.companyname.androidapp1/files/.__override__/profile.mlpd


6. Filter the profile data for item counts that increase or decrease over the 10 button clicks:
> $ mprof-report --alloc-sort=count profile.mlpd | grep 'count: [+-][^0]\|Heap shot [0-9]'




## Results with Xamarin.Android.Support.v7.RecyclerView version 22.1.1.1

(The results are also the same on version 22.2.0.0.)


The `Android.Support.V7.Widget.RecyclerView` type leaks:

> Heap shot 0 at 41.024 secs: size: 187216, object count: 3227, class count: 163, roots: 0
> Heap shot 1 at 41.626 secs: size: 198912, object count: 3452, class count: 163, roots: 0
>       2592        162       16 System.WeakReference (bytes: +752, count: +47)
>       4560        143       31 System.WeakReference[] (bytes: +1728, count: +54)
>       3408        142       24 System.Collections.Generic.List`1 (bytes: +1296, count: +54)
>       4128         43       96 Android.Widget.LinearLayout (bytes: +1728, count: +18)
>       4128         43       96 Android.Widget.TextView (bytes: +1728, count: +18)
>       1720         43       40 AndroidApp1.ItemViewHolder (bytes: +720, count: +18)
>       2976         31       96 Android.Support.V7.Widget.RecyclerView (bytes: +1536, count: +16)
> Heap shot 2 at 42.204 secs: size: 204984, object count: 3586, class count: 163, roots: 0
>       3120        195       16 System.WeakReference (bytes: +528, count: +33)
>       5392        169       31 System.WeakReference[] (bytes: +832, count: +26)
>       4032        168       24 System.Collections.Generic.List`1 (bytes: +624, count: +26)
>       5184         54       96 Android.Widget.TextView (bytes: +1056, count: +11)
>       5184         54       96 Android.Widget.LinearLayout (bytes: +1056, count: +11)
>       2160         54       40 AndroidApp1.ItemViewHolder (bytes: +440, count: +11)
>       4512         47       96 Android.Support.V7.Widget.RecyclerView (bytes: +1536, count: +16)
> Heap shot 3 at 42.810 secs: size: 208680, object count: 3686, class count: 163, roots: 0
>      92080       1154       79 unresolved class 0xb80820c0 (bytes: +80, count: +1)
>       3536        221       16 System.WeakReference (bytes: +416, count: +26)
>       6288        197       31 System.WeakReference[] (bytes: +896, count: +28)
>       4704        196       24 System.Collections.Generic.List`1 (bytes: +672, count: +28)
>       6144         64       96 Android.Support.V7.Widget.RecyclerView (bytes: +1632, count: +17)
> Heap shot 4 at 43.384 secs: size: 217240, object count: 3758, class count: 163, roots: 0
>       3984        249       16 System.WeakReference (bytes: +448, count: +28)
>       6736        211       31 System.WeakReference[] (bytes: +448, count: +14)
>       5040        210       24 System.Collections.Generic.List`1 (bytes: +336, count: +14)
>       7680         80       96 Android.Support.V7.Widget.RecyclerView (bytes: +1536, count: +16)
> Heap shot 5 at 43.971 secs: size: 219728, object count: 3814, class count: 163, roots: 0
>       4208        263       16 System.WeakReference (bytes: +224, count: +14)
>       7152        224       31 System.WeakReference[] (bytes: +416, count: +13)
>       5352        223       24 System.Collections.Generic.List`1 (bytes: +312, count: +13)
>       9216         96       96 Android.Support.V7.Widget.RecyclerView (bytes: +1536, count: +16)




## "Expected results" with Xamarin.Android.Support.v7.RecyclerView version 21.0.3.0

There are no leaks:

> Heap shot 0 at 2.378 secs: size: 177592, object count: 3065, class count: 163, roots: 0
> Heap shot 1 at 2.971 secs: size: 177400, object count: 3053, class count: 163, roots: 0
>       1648        103       16 System.WeakReference (bytes: -192, count: -12)
> Heap shot 2 at 3.669 secs: size: 177400, object count: 3053, class count: 163, roots: 0
> Heap shot 3 at 4.284 secs: size: 177400, object count: 3053, class count: 163, roots: 0
> Heap shot 4 at 4.822 secs: size: 177400, object count: 3053, class count: 163, roots: 0
> Heap shot 5 at 5.326 secs: size: 177400, object count: 3053, class count: 163, roots: 0
> Heap shot 6 at 5.788 secs: size: 177400, object count: 3053, class count: 163, roots: 0
> Heap shot 7 at 6.235 secs: size: 177400, object count: 3053, class count: 163, roots: 0
> Heap shot 8 at 6.637 secs: size: 177400, object count: 3053, class count: 163, roots: 0
> Heap shot 9 at 7.102 secs: size: 177408, object count: 3053, class count: 163, roots: 0




## Partial workaround

Remove or comment out the `OnDraw()` override in EmptyItemDecoration:

> public override void OnDraw(Android.Graphics.Canvas c, RecyclerView parent, RecyclerView.State state)
> {
>     base.OnDraw(c, parent, state);
> }



### Results

The heapshots no longer show the `RecyclerView` type.




## Version information (brief)



### Devices

Xamarin Android Player 0.3.7 (1), Nexus 4 (KitKat)



### OS X 10.10.3

=== Xamarin.Android ===

Version: 5.1.3.1 (Enterprise Edition)
Android SDK: /Users/macuser/Library/Developer/Xamarin/android-sdk-macosx
	Supported Android versions:
		2.3    (API level 10)
		4.0.3  (API level 15)
		4.1    (API level 16)
		4.2    (API level 17)
		4.3    (API level 18)
		4.4    (API level 19)
		4.4.87 (API level 20)
		5.0    (API level 21)
Java SDK: /usr
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)
Comment 1 Brendan Zagaeski (Xamarin Team, assistant) 2015-06-16 17:03:08 UTC
Created attachment 11628 [details]
Profiler files and version information
Comment 3 Brendan Zagaeski (Xamarin Team, assistant) 2015-06-16 19:44:40 UTC
Created attachment 11637 [details]
Test case

Corrected test case: the original test case attachment was missing the `packages.config` file.
Comment 4 Jon Dick 2015-06-18 14:50:39 UTC
If you take a look at the number of times onDraw is actually called in the java
app you will find that in v21.0.3 of RecyclerView onDraw is not called every
time a call to itemAdapter.notifyItemChanged(i) is called.  This behaviour is
also seen in the Xamarin app using v21.0.3 of the binding.

In both v22.1.1 and v22.2.0 of RecyclerView in the java app, onDraw *is* called
each time itemAdapter.notifyItemChanged(i) is called.  This is also seen of
course in the Xamarin app with the bindings of those same versions.

I believe this accounts for the reference counts (or more importantly the GREF
activity) growing more rapidly in the later versions of this library's binding.
 I'm not sure that there's actually a leak here, but just different behaviours
between versions of the library that google has released.

To minimize the impact, you can of course call itemAdapter.notifyDatasetChanged
() after you've updated all your items instead of telling the adapter each item
has changed, in which case onDraw should be called less often.
Comment 5 Brendan Zagaeski (Xamarin Team, assistant) 2015-06-18 14:57:47 UTC
If the problem can also be reproduced in version 21.0.3, then I would agree that it is not a _regression_. It might also mean the underlying problem is within Xamarin.Android rather than within the RecyclerView component.

But I am calling `GC.Collect()` and `GC.WaitForPendingFinalizers()` after every button click, and the number of GREFs still increases after each button click. That means that eventually the app will hit the maximum GREF limit and be "stuck" there, unable to allocate any more memory, no matter how many times the garbage collector runs. That is something that needs to be fixed on the Xamarin side.

I will investigate using version 21.0.3 to see if I can indeed reproduce the problem on that version by forcing `OnDraw()` to be invoked more often.
Comment 6 Peter Collins 2015-12-02 19:38:58 UTC
I _believe_ this was fixed as part of the cycle6 release, or is at least no longer reproducible using XA 6.0.0.34.

Using XA 5.1.x, I was able to reproduce the steady gref increase on each button tap with the provided project. However, after upgrading to the now stable C6 build, I'm never seeing the gref count exceed 200, even after 150 button taps or so.