.NET Memory Profiler 3.5.150 Released

May 25th, 2010

Today we released a maintenance version of .NET Memory Profiler. If you are profiling .NET 1.x applications, or if you are profiling ASP.NET applications on a system with .NET 4.0 installed, it is highly recommended that you download this release. The previous installer was missing a file which caused problems with the dispose tracker when profiling .NET 1.x applications. More importantly, the previous version didn’t detect the Web development server (WebDev.WebServer) included with .NET 4.0. This version detects both version 2.0 and 4.0 of WebDev.WebServer and allows you to select which one to use when profiling an ASP.NET application. For more information about this release, and other maintenance releases, please read the release notes. The latest version can be downloaded from the download page.

Memory Profiling SQL Server

May 25th, 2010

One profiling scenario that is currently not supported by .NET Memory Profiler is SQL Server profiling. If your SQL Server database contains any .NET stored procedures or any other .NET code it can be important to validate the memory usage of the .NET code, especially if any state is kept by the .NET code. As soon as any state information is kept in memory, there is a risk of memory leaks.

As the SQL Server is running as a Windows service, the Profile service command should be used, as described below:

  1. Start .NET Memory Profiler as an adminstrator (e.g. right click and select “Run as administrator”)
  2. Select Profile Service
  3. Find the correct SQL Server service
  4. Start profiling
  5. The SQL Server service will be restarted and you will see the message “Waiting for profiled process to start”.
  6. Make sure that the .NET runtime is loaded into the process, e.g. by executing a stored procedure. This should cause the message to disappear and the profiling to start.

Unfortunately, this will not work! You will soon receive an error message stating:

System.IO.FileNotFoundException: Could not load file or assembly ‘SciTech.NetMemProfiler.InstrumentationHelper2, Version=3.1.0.0, Culture=neutral, PublicKeyToken=2dc3dfad160eda83′ or one of its dependencies. The system cannot find the file specified. 

The problem is that the dispose tracker (which is usually enabled) requires a helper assembly. This assembly is installed in the GAC, but SQL Server will not load this assembly. The solution is to add the helper assembly to the database. But there’s one more gotcha. The helper assembly performs native functions calls, and thus requires unrestricted permissions, i.e. it must be added with PERMISSION_SET = UNSAFE. In order to do this, the database needs to be marked as “Trustworthy” (which is not recommended), or a database login with UNSAFE ASSEMBLY rights must be created for the helper assembly. The login can be created using the following SQL script:

USE master
GO
IF NOT EXISTS (SELECT name FROM master.sys.asymmetric_keys WHERE name = 'MemProfilerInstrumentationKey')
begin
  CREATE ASYMMETRIC KEY MemProfilerInstrumentationKey
    FROM EXECUTABLE FILE = 'C:\Program files\SciTech\NetMemProfiler3\Assemblies\SciTech.NetMemProfiler.InstrumentationHelper2.dll'
  CREATE LOGIN MemProfilerInstrumentationLogin
    FROM ASYMMETRIC KEY MemProfilerInstrumentationKey
  GRANT UNSAFE ASSEMBLY TO MemProfilerInstrumentationLogin
end 

After the login has been created, the assembly can be added with unrestricted permissions. It must be added to each database that includes .NET code that will be profiled, using the SQL script below.

USE [<Database name>]
CREATE ASSEMBLY [SciTech.NetMemProfiler.InstrumentationHelper2]
  FROM 'C:\Program files\SciTech\NetMemProfiler3\Assemblies\SciTech.NetMemProfiler.InstrumentationHelper2.dll'
  WITH PERMISSION_SET = UNSAFE;

 Now it should be possible to profile .NET code hosted by SQL Server. Just follow the steps from the beginning of this post.

Once you have finished profiling, the permissions granted to the profiler can be removed by dropping the assembly, login, and asymmetric key:

USE [<Database name>]
DROP ASSEMBLY [SciTech.NetMemProfiler.InstrumentationHelper2]
GO
USE master
DROP LOGIN MemProfilerInstrumentationLogin
DROP ASYMMETRIC KEY MemProfilerInstrumentationKey

Admittedly these requirements make it a bit cumbersome to profile SQL Server hosted .NET code. The next version of the profiler will include an option to “Profile SQL Server”, which will automatically prepare the database for profiling.

 

Thanks to Gerhard Obenaus at Blackbaud, Inc. for pointing out how to create a login for the helper assembly, instead of using the “Trustworthy” alternative.

.NET Memory Profiler 3.5.130 Released

January 13th, 2010

