Bug 39608 - Potential memory leak with int[][]
Summary: Potential memory leak with int[][]
Status: RESOLVED NOT_REPRODUCIBLE
Alias: None
Product: Android
Classification: Xamarin
Component: Mono runtime / AOT Compiler ()
Version: 6.0.0
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Jonathan Pryor
URL:
Depends on:
Blocks:
 
Reported: 2016-03-14 18:37 UTC by Jon Douglas [MSFT]
Modified: 2017-07-06 16:45 UTC (History)
4 users (show)

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

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 NOT_REPRODUCIBLE

Description Jon Douglas [MSFT] 2016-03-14 18:37:51 UTC
*Description:

Given the following code:

    public class subClass
    {
        const int Size = 48000000;
        const int NumMono = 1;
        int[][] pixel = new int[NumMono][];
        static int cnt = 0;
        static long totalMemory = 0;

        public subClass()
        {
            for (int i = 0; i < NumMono; i++)
                pixel[i] = null;
            while (true)
            {
                pixel[cnt % NumMono] = new int[Size];
                totalMemory = System.GC.GetTotalMemory(false);
                Console.WriteLine("++totalMemory(" + cnt + "): " + totalMemory + "");

                pixel[cnt % NumMono] = null;
                totalMemory = System.GC.GetTotalMemory(false);
                Console.WriteLine("--totalMemory(" + cnt + "): " + totalMemory + "");

                cnt++;
                Task.Delay(100).Wait();
            }
        }
    }

Invoked via creating a new instance:

subClass myInst = new subClass();

It seems that the Mono GC does not collect this in the same fashion that .NET does. It seems to leak memory and lead to a:

[ERROR] FATAL UNHANDLED EXCEPTION: System.OutOfMemoryException: Out of memory - within a couple of iterations

EX:

03-14 14:28:57.826 I/mono-stdout(17962): ++totalMemory(4): 964360520
03-14 14:28:57.830 I/art     (17962): Starting a blocking GC Explicit
--totalMemory(4): 964360520
03-14 14:28:57.844 I/art     (17962): Explicit concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 40% free, 14MB/24MB, paused 225us total 13.193ms
03-14 14:28:57.844 D/Mono    (17962): GC_OLD_BRIDGE num-objects 2 num_hash_entries 2 sccs size 2 init 0.00ms df1 0.03ms sort 0.00ms dfs2 0.02ms setup-cb 0.06ms free-data 0.05ms links 1/1/1/1 dfs passes 5/3
03-14 14:28:57.844 D/Mono    (17962): GC_MAJOR: (user request) pause 2.57ms, total 2.68ms, bridge 0.00ms major 880K/0K los 937508K/0K
03-14 14:28:57.844 I/mono-stdout(17962): --totalMemory(4): 964360520
++totalMemory(5): 1156360536
03-14 14:28:57.945 I/mono-stdout(17962): ++totalMemory(5): 1156360536
03-14 14:28:57.948 I/art     (17962): Starting a blocking GC Explicit
03-14 14:28:57.960 I/art     (17962): Explicit concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 40% free, 14MB/24MB, paused 228us total 11.899ms
--totalMemory(5): 1156360536
03-14 14:28:57.961 D/Mono    (17962): GC_OLD_BRIDGE num-objects 2 num_hash_entries 2 sccs size 2 init 0.00ms df1 0.03ms sort 0.00ms dfs2 0.02ms setup-cb 0.06ms free-data 0.05ms links 1/1/1/1 dfs passes 5/3
03-14 14:28:57.961 D/Mono    (17962): GC_MAJOR: (user request) pause 2.44ms, total 2.52ms, bridge 0.00ms major 880K/0K los 1125008K/0K
03-14 14:28:57.961 I/mono-stdout(17962): --totalMemory(5): 1156360536
++totalMemory(6): 1348360552
03-14 14:28:58.062 I/mono-stdout(17962): ++totalMemory(6): 1348360552
--totalMemory(6): 1348360552
03-14 14:28:58.065 I/art     (17962): Starting a blocking GC Explicit
03-14 14:28:58.078 I/art     (17962): Explicit concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 40% free, 14MB/24MB, paused 230us total 12.421ms
03-14 14:28:58.078 D/Mono    (17962): GC_OLD_BRIDGE num-objects 2 num_hash_entries 2 sccs size 2 init 0.00ms df1 0.10ms sort 0.00ms dfs2 0.02ms setup-cb 0.04ms free-data 0.05ms links 1/1/1/1 dfs passes 5/3
03-14 14:28:58.079 D/Mono    (17962): GC_MAJOR: (user request) pause 2.73ms, total 2.80ms, bridge 0.00ms major 880K/0K los 1312508K/0K
03-14 14:28:58.079 I/mono-stdout(17962): --totalMemory(6): 1348360552
++totalMemory(7): 1540360568
03-14 14:28:58.180 I/mono-stdout(17962): ++totalMemory(7): 1540360568
03-14 14:28:58.183 I/art     (17962): Starting a blocking GC Explicit
--totalMemory(7): 1540360568
03-14 14:28:58.196 I/art     (17962): Explicit concurrent mark sweep GC freed 3(96B) AllocSpace objects, 0(0B) LOS objects, 40% free, 14MB/24MB, paused 227us total 12.431ms
03-14 14:28:58.197 D/Mono    (17962): GC_OLD_BRIDGE num-objects 2 num_hash_entries 2 sccs size 2 init 0.00ms df1 0.10ms sort 0.00ms dfs2 0.02ms setup-cb 0.04ms free-data 0.05ms links 1/1/1/1 dfs passes 5/3
03-14 14:28:58.197 D/Mono    (17962): GC_MAJOR: (user request) pause 2.76ms, total 2.83ms, bridge 0.00ms major 880K/0K los 1500008K/0K
03-14 14:28:58.197 I/mono-stdout(17962): --totalMemory(7): 1540360568
Unhandled Exception:

System.OutOfMemoryException: Out of memory

However on .NET, memory seems to be collected and it stays relatively the same:

++totalMemory(18): 192224120
--totalMemory(18): 192224460
++totalMemory(19): 192224120
--totalMemory(19): 192224660
++totalMemory(20): 192224120
--totalMemory(20): 192224460
++totalMemory(21): 192224120
--totalMemory(21): 192224660
++totalMemory(22): 192224120
--totalMemory(22): 192224460
++totalMemory(23): 192224120
--totalMemory(23): 192224660
++totalMemory(24): 192224120
--totalMemory(24): 192224460
++totalMemory(25): 192224120
--totalMemory(25): 192224660
++totalMemory(26): 192224120
--totalMemory(26): 192224460
++totalMemory(27): 192224172
--totalMemory(27): 192224712
++totalMemory(28): 192224172
--totalMemory(28): 192224512
++totalMemory(29): 192224172
--totalMemory(29): 192224712
++totalMemory(30): 192224172
--totalMemory(30): 192224512
++totalMemory(31): 192224172
--totalMemory(31): 192224712
++totalMemory(32): 192224172
--totalMemory(32): 192224512
++totalMemory(33): 192224172
--totalMemory(33): 192224712

*Reproduction:

1. Create a new File -> New Android Project

2. Paste the following Gist into your MainActivity(Change Namespaces/etc if needed):

https://gist.github.com/JonDouglas/b119a4d0042fbb89ab26

*Version Information:

Xamarin - 4.0.1.145
Xamarin.Android - 6.0.2.1
Comment 1 Brendan Zagaeski (Xamarin Team, assistant) 2016-03-14 18:45:26 UTC
At first glance this looks like it might be related to the "false pinning" behavior described in Bug 28958, and in particular Bug 28958, Comment 5.
Comment 2 Prashant [MSFT] 2017-06-29 06:50:39 UTC
Unfortunately, we’re unable to reproduce this report on Xamarin 15.2. If this issue is still occurring for you, please reopen this issue and attach a reproduction to the bug by starting with a clean Xamarin.Android project adding just the code necessary to demonstrate the issue.
Comment 3 Prashant [MSFT] 2017-07-06 16:45:06 UTC
I have tested this bug on Galaxy S7E, Google Pixel, and emulators running Android 6 and 7 respectively

This is does not occur with the new GC implementation in Xamarin.Android, when we change the gc bridge to old[1] the total memory usage increases slowly.



1. https://developer.xamarin.com/guides/android/advanced_topics/garbage_collection/#GC_Bridge_Options