Bug 60496 - Memory leak when using DispatchQueue.MainQueue.DispatchAsync
Summary: Memory leak when using DispatchQueue.MainQueue.DispatchAsync
Status: RESOLVED ANSWERED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: XI 11.2 (d15-4)
Hardware: PC Windows
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2017-11-02 15:35 UTC by Shane
Modified: 2017-11-02 18:24 UTC (History)
3 users (show)

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


Attachments
screen shot of Xam Profiler new allocations (15.58 KB, image/png)
2017-11-02 15:35 UTC, Shane
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 Shane 2017-11-02 15:35:03 UTC
Created attachment 25546 [details]
screen shot of Xam Profiler new allocations

I'm using Xamarin Profiler to try and locate some memory leaks in my app. One of the 3rd party libraries I use uses "DispatchQueue.MainQueue.DispatchAsync" and I noticed in the profiler  allocations of Corefoundation.DispatchQueue that just kept accumulating

So I wrote up a basic unit test


[Test]
        public void DispatchQueueMemoryLeak()
        {
            var totalMemory = System.GC.GetTotalMemory(false);
            var physicalMemory = NSProcessInfo.ProcessInfo.PhysicalMemory;
            var totalMemory2 = System.GC.GetTotalMemory(false);
            var physicalMemory2 = NSProcessInfo.ProcessInfo.PhysicalMemory;
            var totalMemoryDiff = totalMemory2 - totalMemory;
            GC.Collect();
            var startingMemory = System.GC.GetTotalMemory(false);
            for (int i = 0; i < 20; i++)
            {
                totalMemory = System.GC.GetTotalMemory(false);
                physicalMemory = NSProcessInfo.ProcessInfo.PhysicalMemory;

                DispatchQueue.MainQueue.DispatchAsync(new NSAction(() =>
                {

                }));

                GC.Collect();

                totalMemory2 = System.GC.GetTotalMemory(false);
                physicalMemory2 = NSProcessInfo.ProcessInfo.PhysicalMemory;
                totalMemoryDiff = totalMemory2 - totalMemory;
            }
            GC.Collect();
            var finishingMemory = System.GC.GetTotalMemory(false);            
            var totalDifference = finishingMemory - startingMemory;
        }


If I remove
 DispatchQueue.MainQueue.DispatchAsync(new NSAction(() =>
                {

                }));

then           

            var totalDifference = finishingMemory - startingMemory;

Always yields a value of zero

I googled around a bit about memory leaks like this and I'm curious if it's a retain cycle issue with the implementation of DispatchASync

If the call here
DispatchQueue.dispatch_async_f(this.handle, (IntPtr) GCHandle.Alloc((object) Tuple.Create<Action, DispatchQueue>(action, this)), DispatchQueue.static_dispatch);

should use a weak reference to "this" ?

I've also attached a screen shot of xam profiler after taking some snapshots while profiling the above test
Comment 1 Shane 2017-11-02 15:52:08 UTC
Microsoft Visual Studio Enterprise 2017 
Version 15.4.2
VisualStudio.15.Release/15.4.2+27004.2006
Microsoft .NET Framework
Version 4.7.02556

Installed Version: Enterprise

Visual Basic 2017   00369-60000-00001-AA951
Microsoft Visual Basic 2017

Visual C# 2017   00369-60000-00001-AA951
Microsoft Visual C# 2017

Visual C++ 2017   00369-60000-00001-AA951
Microsoft Visual C++ 2017

Visual F# 4.1   00369-60000-00001-AA951
Microsoft Visual F# 4.1

ASP.NET and Web Tools 2017   15.0.30925.0
ASP.NET and Web Tools 2017

ASP.NET Core Razor Language Services   1.0
Provides languages services for ASP.NET Core Razor.

ASP.NET Web Frameworks and Tools 2017   5.2.50921.0
For additional information, visit https://www.asp.net/

Azure App Service Tools v3.0.0   15.0.30915.0
Azure App Service Tools v3.0.0

Azure Data Lake Node   1.0
This package contains the Data Lake integration nodes for Server Explorer.

Azure Data Lake Tools for Visual Studio   2.3.0000.1
Microsoft Azure Data Lake Tools for Visual Studio

