{"id":2943,"date":"2013-06-20T23:25:00","date_gmt":"2013-06-20T23:25:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/visualstudioalm\/2013\/06\/20\/using-visual-studio-2013-to-diagnose-net-memory-issues-in-production\/"},"modified":"2022-07-19T06:57:08","modified_gmt":"2022-07-19T14:57:08","slug":"using-visual-studio-2013-to-diagnose-net-memory-issues-in-production","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/devops\/using-visual-studio-2013-to-diagnose-net-memory-issues-in-production\/","title":{"rendered":"Using Visual Studio 2013 to Diagnose .NET Memory Issues in Production"},"content":{"rendered":"<p><em>Update: Note this post has been updated for Visual Studio 2013 RTM and is the first of a two-part series.\u00a0 In the screenshots and examples Just My Code and Collapse Small Objects are disabled as covered in <a href=\"http:\/\/blogs.msdn.com\/b\/visualstudioalm\/archive\/2013\/10\/16\/net-memory-analysis-enhancements-in-visual-studio-2013.aspx\">part 2<\/a>.\u00a0 It is recommended that you read this post before reading <a href=\"http:\/\/blogs.msdn.com\/b\/visualstudioalm\/archive\/2013\/10\/16\/net-memory-analysis-enhancements-in-visual-studio-2013.aspx\">part 2<\/a>.<\/em><\/p>\n<p>One of the issues that frequently affects .NET applications running in production environments is problems with their memory use which can impact both the application and potentially the entire machine. To help with this, we\u2019ve introduced a feature in Visual Studio 2013 to help you understand the .NET memory use of your applications from <a href=\"http:\/\/blogs.msdn.com\/b\/debugger\/archive\/2009\/12\/30\/what-is-a-dump-and-how-do-i-create-one.aspx\">.dmp files<\/a> collected on production machines.<\/p>\n<p>In this post, I\u2019ll first discuss common types of memory problems and why they matter. I\u2019ll then walk through <a href=\"#sample\">an example<\/a> of how to collect data, and finally describe how to use the new functionality to solve memory problems in your applications.<\/p>\n<p>Before I begin, there are a few things to note about the &#8220;Debug Managed Memory&#8221; feature discussed in this post:<\/p>\n<ol>\n<li>The option will only be available from the dump summary page in the Ultimate version of Visual Studio 2013.\u00a0 If you are using Premium or Professional you will not see the option<\/li>\n<li>The process the dump file was collected against must have been running on .NET 4.5 or higher.\u00a0 If the dump was collected on 3.5 or previous the option will not appear, if it was collected on 4.0 it will fail to launch with an error message.<\/li>\n<\/ol>\n<h2>Why worry about memory problems<\/h2>\n<p>.NET is a garbage collected runtime, which means most of the time the framework\u2019s garbage collector takes care of cleaning up memory and the user never notices any impact. However, when an application has a problem with its memory this can have a negative impact on both the application and the machine.<\/p>\n<ol>\n<li>**Memory leaks **are places in an application where objects are meant to be temporary, but instead are left permanently in memory. In a garbage collected runtime like .NET, developers do not need to explicitly free memory like they need to do in a runtime like C++. However the garbage collector can only free memory that is no longer being used, which it determines based on whether the object is reachable (referenced) by other objects that are still active in memory. So a memory leak occurs in .NET when an object is still reachable from the roots of the application but should not be (e.g. a static event handler references an object that should be collected). When memory leaks occur, usually memory increases slowly over time until the application starts to exhibit poor performance.\u00a0 **Physical resource leaks **are a sub category of memory leaks where a physical resource such as a file, or OS handler is accidentally left open or retained. This can lead to errors later in execution as well as increased memory consumption.<\/li>\n<li>**Inefficient memory use **is when an application is using significantly more memory than intended at any given point in time, but the memory consumption is not the result of a leak. An example of inefficient memory use in a web application is querying a database and bringing back significantly more results than are needed by the application.<\/li>\n<li>**Unnecessary allocations. **In .NET, allocation is often quite fast, but overall cost can be deceptive, because the garbage collector (GC) needs to clean it up later. The more memory that gets allocated, the more frequently the GC will need to run. These GC costs are often negligible to the program\u2019s performance, but for certain kinds of apps, these costs can add up quickly and make a noticeable impact to the performance of the app<\/li>\n<\/ol>\n<p>If an application suffers from a memory problem, there are three common symptoms that may affect end users.<\/p>\n<ol>\n<li><strong>The application can crash with an \u201cOut of Memory\u201d exception.<\/strong> This is a relatively common problem for 32bit applications because they are limited to only 4GB of total <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa366912(v=vs.85).aspx\">Virtual Address Space<\/a>. It is however less common for 64bit applications because they are given much higher virtual address space limits by the operating system.<\/li>\n<li><strong>The application will begin to exhibit poor performance.<\/strong> This can occur because the garbage collector is running frequently and competing for CPU resources with the application, or because the application constantly needs to move memory between RAM (physical memory) and the hard drive (virtual memory); which is called paging.<\/li>\n<li><strong>Other applications running on the same machine exhibit poor performance.<\/strong> Because the CPU and physical memory are both system resources, if an application is consuming a large amount of these resources, other applications are left with insufficient amounts and will exhibit negative performance.<\/li>\n<\/ol>\n<p>In this post I\u2019ll be covering a new feature added to Visual Studio 2013 intended to help identify memory leaks and inefficient memory use (the first two problem types discussed above). If you are interested in tools to help identify problems related to unnecessary allocations, see <a href=\"http:\/\/blogs.msdn.com\/b\/dotnet\/archive\/2013\/04\/04\/net-memory-allocation-profiling-with-visual-studio-2012.aspx\">.NET Memory Allocation Profiling with Visual Studio 2012<\/a>.<\/p>\n<h2><a name=\"CollectingSample\"><\/a>Collecting the data<\/h2>\n<p>To understand how the new .NET memory feature for .dmp files helps us to find and fix memory problems let\u2019s walk through an example. For this purpose, I have introduced a memory leak when loading the Home page of a default MVC application created with Visual Studio 2013. However to simulate how a normal memory leak investigation works, we\u2019ll use the tool to identify the problem before we discuss the problematic source code.<\/p>\n<p>The first thing I am going to do is to launch the application without debugging to start the application in IIS Express. Next I am going to open <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/cc749249.aspx\">Windows Performance Monitor<\/a> to track the memory usage during my testing of the application. Next I\u2019ll add the \u201c.NET CLR Memory -> # Bytes in all Heaps\u201d counter, which will show me how much memory I\u2019m using in the .NET runtime (which I can see is ~ 3.5 MB at this point). You may use alternate or additional tools in your environment to detect when memory problems occur, I\u2019m simply using Performance Monitor as an example. The important point is that a memory problem is detected that you need to investigate further.<\/p>\n<p><img decoding=\"async\" title=\"HomePagewDefaultPerfMon\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/1325.HomePagewDefaultPerfMon_thumb_426D77BC.png\" alt=\"HomePagewDefaultPerfMon\" width=\"716\" height=\"609\" border=\"0\" \/><\/p>\n<p>The next thing I\u2019m going to do is refresh the home page five times to exercise the page load logic. After doing this I can see that my memory has increased from ~3.5 MB to ~13 MB so this seems to indicate that I may have a problem with my application\u2019s memory since I would not expect multiple page loads by the same user to result in a significant increase in memory.<\/p>\n<p><img decoding=\"async\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/3414.image_thumb_3024B0FA.png\" alt=\"image\" width=\"726\" height=\"461\" border=\"0\" \/><\/p>\n<p>For this example I\u2019m going to capture a dump of iisexpress.exe using <a href=\"http:\/\/technet.microsoft.com\/en-us\/sysinternals\/dd996900.aspx\">ProcDump<\/a>, and name it \u201ciisexpress1.dmp\u201d (notice I need to use the \u2013ma flag to capture the process memory, otherwise I won\u2019t be able to analyze the memory). You can read about alternate tools for capturing dumps in <a href=\"http:\/\/blogs.msdn.com\/b\/debugger\/archive\/2009\/12\/30\/what-is-a-dump-and-how-do-i-create-one.aspx\">what is a dump and how do I create one?<\/a><\/p>\n<p><img decoding=\"async\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/5141.image_thumb_56F2C73A.png\" alt=\"image\" width=\"621\" height=\"207\" border=\"0\" \/><\/p>\n<p>Now that I\u2019ve collected a baseline snapshot, I\u2019m going to refresh the page an additional 10 times. After the additional refreshes I can see that my memory use has increased to ~21 MB. So I am going to use procdump.exe again to capture a second dump I\u2019ll call \u201ciisexpress2.dmp\u201d<\/p>\n<p><img decoding=\"async\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/7230.image_thumb_68CF5B07.png\" alt=\"image\" width=\"732\" height=\"462\" border=\"0\" \/><\/p>\n<p>Now that we\u2019ve collected the dump files, we\u2019re ready to use Visual Studio to identify the problem.<\/p>\n<h2>Analyzing the dump files<\/h2>\n<p>The first thing we need to do to begin analysis is open a dump file. In this case I\u2019m going to choose the most recent dump file, \u201ciisexpress2.dmp\u201d.<\/p>\n<p><img decoding=\"async\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/0876.image_thumb_0F9D7148.png\" alt=\"image\" width=\"576\" height=\"438\" border=\"0\" \/><\/p>\n<p>Once the file is open, I\u2019m presented with the dump file summary page in Visual Studio that gives me information such as when the dump was created, the architecture of the process, the version of Windows, and what the version of the .NET runtime (CLR version) the process was running. To begin analyzing the managed memory, click \u201cDebug Managed Memory\u201d in the \u201cActions\u201d box in the top right.<\/p>\n<p><img decoding=\"async\" style=\"border-width: 0px\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/1563.image_thumb_3477E9A9.png\" alt=\"image\" width=\"767\" height=\"577\" border=\"0\" \/><\/p>\n<p>This will begin analysis<\/p>\n<p><img decoding=\"async\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/4812.image_thumb_48481B55.png\" alt=\"image\" width=\"768\" height=\"329\" border=\"0\" \/><\/p>\n<p>Once analysis completes I am presented with Visual Studio 2013\u2019s brand new managed memory analysis view. The window contains two panes, the top pane contains a list of the objects in the heap grouped by their type name with columns that show me their count and the total size. When a type or instance is selected in the top pane, the bottom one shows the objects that are referencing this type or instance which prevent it from being garbage collected.<\/p>\n<p><img decoding=\"async\" style=\"border: 0px\" title=\"dump2-summary\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/0160.dump2summary_thumb_2F02CFDC.png\" alt=\"dump2-summary\" width=\"773\" height=\"446\" border=\"0\" \/><\/p>\n<p>[Note: At this point Visual Studio is in debug mode since we are actually debugging the dump file, so I have closed the default debug windows (watch, call stack, etc.) in the screenshot above.]<\/p>\n<p>Thinking back to the test scenario I was running there are two issues I want to investigate. First, 16 page loads increased my memory by ~18 MB which appears to be an inefficient use of memory since each page load should not use over 1 MB. Second, as a single user I\u2019m requesting the same page multiple times, which I expect to have a minimal effect on the process memory, however the memory is increasing with every page load.<\/p>\n<h3><a name=\"instances\"><\/a>Improving the memory efficiency<\/h3>\n<p>First want to see if I can make page loading more memory efficient, so I\u2019ll start looking at the objects that are using the most memory in the type summary (top pane) of memory analysis window.<\/p>\n<p>Here I see that <em>Byte[]<\/em> is the type that is using the most memory, so I\u2019ll expand the <em>System.Byte[]<\/em> line to see the 10 largest <em>Byte[]<\/em>\u2019s in memory. I see that this and all of the largest <em>Byte[]\u2019s *are ~1 MB each which seems large so I want to determine what is using these large *Byte[]\u2019s<\/em>. Clicking on the first instance shows me this is being referenced by a <em>SampleLeak.Models.User<\/em> object (as are all of the largest <em>Byte[]<\/em>\u2019s if I work my way down the list).<\/p>\n<p><img decoding=\"async\" style=\"border: 0px\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/5543.image_thumb_4EB1A9A4.png\" alt=\"image\" width=\"784\" height=\"498\" border=\"0\" \/><\/p>\n<p>At this point I need to go to my application\u2019s source code to see what <em>User *is using the *Byte[] *for. Navigating to the definition of *User<\/em> in the sample project I can see that I have a <em>BinaryData<\/em> member that is of type <em>byte[]<\/em>. It turns out when I\u2019m retrieving my user from the database I\u2019m populating this field even though I am not using this data as part of the page load logic.<\/p>\n<blockquote>\n<p>public class User : IUser<br \/>\n  \u00a0\u00a0 {<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u2026<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 [Key]<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string Id { get; set; }<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string UserName { get; set; }<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public byte[] BinaryData { get; set; }<br \/>\n  \u00a0\u00a0 }<\/p>\n<\/blockquote>\n<p>Which is populated by the query<\/p>\n<blockquote>\n<p>User user = MockDatabase.SelectOrCreateUser(<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;select * from Users where Id = @p1&#8221;,<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 userID);<\/p>\n<\/blockquote>\n<p>In order to fix this, I need to modify my query to only retrieve the <em>Id<\/em> and <em>UserName<\/em> when I\u2019m loading a page, I\u2019ll retrieve the binary data later only if and when I need it.<\/p>\n<blockquote>\n<p>User user = MockDatabase.SelectOrCreateUser(<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;select Id, UserName from Users where Id = @p1&#8221;,<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 userID);<\/p>\n<\/blockquote>\n<h3>Finding the memory leak<\/h3>\n<p>The second problem I want to investigate is the continual growth of the memory that is indicating a leak. The ability to see what has changed over time is a very powerful way to find leaks, so I am going to compare the current dump to the first one I took. To do this, I expand the \u201cSelect Baseline\u201d dropdown, and choose \u201cBrowse\u2026\u201d This allows me to select \u201ciisexpress1.dmp\u201d as my baseline.<\/p>\n<p><img decoding=\"async\" style=\"border: 0px\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/8688.image_thumb_035205E0.png\" alt=\"image\" width=\"854\" height=\"135\" border=\"0\" \/><\/p>\n<p>Once the baseline finishes analyzing, I have an additional two columns, \u201cCount Diff\u201d and \u201cTotal Size Diff\u201d that show me the change between the baseline and the current dump. Since I see a lot of system objects I don\u2019t control in the list, I\u2019ll use the Search box to find all objects in my application\u2019s top level namespace \u201c<em>SampleLeak\u201d<\/em>. After I search, I see that <em>SampleLeak.Models.User<\/em> has increased the most in both size, and count (there are additional 10 objects compared to the baseline). This is a good indication that <em>User<\/em> may be leaking.<\/p>\n<p><img decoding=\"async\" style=\"border: 0px\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/3733.image_thumb_5C17BCAA.png\" alt=\"image\" width=\"865\" height=\"391\" border=\"0\" \/><\/p>\n<p>The next thing to do is determine why <em>User<\/em> objects are not being collected. To do this, I select the <em>SampleLeak.Models.User<\/em> row in the top table. This will then show me the reference graph for all <em>User<\/em> objects in the bottom pane. Here I can see that <em>SampleLeak.Models.User[]<\/em> has added an additional 10 references to <em>User<\/em> objects (notice the reference count diff matches the count diff of <em>User<\/em>).<\/p>\n<p><img decoding=\"async\" style=\"border: 0px\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/7450.image_thumb_058E8E9C.png\" alt=\"image\" width=\"872\" height=\"380\" border=\"0\" \/><\/p>\n<p>Since I don\u2019t remember explicitly creating a <em>User[]<\/em> in my code, I\u2019ll expand the reference graph back to the root to figure out what is referencing the <em>User[]<\/em>. Once I\u2019ve finished expansion, I can see that the <em>User[]<\/em> is part of a <em>List<User><\/em> which is directly being referenced by a that is a the static variable *SampleLeak.Data.UserRepository.m_userCache *(static variables are GC roots)<\/p>\n<p><img decoding=\"async\" style=\"border: 0px\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/0118.image_thumb_6C268B61.png\" alt=\"image\" width=\"885\" height=\"118\" border=\"0\" \/><\/p>\n<p>Next I\u2019ll go to the <em>UserRepository<\/em> class I added to the application.<\/p>\n<blockquote>\n<p>public static class UserRepository<br \/>\n  {<br \/>\n  \u00a0\u00a0\u00a0 \/\/Store a local copy of recent users in memory to prevent extra database queries<br \/>\n  \u00a0\u00a0\u00a0 static private List<User> m_userCache = new List<User>();<br \/>\n  \u00a0\u00a0\u00a0 public static List<User> UserCache { get { return m_userCache; } }<\/p>\n<p>\u00a0\u00a0\u00a0 public static User GetUser(string userID)<br \/>\n  \u00a0\u00a0\u00a0 {<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/Retrieve the user\u2019s database record<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 User user = MockDatabase.SelectOrCreateUser(<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;select Id, UserName from Users where Id = @p1&#8221;,<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 userID);<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/Add the user to cache before returning<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_userCache.Add(user);<br \/>\n  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return user;<br \/>\n  \u00a0\u00a0\u00a0 }<br \/>\n  }<\/p>\n<\/blockquote>\n<p>Note, at this point determining the right fix usually requires an understanding of how the application works. In the case of my sample application, when a user loads the <em>Home<\/em> page, the page\u2019s controller queries the <em>UserRepository<\/em> for the user\u2019s database record. If the user does not have an existing record a new one is created and returned to the controller. In my <em>UserRepository<\/em> I have created a static <em>List<User><\/em> I\u2019m using as a cache to keep local copies so I don\u2019t always need to query the database. However, statics are automatically rooted, which is why the <em>List<User><\/em> shows as directly referenced by a root rather than by UserRepository.<\/p>\n<p>Coming back to the investigation, a review of the logic in my <em>GetUser()<\/em> method reveals that the problem is I\u2019m not checking the cache before querying the database, so on every page load I\u2019m creating a new <em>User<\/em> object and adding it to the cache. To fix this problem I need to check the cache before querying the database.<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public static User GetUser(string userID)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/Check to see if the user is in the local cache<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var cachedUser = from user in m_userCache<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 where user.Id == userID<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 select user;<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (cachedUser.Count() > 0)<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return cachedUser.FirstOrDefault();<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/User is not in the local cache, retrieve user from the database<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 User user = MockDatabase.SelectOrCreateUser(<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &#8220;select * from Users where Id = @p1&#8221;,<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 userID);<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/Add the user to cache before returning<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 m_userCache.Add(user);<\/p>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return user;<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<br \/>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/p>\n<h2>Validating the fix<\/h2>\n<p>Once I make these changes I want to verify that I have correctly fixed the problem. In order to do this, I\u2019ll launch the modified application again and after 20 page refreshes, Performance Monitor shows me only a minimal increase in memory (some variation is to be expected as garbage builds up until it is collected).<\/p>\n<p>Just to definitely validate the fixes, I\u2019ll capture one more dump and a look at it shows me that <em>Byte[]<\/em> is no longer the object type taking up the most memory. When I do expand <em>Byte[]<\/em> I can see that the largest instance is much smaller than the previous 1 MB instances, and it is not being referenced by <em>User<\/em>. Searching for <em>User<\/em> shows me one instance in memory rather than 20, so I am confident I have fixed both of these issues.<\/p>\n<p><img decoding=\"async\" style=\"border: 0px\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2013\/06\/7558.image_thumb_72D994E4.png\" alt=\"image\" width=\"857\" height=\"540\" border=\"0\" \/><\/p>\n<h2>In Closing<\/h2>\n<p>We walked through a simple example that showed how to use Visual Studio 2013 to diagnose memory problems using dump files with heap. While the example was simple, hopefully you can see how this can be applied to memory problems you have with your applications in production. So if you find yourself in a scenario where you need to be using less memory, or you suspect there is a memory leak give Visual Studio 2013 Ultimate a try. Feel free to <a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/02\/SampleLeakFiles.zip\">download the sample project used in this blog post<\/a> and try it for yourself.\u00a0 It is recommended that you continue by reading <a href=\"http:\/\/blogs.msdn.com\/b\/visualstudioalm\/archive\/2013\/10\/16\/net-memory-analysis-enhancements-in-visual-studio-2013.aspx\">part 2 of this post covering additional features<\/a>.<\/p>\n<p>If you have any comments\/questions I\u2019d love to hear them in the comments below or in our <a href=\"http:\/\/social.msdn.microsoft.com\/Forums\/en-US\/vsdebug\/threads\">MSDN forum<\/a>.<\/p>\n<h3><a name=\"#sample\"><\/a>Using the example in this post<\/h3>\n<p>If you would like to try the sample I showed in this post do the following:<\/p>\n<ol>\n<li>Download the attached SampleLeakFiles.zip file and extract the contents<\/li>\n<li>In Visual Studio 2013 Create a new C# ASP.NET MVC project and name it \u201cSampleLeak\u201d (make sure to use the <a href=\"http:\/\/blogs.msdn.com\/b\/webdev\/archive\/2013\/06\/26\/announcing-release-of-asp-net-and-web-tools-for-visual-studio-2013-preview-and-the-refresh-update.aspx\">new Visual Studio 2013 One ASP.NET template<\/a>)<\/li>\n<li>Replace the contents of the generated &#8220;ControllersHomeController.cs&#8221; with the copy from the .zip<\/li>\n<li>Add the &#8220;User.cs&#8221; included in this .zip to the &#8220;Models&#8221; folder<\/li>\n<li>Add the included UserRepository.cs and MockDatabase.cs to the project<\/li>\n<\/ol>\n<p>Your SampleLeak MVC app will now match the app I used to create this blog post<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/02\/SampleLeakFiles.zip\">SampleLeakFiles.zip<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update: Note this post has been updated for Visual Studio 2013 RTM and is the first of a two-part series.\u00a0 In the screenshots and examples Just My Code and Collapse Small Objects are disabled as covered in part 2.\u00a0 It is recommended that you read this post before reading part 2. One of the issues [&hellip;]<\/p>\n","protected":false},"author":68,"featured_media":45953,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,225],"tags":[],"class_list":["post-2943","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-git"],"acf":[],"blog_post_summary":"<p>Update: Note this post has been updated for Visual Studio 2013 RTM and is the first of a two-part series.\u00a0 In the screenshots and examples Just My Code and Collapse Small Objects are disabled as covered in part 2.\u00a0 It is recommended that you read this post before reading part 2. One of the issues [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/2943","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/users\/68"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/comments?post=2943"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/2943\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media\/45953"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media?parent=2943"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/categories?post=2943"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/tags?post=2943"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}