Bug 42721 - ViewControllers not being garbage collected when pushed onto navigation stack
Summary: ViewControllers not being garbage collected when pushed onto navigation stack
Status: RESOLVED ANSWERED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: XI 9.8 (tvOS / C7)
Hardware: Macintosh Mac OS
: Highest blocker
Target Milestone: Untriaged
Assignee: Rolf Bjarne Kvinge [MSFT]
URL:
Depends on:
Blocks:
 
Reported: 2016-07-21 18:26 UTC by Alex Blount
Modified: 2016-07-22 13:39 UTC (History)
5 users (show)

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


Attachments
Reproduction (12.14 KB, application/zip)
2016-07-21 18:26 UTC, Alex Blount
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 ANSWERED

Description Alex Blount 2016-07-21 18:26:32 UTC
Created attachment 16749 [details]
Reproduction

When creating a managed object backed view controller being added to a navigation controller either through a segue in a storyboard or using code the instance is never garbage collected even when popped from the stack.

When adding a view controller to the navigation stack using a segue which is not assigned a class in the storyboard then it is happily garbage collected.



=== Xamarin Studio Enterprise ===

Version 6.0.1 (build 9)
Installation UUID: a157ecbd-42c7-4410-840b-1d3ec6c88add
Runtime:
	Mono 4.4.1 (mono-4.4.0-branch-c7sr0/4747417) (64-bit)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 404010000

=== Xamarin.Profiler ===

Version: 0.33.2
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

=== Apple Developer Tools ===

Xcode 7.3.1 (10188.1)
Build 7D1014

=== Xamarin.Android ===

Version: 6.1.1.1 (Xamarin Enterprise)
Android SDK: /Users/blounty/Library/Developer/Xamarin/android-sdk-macosx
	Supported Android versions:
		6.0 (API level 23)

SDK Tools Version: 25.1.2
SDK Platform Tools Version: 24.0.0
SDK Build Tools Version: 23.0.2

Java SDK: /usr
java version "1.7.0_71"
Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)

Android Designer EPL code available here:
https://github.com/xamarin/AndroidDesigner.EPL

=== Xamarin Android Player ===

Version: 0.6.5
Location: /Applications/Xamarin Android Player.app

=== Xamarin.Mac ===

Version: 2.8.1.4 (Xamarin Enterprise)

=== Xamarin.iOS ===

Version: 9.8.1.4 (Xamarin Enterprise)
Hash: 3cf8aae
Branch: c7sr0
Build date: 2016-06-20 16:09:58-0400

=== Xamarin Inspector ===

Version: 0.9.0.14
Hash: 4d868da
Branch: master
Build date: Mon Jun 13 19:14:13 UTC 2016

=== Build Information ===

Release ID: 600010009
Git revision: e879ce52093257c5c386ad7e390dfaa937fa7f90
Build date: 2016-06-24 11:53:43-04
Xamarin addins: a9252e6df4851fbbed1f9c6228e7b6dd1b475ac5
Build lane: monodevelop-lion-cycle7-sr0

=== Operating System ===

Mac OS X 10.12.0
Darwin Alexs-MBP.home 16.0.0 Darwin Kernel Version 16.0.0
    Tue Jun 28 15:57:40 PDT 2016
    root:xnu-3757.0.0.0.1~20/RELEASE_X86_64 x86_64

=== Enabled user installed addins ===

Xamarin Inspector 0.9.0.14
Comment 1 Alex Blount 2016-07-21 19:08:12 UTC
Instruments walk through:

https://youtu.be/wmYQkAX1b8s
Comment 2 Sebastien Pouliot 2016-07-22 00:59:42 UTC
It's unclear what you're trying to show in your video. Your sample shows 3 different scenarios:

1. the OS loads a native/naked UIViewController, with no managed state. The XI runtime treat them differently since we can always re-create the managed wrapper on demand. In such case the native instance will exists as long as the owner (OS) keeps a reference to it (but the managed instance can be disposed);

2. the OS loads a managed MyViewController, with (assumed) managed state. The XI runtime cannot recreate them so they'll be kept around as long as the native peer exists. In such case both the native and managed instance will exists as long as the owner (OS) keeps a reference to it;

3. the application (code) loads a naked UIViewController (no managed state). Similar to #1 except for the ownership. In such case you (optionally) have control of the lifetime of the instances;

All three (and more) scenarios will behave differently and that's normal.

I'll add some extra logging and try it myself.
Comment 3 Sebastien Pouliot 2016-07-22 02:13:56 UTC
I do not get those results (nor leaks), either measuring them individually or repeating something close to the video. OTOH I did not have an exact match (master with Xcode 8 b3).

@Rolf can you try to duplicate it (with whatever version you have presently) ? and do you recall any change since C7 that could affect this ? (the delta should be small since most work was done on xcode8 or watchOS recently).

@Alex going on the other sense, can you tell us which previous version of XI was working ? if this was fixed after that we'll need to make sure it's totally fixed (and that means finding where it started, not just where it ended).

Thanks!
Comment 4 Alex Blount 2016-07-22 06:36:26 UTC
@Sebastien the only thing I am trying to show is that the instances of view controllers which have managed state are never garbage collected, they hang around permanently. This seems to mirror an issue from last year which @Rolf fixed. So:

1: Correctly disposes
2: is not disposing
3: is not disposing

As you say the all behave differently but at some point they should all be disposed / collected.
Comment 5 Rolf Bjarne Kvinge [MSFT] 2016-07-22 12:59:51 UTC
So I can reproduce leaks in the current stable release (9.8.1.4), but not master.
Comment 6 Rolf Bjarne Kvinge [MSFT] 2016-07-22 13:21:07 UTC
So there was a regression of sorts, but not really a bug.

We've had a feature in the simulator where we run the GC every second, to help developers detect bugs related to object lifetime.

We regressed that feature, meaning that we stopped running the GC every second (which is fixed in the master).

This means that there's no leak, you're just seeing the GC waiting for enough memory to be allocated for it to run.

In other words adding a simple call to GC.Collect in the test project makes the "leaks" go away.
Comment 7 Sebastien Pouliot 2016-07-22 13:26:02 UTC
@Alex in _most_ cases yes, but you cant generalize this as it depends on the API, e.g. some UIImage API ends up caching images, UITableViewCell are also cached (and that's out of your control)

@Rolf awesome! that was surprising as the C8/master delta was even smaller. Was this backported to C8 ? and can we backport it to C7 ?
Comment 8 Rolf Bjarne Kvinge [MSFT] 2016-07-22 13:29:30 UTC
@Sebastien, this is the fix: https://github.com/xamarin/xamarin-macios/commit/d9677714

It was fixed before C8 was branched, so the fix is in both master and C8.

It should be trivial to backport to C7 if we wish (but imho it's not a high priority backport).