Yesterday we published a maintenance release of .NET Memory Profiler 3.5 (version 3.5.130). This release contains several important fixes, so it is recommended that you download an install this release if you have an older version installed. For instance, due to refactorings in the previous release, native stack walking failed to use symbols from the Microsoft symbol store, which caused the native allocation call stacks to be much less detailed. We have also improved the performance when working with very large snapshots, and the memory usage has been reduced somewhat. Still, to avoid out of memory problems, it is recommended that the 64-bit version of .NET Memory Profiler is used when profiling applications with high memory usage. The 64-bit version is automatically used when the standalone profiler is used on a 64-bit operating, but since Visual Studio is a 32-bit process, the integrated profiler will only run as 32-bit.

The latest release can be downloaded from the Download page, and more information about the release is available in the release notes.

.NET Memory Profiler 3.5 Released

October 15th, 2009

Finally! Last week we launched .NET MemoryProfiler 3.5. It has taken a while to finish this version, but I’m very pleased with the result. For more information about this version, and to download it, please visit the .NET Memory Profiler site.

.NET Memory Profiler 3.5 Beta Released

September 7th, 2009

It took much longer than planned, but now we have released .NET Memory Profiler 3.5 Beta. It contains significant improvement over the preview, such as a call stack reducer, significantly faster loading and saving of session files, the possibility to ignore analysis issues and support for .NET Framework 4.0. This beta is more or less feature complete and we expect to release the final version of .NET Memory Profiler 3.5 before the end of September. For more information about the beta and to download it, please visit the beta page at http://memprofiler.com/beta. If you have any comments about the new version, you can comment in this blog, or send an e-mail to memprofiler@scitech.se.

Resource Leak in TreeView

April 6th, 2009

I’m planning to restart this blog by writing a few posts about the new features in .NET Memory Profiler  3.5. I’ll start of by investigating a resource leak in the .NET Framework.

I discovered this leak almost a year ago as I investigated memory problems reported by a user (in our support forum). To illustrate the leak, I have created a very simple Windows Forms application, with a form that contains a single button. In the Click handler of the button,  a number of TreeViews are created and the Checkboxes are enabled. They are added to the form, just to make sure that they will be fully initialized and then immediately disposed.

private void button1_Click( object sender, EventArgs e )
{
   for( int i = 0; i < 100; i++ )
   {
      using( TreeView treeView = new TreeView() )
      {
         this.Controls.Add( treeView );
         treeView.CheckBoxes = true;
      }
   }
}

This should not cause any left over instances; neither managed memory instances nor unmanaged resource instances. But when testing this under the profiler, the following results can be seen (after collecting a snapshot before and after a button click).

There are 200 new HBITMAPs and HDCs, and 100 new HIMAGELISTs! Considering that we created 100 TreeViews, it seems very likely that the new resource instances are related to them. Let’s investigate one of the resource further, for example the HBITMAPs. The allocation call stacks of the bitmaps provide the following information:

Thanks to the improved native stacks in .NET Memory Profiler 3.5, you can easily see that the HBITMAP is created as part of an ImageList, when initializing the checkboxes in the native TreeView (TV_InitCheckBoxes). So setting the CheckBoxes property to true, caused the HBITMAP to be created, but why is it not released? At first I suspected that there was actually a resource leak in the native Win32 TreeView implementation, but when checking the documentation, I found this:

Once a tree-view control is created with this style, the style cannot be removed. Instead, you must destroy the control and create a new one in its place. Destroying the tree-view control does not destroy the check box state image list. You must destroy it explicitly. Get the handle to the state image list by sending the tree-view control a TVM_GETIMAGELIST message. Then destroy the image list with ImageList_Destroy.

Apparantly, it’s the responsibility of the user of the native TreeView (e.g. the .NET TreeView control) to release the image list. I find this a bit odd since this image list is created as a side-effect of the internal implementation of the check boxes. Anyway, it seems like the .NET TreeView control fails to release the image list. To fix this leak, the image-list must be explicility released. The ReleaseCheckBoxImageList method below shows an example on how this can be done.

static class TreeViewHelper
{
   ///
   /// Releases the checkbox image list in the
   /// specified TreeView.
   ///
   internal static void ReleaseCheckBoxImageList(TreeView treeView)
   {
      if( treeView.IsHandleCreated )
      {
         int style = GetWindowLong( treeView.Handle, GWL_STYLE );

         if( (style & TVS_CHECKBOXES) != 0 )
         {
            // Checkboxes were enabled in the
            // tree view. Let's destroy the
            // image list.
            IntPtr hStateImageList = SendMessage(
               treeView.Handle,
               TVM_GETIMAGELIST,
               (IntPtr)TVSIL_STATE,
               IntPtr.Zero );

            if( hStateImageList != IntPtr.Zero )
            {
               ImageList_Destroy( hStateImageList );
            }
         }
      }
   }