Azure Data Lake Tools for Visual Studio   2.3.0000.1
Microsoft Azure Data Lake Tools for Visual Studio

Command Task Runner   1.2.34
Adds support for command line batch files in Visual Studio 2015's Task Runner Explorer. Supports .cmd, .bat, .ps1 and .psm1 files.

Common Azure Tools   1.10
Provides common services for use by Azure Mobile Services and Microsoft Azure Tools.

Fabric.DiagnosticEvents   1.0
Fabric Diagnostic Events

GitHub.VisualStudio   2.3.4.54
A Visual Studio Extension that brings the GitHub Flow into Visual Studio.

JavaScript Language Service   2.0
JavaScript Language Service

JavaScript Project System   2.0
JavaScript Project System

JavaScript UWP Project System   2.0
JavaScript UWP Project System

JetBrains ReSharper Ultimate 2017.2.2    Build 109.0.20171006.122324
JetBrains ReSharper Ultimate package for Microsoft Visual Studio. For more information about ReSharper Ultimate, visit http://www.jetbrains.com/resharper. Copyright © 2017 JetBrains, Inc.

Markdown Editor   1.11.214
A full featured Markdown editor with live preview and syntax highlighting. Supports GitHub flavored Markdown.

Merq   1.1.17-rc (cba4571)
Command Bus, Event Stream and Async Manager for Visual Studio extensions.

Microsoft Azure HDInsight Azure Node   2.3.0000.1
HDInsight Node under Azure Node

Microsoft Azure Hive Query Language Service   2.3.0000.1
Language service for Hive query

Microsoft Azure Service Fabric Tools for Visual Studio   1.8
Microsoft Azure Service Fabric Tools for Visual Studio

Microsoft Azure Stream Analytics Language Service   2.3.0000.1
Language service for Azure Stream Analytics

Microsoft Azure Stream Analytics Node   1.0
Azure Stream Analytics Node under Azure Node

Microsoft Azure Tools   2.9
Microsoft Azure Tools for Microsoft Visual Studio 2017 - v2.9.50719.1

Microsoft Continuous Delivery Tools for Visual Studio   0.3
Simplifying the configuration of continuous build integration and continuous build delivery from within the Visual Studio IDE.

Microsoft JVM Debugger   1.0
Provides support for connecting the Visual Studio debugger to JDWP compatible Java Virtual Machines

Microsoft MI-Based Debugger   1.0
Provides support for connecting Visual Studio to MI compatible debuggers

Microsoft Visual C++ Wizards   1.0
Microsoft Visual C++ Wizards

Microsoft Visual Studio VC Package   1.0
Microsoft Visual Studio VC Package

Mono Debugging for Visual Studio   4.7.4-pre (c2d89eb)
Support for debugging Mono processes with Visual Studio.

NPM Task Runner   1.4.81
Adds support for npm scripts defined in package.json directly in Visual Studio's Task Runner Explorer. Includes full support for Yarn

NuGet Package Manager   4.4.0
NuGet Package Manager in Visual Studio. For more information about NuGet, visit http://docs.nuget.org/.

OptionsPackage Extension   1.0
OptionsPackage Visual Studio Extension Detailed Info

OzCode   1.0
Your road to Magical Debugging. http://www.oz-code.com

OzCodePackage Extension   1.0
OzCodePackage Visual Studio Extension Detailed Info

Project   1.0
Information about my package

Redgate ReadyRoll   1.14.20.5993
Extend DevOps processes to your SQL Server databases and safely automate database deployments.
    
Visit https://www.red-gate.com/readyroll for more information.

Copyright (C) 2011 Red Gate Software Ltd. All rights reserved.
  
This software contains components from Component Owl.
SQL Server is a registered trademark of Microsoft Corporation. 
Visual Studio is a registered trademark of Microsoft Corporation. 

ReadyRoll contains code from the following open source software:

NuGet https://www.nuget.org/
SQL LocalDB Wrapper https://github.com/martincostello/sqllocaldb
Autofac https://autofac.org/
Json.NET https://json.net/
MahApps.Metro http://mahapps.com/
SemVer https://github.com/maxhauser/semver
Log4Net http://logging.apache.org/log4net/
Extended WPF Toolkit https://wpftoolkit.codeplex.com/
Code InfoBox VSX http://www.codeproject.com/Articles/55196/Code-InfoBox-Visual-Studio-Extension-VSX
OctoPack https://github.com/OctopusDeploy/OctoPack
SQLite https://sqlite.org/

This product contains icons from http://www.visualpharm.com distributed under a free backlink license.

For license details or other notices relating to the above software, please see NOTICE.TXT and EULA.rtf in the ReadyRoll application folder.
    

Redgate SQL Prompt   8.2.5.2924
Write, format, and refactor SQL effortlessly

SQL Server Analysis Services   14.0.806.134
Microsoft SQL Server Analysis Services Designer 
Version 14.0.806.134

SQL Server Data Tools   15.1.61707.200
Microsoft SQL Server Data Tools

SQL Server Reporting Services   14.0.806.134
Microsoft SQL Server Reporting Services Designers 
Version 14.0.806.134

SsmsVsIntegration   1.0
Information about my package

TargetFrameworkMigrator   1.0
Bulk Change .Net Projects Target Frameworks

ToolWindowHostedEditor   1.0
Hosting json editor into a tool window

TypeScript   2.3.5.0
TypeScript tools for Visual Studio

Typewriter   1.15.0
Typewriter generates TypeScript files from c# code files using TypeScript Templates. This allows you to create fully typed TypeScript representations of server side API that automatically updates when you make changes to your c# code.

Visual Studio Code Debug Adapter Host Package   1.0
Interop layer for hosting Visual Studio Code debug adapters in Visual Studio

Visual Studio Tools for Unity   3.4.0.2
Visual Studio Tools for Unity

Visual Studio Tools for Universal Windows Apps   15.0.27004.2006
The Visual Studio Tools for Universal Windows apps allow you to build a single universal app experience that can reach every device running Windows 10: phone, tablet, PC, and more. It includes the Microsoft Windows 10 Software Development Kit.

VisualStudio.IoT   1.0
Package with IoT components for Visual Studio

VisualStudio.Mac   1.0
Mac Extension for Visual Studio

Vue.js Pack 2017   1.1.8
Contains HTML Intellisense and code snippets for the Vue.js JavaScript library

WebJobs Tools v1.0.0   15.0.30923.0
WebJobs Tools v1.0.0

WebPack Task Runner   1.5.91
Adds support for WebPack in Visual Studio 2015's Task Runner Explorer.

Xamarin   4.7.10.33 (70936af)
Visual Studio extension to enable development for Xamarin.iOS and Xamarin.Android.

Xamarin.Android SDK   8.0.2.1 (HEAD/c2a33d8ea)
Xamarin.Android Reference Assemblies and MSBuild support.

Xamarin.iOS and Xamarin.Mac SDK   11.2.1.0 (12e80e0)
Xamarin.iOS and Xamarin.Mac Reference Assemblies and MSBuild support.
Comment 2 Rolf Bjarne Kvinge [MSFT] 2017-11-02 17:14:05 UTC
DispatchQueue.DispatchAsync will use the memory until the actions you queue have been executed, and you're not waiting for them to finish executing before checking if the memory has been reclaimed.

Try putting a button in a test app, and execute the test method when the button is pressed. If you press the button multiple times (say 5-10), you should see that the memory is freed between button presses. Can you try this and see what happens?
Comment 3 Shane 2017-11-02 18:24:14 UTC
Aw yea that totally makes sense

I guess where I got on the wrong track is that I kind of thought I had already done that :-/

At first I was just running this in an nunit UI Test project that would just run the loop. I'd take a snapshot before the test, run the test, wait some time, snapshot, and then it'd show basically the screen shot I attached from the profiler. It'd show some number of allocations of DispatchQueue that were never retained.

But I just created a really basic xamarin ios project with a button and in that scenario the profiler doesn't report those allocations as staying around plus I can see the memory in that project even out.. 

My application hooked to Xam Profiler they seem to stick around according to snapshots diffs so just need to narrow it down a bit more.

Thank you for the quick reply