   #region Windows interop

   const int TV_FIRST = 0x1100;
   const int TVM_GETIMAGELIST = (TV_FIRST + 8);
   const int TVSIL_STATE = 2;
   const int TVS_CHECKBOXES = 0x0100;

   const int GWL_STYLE = (-16);

   [DllImport( "User32" )]
   static extern IntPtr SendMessage(
      IntPtr hWnd, int Msg,
      IntPtr wParam, IntPtr lParam);

   [DllImport( "User32" )]
   static extern int GetWindowLong(
      IntPtr hWnd, int nIndex);

   [DllImport( "comctl32" )]
   [return: MarshalAs( UnmanagedType.Bool )]
   static extern bool ImageList_Destroy(IntPtr himl);

   #endregion
}

This method should be called when the image list will no longer be needed, for instance when the window handle is destroyed. The FixedTreeView class below shows how this can be implemented:

///
/// A TreeView that properly releases
/// native Win32 resources.
///
class FixedTreeView : TreeView
{
   ///
   /// Overridden to make sure that the native
   /// checkbox image list is properly released.
   ///
   protected override void OnHandleDestroyed(EventArgs e)
   {
      TreeViewHelper.ReleaseCheckBoxImageList( this );

      base.OnHandleDestroyed( e );
   }
}

By using the FixedTreeView instead of the standard TreeView, the test program no longer has a resource leak (or memory leak).

As you can see, this fixed the resource leak of HBITMAPs, HIMAGELISTs, HDCs, and even the HeapAlloced memory.

An additional bonus is that this fix will also handle the case where the CheckBoxes property is toggled.  When the CheckBoxes property is set to false, the image list should also be released. Thanks to the fact that the native TreeView must be recreated whenever the checkbox style is updated, the handle will be destroyed when the CheckBoxes property is changed and the fix will executed (“Once a tree-view control is created with this style, the style cannot be removed. Instead, you must destroy the control and create a new one in its place”).

The code in the forum post mentioned in the beginning didn’t handle this correctly, since it used the CheckBoxes property to decide if the image list should be released. This property don’t reflect the whether checkboxes were included in the control being destroyed. Therefore the TVS_CHECKBOXES style is checked instead, as that will handle setting CheckBoxes to false as well.

A beta of .NET Memory Profiler 3.5 will soon be released, but in the meantime you can test the improved native call stacks by downloading the .NET Memory Profiler 3.5 preview.

.NET Memory Profiler 3.5 Preview Released

February 17th, 2009

We didn’t quite make it within two weeks as I wrote in my last post, but now .NET Memory Profiler 3.5 Preview has been released. For more information and to download the preview, visit the .NET Memory Profiler 3.5 Preview page. If you have any comments, questions, or bug reports, we would like to hear about them. Please send any feedback you have to memprofiler@scitech.se.

.NET Memory Profiler 3.1.321 Released (and v3.5 is coming soon)

January 26th, 2009

Today we released a minor maintenance release of .NET Memory Profiler 3.1 (v3.1.321). This release can be downloaded from the .NET Memory Profiler download page. For more information about changes and fixes in this release, check out the release notes.

A more interesting release is the upcoming release of .NET Memory Profiler 3.5. We have put a lot of work into this version and I hope that you will feel that it is a significant improvement over v3.1. Finishing version 3.5 has taken quite a bit longer than we orginally planned, mainly because we started to include features that were initially intended for v4.0. Anyway, it’s soon here. A preview should be available within two weeks. More information will follow, and I really intend to start writing more posts for this blog.

.NET Memory Profiler 3.1.312 Released

August 26th, 2008

Last week we released a maintenance version of .NET Memory Profiler 3.1. The most important update in this version is support for .NET Framework 3.5 SP1. Due to some low-level changes in the runtime, some parts of the profiler didn’t work correctly, in particular the “attach-to” feature and memory dump import.

The new version can be downloaded from http://memprofiler.com/download.aspx. For additional information about what’s new in this release, check the release notes.

.NET Memory Profiler 3.1.301 Released

June 3rd, 2008

Earlier today we released .NET Memory Profiler 3.1.301. This release contains a few fixes related to ASP.NET profiling and the resource tracker. We also recently released .NET Memory Profiler 3.1.297, which contains more significant improvements and fixes to more serious problems. For more information about the latest releases, see the release notes. To download version 3.1.301, go to the download page at http://memprofiler.com/download.aspx.