<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>If broken it is, fix it you should</title><link>http://blogs.msdn.com/b/tess/</link><description>Using the powers of the debugger to solve the problems of the world - and a bag of chips
&amp;nbsp;&amp;nbsp;&amp;nbsp;by Tess Ferrandez, ASP.NET Escalation Engineer (Microsoft)
</description><dc:language>sv-SE</dc:language><generator>Telligent Community 5.6.583.17018 (Build: 5.6.583.17018)</generator><item><title>Kinect SDK for Windows – Hover Button / Hover Control</title><link>http://blogs.msdn.com/b/tess/archive/2011/08/16/kinect-sdk-for-windows-hover-button-hover-control.aspx</link><pubDate>Tue, 16 Aug 2011 13:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10196185</guid><dc:creator>Tess1</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10196185</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2011/08/16/kinect-sdk-for-windows-hover-button-hover-control.aspx#comments</comments><description>&lt;p&gt;&lt;br /&gt;This is part of what will be a series of posts on Kinect SDK demos and howtos, &lt;a title="go here to see the whole list" href="http://blogs.msdn.com/b/tess/archive/2011/08/16/kinect-sdk-for-windows-demos.aspx"&gt;go here to see the whole list&lt;/a&gt;. &lt;br /&gt; &lt;br /&gt;In this post I will talk about how you can create a simple and versatile Hover Button / Hover Control for Kinect with a Metro look.&amp;nbsp; &lt;br /&gt;The control is largely based on the &lt;a href="http://blogs.microsoft.co.il/blogs/shair/archive/2011/06/23/kinect-create-buttons.aspx"&gt;Kinect Buttons&lt;/a&gt; from Shai Raiten, so all cred goes to him, this is just a customization of his work.&lt;/p&gt;
&lt;h3&gt;Hover button UI&lt;/h3&gt;
&lt;p&gt;The HoverButton control can have either an image or text or both and can be resized to fit your needs. It features a Click event that will occurr after a hovering for 2 seconds.&lt;/p&gt;
&lt;p&gt;Below are two examples of how you could use the HoverButton control&amp;hellip;&lt;/p&gt;
&lt;p&gt;In the &lt;strong&gt;first example&lt;/strong&gt; I have used 10 HoverButtons to create a metro style UI for &lt;br /&gt;getting into different demos and I have used both images and just buttons with text together so you can see the difference.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The center button is currently selected and the white overlay slowly covers the whole button&amp;hellip; when the button is fully covered a Click event is fired.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-55-89-metablogapi/5383.KinectHub_5F00_7FC268EA.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="KinectHub" border="0" alt="KinectHub" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-55-89-metablogapi/7140.KinectHub_5F00_thumb_5F00_789306A5.png" width="644" height="452" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the &lt;strong&gt;second example&lt;/strong&gt; I have used only images to show a completely different effect with the same hover button where the 3rd avatar is being selected.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-55-89-metablogapi/3326.Select_2D00_avatar_5F00_603FEC8A.png"&gt;&lt;img style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border-width: 0px;" title="Select-avatar" border="0" alt="Select-avatar" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-55-89-metablogapi/2656.Select_2D00_avatar_5F00_thumb_5F00_43E2849D.png" width="644" height="452" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Creating the HoverButton&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Create a new WPF user control library (KinectControls) and add a new UserControl called HoverButton&lt;/li&gt;
&lt;li&gt;Add Dependency Properties&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;The dependency properties will be used to bind xaml controls in the HoverButton so that we can customize the button from the using application&lt;/p&gt;
&lt;p&gt;Add a dependency property for BackgroundColor (the color of the button) like this&lt;/p&gt;
&lt;pre class="code"&gt;	public Brush BackgroundColor{
		get{ return (Brush)this.GetValue(BackgroundColorProperty);}
		set{ this.SetValue(BackgroundColorProperty, value);}
	} 
	public static readonly DependencyProperty BackgroundColorProperty = DependencyProperty.Register(
	   "BackgroundColor", typeof(Brush), typeof(HoverButton), new PropertyMetadata(Brushes.Red));&lt;/pre&gt;
&lt;p&gt;Do the same for the following properties&lt;/p&gt;
&lt;table style="width: 600px;" border="0" cellspacing="4" cellpadding="0"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;&lt;strong&gt;Property&lt;/strong&gt;&lt;/td&gt;
&lt;td valign="top" width="133"&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/td&gt;
&lt;td valign="top" width="133"&gt;&lt;strong&gt;Default value&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;HoverColor&lt;/td&gt;
&lt;td valign="top" width="133"&gt;Brush&lt;/td&gt;
&lt;td valign="top" width="133"&gt;Brushes.White&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;TextColor&lt;/td&gt;
&lt;td valign="top" width="133"&gt;Brush&lt;/td&gt;
&lt;td valign="top" width="133"&gt;Brushes.White&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;TextSize&lt;/td&gt;
&lt;td valign="top" width="133"&gt;int&lt;/td&gt;
&lt;td valign="top" width="133"&gt;36&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top" width="133"&gt;Image&lt;/td&gt;
&lt;td valign="top" width="133"&gt;string&lt;/td&gt;
&lt;td valign="top" width="133"&gt;&amp;ldquo;&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
&lt;p&gt;3.&amp;nbsp; Create the XAML for the HoverButton and bind to the relevant controls&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;    &amp;lt;grid background="{Binding BackgroundColor}"&amp;gt;
        &amp;lt;img stretch="Fill" source="{Binding Image}" /&amp;gt;
        &amp;lt;textblock verticalalignment="Center" horizontalalignment="Center" fontfamily="Segoe UI" foreground="{Binding TextColor}" &lt;br /&gt;                fontsize="{Binding TextSize}" text="{Binding Text}" /&amp;gt;
        &amp;lt;rectangle verticalalignment="Top" horizontalalignment="Left" height="0" rendertransformorigin="0,0" opacity="0.3" &lt;br /&gt;                width="{Binding Width}" fill="{Binding HoverColor}" name="Mask" /&amp;gt;
    &amp;lt;/grid&amp;gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;4. Set up the data binding in the HoverButton constructor to bind the properties&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;    this.DataContext = this;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now we are done with the properties, it is time to do the hover magic&amp;hellip; for this we will use the Mask rectangle and animate it to grow when the cursor enters the button, and reverse the animation when the cursor exits&lt;/p&gt;
&lt;p&gt;5. Add the following fields to the HoverButton class&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;        private Duration hoverDuration = new Duration(new TimeSpan(0, 0, 2));
        private Duration reverseDuration = new Duration(new TimeSpan(0, 0, 1));
        private DoubleAnimation maskAnimation;
        private bool isHovering = false;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;the hoverDuration is the time it will take to do the full hover&lt;/p&gt;
&lt;p&gt;6.&amp;nbsp; Create two methods to start hovering and stop hovering that initiate and reverse the animation&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;        private void StartHovering()
        {
            double maxFillHeight = this.ActualHeight;

            if (!isHovering)
            {
                isHovering = true;
                maskAnimation = new DoubleAnimation(Mask.ActualHeight, maxFillHeight, hoverDuration);
                maskAnimation.Completed += new EventHandler(maskAnimation_Completed);
                Mask.BeginAnimation(Canvas.HeightProperty, maskAnimation);
            }
        }

        private void StopHovering()
        {
            if (isHovering)
            {
                isHovering = false;
                maskAnimation.Completed -= maskAnimation_Completed;
                maskAnimation = new DoubleAnimation(Mask.ActualHeight, 0, reverseDuration);
                Mask.BeginAnimation(Canvas.HeightProperty, maskAnimation);
            }
        }&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;7. Create a Click event that will fire when we have hovered for the hoverDuration&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;        public delegate void ClickHandler(object sender, EventArgs e);
        public event ClickHandler Click;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;8.&amp;nbsp; Finally create a maskAnimation_Completed eventhandler we will fire the Click event&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;        void maskAnimation_Completed(object sender, EventArgs e)
        {
            isHovering = false;
            if (Click != null)
                Click(this, e);
            Mask.BeginAnimation(Canvas.HeightProperty, null);
        }&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now the animation logic is complete, we just have to trigger the StartHovering and StopHovering methods, and we will do this by manually checking when a cursor enters and exits the button area&amp;hellip; from user code we will have to call a function Check whenever the cursor moves&amp;hellip;&lt;/p&gt;
&lt;p&gt;9. Implement the Check and IsCursorInButton methods that check if the cursor (a framework element) is inside or outside the button&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;        public bool Check(FrameworkElement cursor)
        {
            if (IsCursorInButton(cursor))
            {
                this.StartHovering();
                return true;
            }
            else
            {
                this.StopHovering();
                return false;
            }
        }

        private bool IsCursorInButton(FrameworkElement cursor)
        {
            try
            {
                //Cursor midpoint location
                Point cursorTopLeft = cursor.PointToScreen(new Point());
                double cursorCenterX = cursorTopLeft.X + (cursor.ActualWidth / 2);
                double cursorCenterY = cursorTopLeft.Y + (cursor.ActualHeight / 2);

                //Button location
                Point buttonTopLeft = this.PointToScreen(new Point());
                double buttonLeft = buttonTopLeft.X;
                double buttonRight = buttonLeft + this.ActualWidth;
                double buttonTop = buttonTopLeft.Y;
                double buttonBottom = buttonTop + this.ActualHeight;

                if (cursorCenterX &amp;lt; buttonLeft || cursorCenterX &amp;gt; buttonRight)
                    return false;

                if (cursorCenterY &amp;lt; buttonTop || cursorCenterY &amp;gt; buttonBottom)
                    return false;

                return true;
            }
            catch
            {
                return false;
            }
        }&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;And with that we are done with the button&amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As a helper I have also created a HandCursor control that is extremely simple with the following XAML&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;    &amp;lt;Ellipse Height="40" Width="40" Name="hand"&amp;gt;
        &amp;lt;Ellipse.Fill&amp;gt;
            &amp;lt;ImageBrush ImageSource="/KinectControls;component/Images/hand.png" /&amp;gt;
        &amp;lt;/Ellipse.Fill&amp;gt;
    &amp;lt;/Ellipse&amp;gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;hellip; and just one function&amp;nbsp; (note: for this to work we need to include the Microsoft.Research.Kinect and Coding4Fun.Kinect.WPF dlls and add using statements for Microsoft.Research.Kinect.Nui and Coding4Fun.Kinect.WPF)&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;        public void SetPosition(Joint joint)
        {
            Joint scaledJoint = joint.ScaleTo(800, 600, 0.5f, 0.5f);
            Canvas.SetLeft(this, scaledJoint.Position.X);
            Canvas.SetTop(this, scaledJoint.Position.Y);
        }&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Using the HoverButton&lt;/h3&gt;
&lt;p&gt;1. Add a reference to the KinectControls library in the application&lt;/p&gt;
&lt;p&gt;2. Add the following XAML to the Window to add the HoverButton and HandCursor&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;    &amp;lt;Canvas Background="Black"&amp;gt;
        &amp;lt;ctrl:HoverButton Name="btn1" BackgroundColor="Blue" Text="Test" HoverColor="White" Height="100" Width="200" Click="HoverButton_Click" Canvas.Top="100" &lt;br /&gt;                 Canvas.Left="100"/&amp;gt;
        &amp;lt;ctrl:HandCursor Name="hand" Canvas.Top="0" Canvas.Left="0"/&amp;gt;
    &amp;lt;/Canvas&amp;gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;3. Add a kinect Runtime to the window class&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;        Runtime kinect = null;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;4. Initialize the kinect in window_loaded and uninitialize it when the window closes (this uses the RuntimeExtensions methods shown in the previous post&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            kinect = new Runtime();
            kinect.Initialize(RuntimeOptions.UseSkeletalTracking);
            kinect.SetSmoothTransform();
            kinect.SkeletonFrameReady += new EventHandler&lt;skeletonframereadyeventargs&gt;(kinect_SkeletonFrameReady); this.Cursor = Cursors.None; } private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if (kinect != null) kinect.Uninitialize(); kinect = null; }&lt;/skeletonframereadyeventargs&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;5. And the last thing we need to do before we can try it out is to move the cursor in the SkeletonFrameReady event, as well as checking the button&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code"&gt;        void kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            SkeletonData data = e.SkeletonFrame.GetFirstTrackedSkeleton();
            Joint handJoint = data.Joints[JointID.HandRight];

            hand.SetPosition(handJoint);
            btn1.Check(hand);
        }&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Voila, we are ready to rock!&lt;/p&gt;
&lt;p&gt;Have fun, &lt;br /&gt;Tess&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10196185" width="1" height="1"&gt;</description><enclosure url="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-19-61-85/KinectControls.zip" length="342313" type="application/zip" /><category domain="http://blogs.msdn.com/b/tess/archive/tags/Kinect+SDK/">Kinect SDK</category></item><item><title>Kinect SDK for Windows–Extensions Methods</title><link>http://blogs.msdn.com/b/tess/archive/2011/08/16/kinect-sdk-for-windows-extensions-methods.aspx</link><pubDate>Tue, 16 Aug 2011 13:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10196184</guid><dc:creator>Tess1</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10196184</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2011/08/16/kinect-sdk-for-windows-extensions-methods.aspx#comments</comments><description>&lt;p&gt;&lt;/p&gt;
&lt;p&gt;This is part of what will be a series of posts on Kinect SDK demos and howtos, &lt;a title="go here to see the whole list" href="http://blogs.msdn.com/b/tess/archive/2011/08/16/kinect-sdk-for-windows-demos.aspx"&gt;go here to see the whole list&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Every time I create a new Kinect SDK demo I find myself doing the same setup so I created a few extensions methods that I use in my projects to make life easier. &lt;br /&gt;I figured I would share them here since I will be using them in my blog posts about Kinect in the future.&lt;/p&gt;
&lt;p&gt;The extension methods are SetSmoothTransform, which sets the smoothing parameters on the skeleton to stabilize the skeleton movement a bit, and the second method (GetFirstTrackedSkeleton) simply grabs the first skeleton that is tracked, so that we can use it in the SkeletonFrameReady event if we only need data about one skeleton.&lt;/p&gt;
&lt;pre class="code"&gt;   public static class RuntimeExtensions{
        public static void SetSmoothTransform(this Runtime runtime)
        {
            runtime.SkeletonEngine.TransformSmooth = true;

            var parameters = new TransformSmoothParameters
            {
                Smoothing = 0.75f,
                Correction = 0.0f,
                Prediction = 0.0f,
                JitterRadius = 0.05f,
                MaxDeviationRadius = 0.04f
            };

            runtime.SkeletonEngine.SmoothParameters = parameters;
        }

        public static SkeletonData GetFirstTrackedSkeleton(this SkeletonFrame skeletonSet){
            SkeletonData data = (from s in skeletonSet.Skeletons
                                 where s.TrackingState == SkeletonTrackingState.Tracked
                                 select s).FirstOrDefault();
            return data;
        }
    }&lt;/pre&gt;
&lt;p&gt;I would also recommend another extension method from &lt;a href="http://channel9.msdn.com/coding4fun/kinect/Display-Kinect-color-image-containing-only-players-aka-background-removal"&gt;Greg Duncan&lt;/a&gt; called CreateLivePlayerRenderer which extracts just the player from the video, based on depth data&amp;hellip; I will use this later in the series.&lt;/p&gt;
&lt;p&gt;Enjoy, &lt;br /&gt;Tess&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10196184" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/Kinect+SDK/">Kinect SDK</category></item><item><title>Kinect SDK for Windows – demos</title><link>http://blogs.msdn.com/b/tess/archive/2011/08/16/kinect-sdk-for-windows-demos.aspx</link><pubDate>Tue, 16 Aug 2011 12:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10196181</guid><dc:creator>Tess1</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10196181</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2011/08/16/kinect-sdk-for-windows-demos.aspx#comments</comments><description>&lt;p&gt;&lt;br /&gt;Lately I have been working quite a bit with the Kinect SDK for Windows, which you can install and use on your computer from &lt;a href="http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/"&gt;our research department&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Geting started&lt;/h3&gt;
&lt;p&gt;The only thing you need to get started is a computer running Windows, a Kinect device (must be the one with a power chord, but you can buy the power chord separately very cheep at most stores where they sell Kinect), and the Kinect SDK.&lt;/p&gt;
&lt;p&gt;Once you have everything installed I suggest you go to Channel9 and watch the &lt;a href="http://channel9.msdn.com/Series/KinectSDKQuickstarts"&gt;QuickStarts&lt;/a&gt;&amp;nbsp; to familiarize yourself with the basics and finally move over to the &lt;a href="http://channel9.msdn.com/coding4fun/Kinect/"&gt;Channel9 Kinect blog&lt;/a&gt; to get inspiration and look at all the cool projects people are making.&lt;/p&gt;
&lt;h3&gt;This series&lt;/h3&gt;
&lt;p&gt;In this series I will post a number of different controls, extensions and demo apps that I have created.&amp;nbsp; Some are based on inspiration from the Kinect blog and other sources. The list of demos/howtos here will hopefully grow over time&lt;/p&gt;
&lt;p&gt;1. &lt;a title="RuntimeExtension methods for common stuff" href="http://blogs.msdn.com/b/tess/archive/2011/08/16/kinect-sdk-for-windows-extensions-methods.aspx"&gt;RuntimeExtension methods for common stuff&lt;/a&gt; &lt;br /&gt;2. &lt;a title="Creating a Kinect Hover Button / Hover Control" href="http://blogs.msdn.com/b/tess/archive/2011/08/16/kinect-sdk-for-windows-hover-button-hover-control.aspx"&gt;Creating a Kinect Hover Button / Hover Control&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enjoy, &lt;br /&gt;Tess&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10196181" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/Kinect+SDK/">Kinect SDK</category></item><item><title>Entering geek territory or exiting geek territory? That’s the question…</title><link>http://blogs.msdn.com/b/tess/archive/2011/05/06/entering-geek-territory-or-exiting-geek-territory-that-s-the-question.aspx</link><pubDate>Fri, 06 May 2011 14:12:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10161796</guid><dc:creator>Tess1</dc:creator><slash:comments>20</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10161796</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2011/05/06/entering-geek-territory-or-exiting-geek-territory-that-s-the-question.aspx#comments</comments><description>&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font size="3" face="Tahoma"&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-55-89-metablogapi/4571.migbipng_5F00_32FCAFA3.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; margin: 0px 10px 10px; padding-left: 0px; padding-right: 0px; display: inline; float: left; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="migbipng" border="0" alt="migbipng" align="left" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-55-89-metablogapi/3414.migbipng_5F00_thumb_5F00_2B714036.png" width="115" height="149" /&gt;&lt;/a&gt;After 12 years in support I decided to lift my head above the WinDbg window and take a look at what the rest of the world has to offer… &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="3" face="Tahoma"&gt;In fact, I decided not only to have a look but take a long long jump to the other end of the software spectrum, miles away from “My ASP.NET app hangs” to the world of “This new stuff that will be released in 2014 is soooo cool I’m gonna die”, and believe me, it’s a scary leap&lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Ler" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-55-89-metablogapi/4186.wlEmoticon_2D00_smile_5F00_5819FA0F.png" /&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="3" face="Tahoma"&gt;For the next two months I’ll be working in a team at Microsoft called DPE (Developer Evangelism), looking at what’s next in Web, Phone, Kinect, HTML5, you name it, still doing what I love most though, which is making people excited about technology and talking about what I learn along the way.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="3" face="Tahoma"&gt;Just to explain how far away from my “day job” this is, I’ll share what my first assigment was…&amp;#160; my first task in this new role was to design a character for this site we are starting up &lt;a href="http://www.migbi.se"&gt;http://www.migbi.se&lt;/a&gt; with all swedish content for people getting started with app and web development. &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="3" face="Tahoma"&gt;Several people have said, ooooh so you are going to join the geeks now&lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Ler" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-55-89-metablogapi/4186.wlEmoticon_2D00_smile_5F00_5819FA0F.png" /&gt;&amp;#160; Am I?&amp;#160; I thought it couldn't get more geeky than spending your days in WinDbg, I guess I’ll just have to wait and see…&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="3" face="Tahoma"&gt;&lt;strong&gt;What does this mean for the blog?&lt;/strong&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="3" face="Tahoma"&gt;To be honest I don’t know… It’s been so busy lately that I haven’t had time to take care of the blog as much as I should have, but I think it means that you will be seeing a lot more varied content here.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="3" face="Tahoma"&gt;I am too inlove with WinDbg and debugging to stop it alltogether, and the plan is for this stint to be temporary, but it might mean that I’ll lean more towards showing stuff that I work on in my current role for a while… hope you don’t mind&lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="Ler" src="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-55-89-metablogapi/4186.wlEmoticon_2D00_smile_5F00_5819FA0F.png" /&gt;&lt;/font&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;font size="3" face="Tahoma"&gt;Have a great weekend all,&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font size="3" face="Tahoma"&gt;Tess&lt;/font&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10161796" width="1" height="1"&gt;</description></item><item><title>Reader email: Need help troubleshooting perf/memory issues</title><link>http://blogs.msdn.com/b/tess/archive/2010/12/06/reader-email-need-help-troubleshooting-perf-memory-issues.aspx</link><pubDate>Mon, 06 Dec 2010 09:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10100695</guid><dc:creator>Tess1</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10100695</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/12/06/reader-email-need-help-troubleshooting-perf-memory-issues.aspx#comments</comments><description>&lt;p&gt;I get several emails every day (through the blog) with urgent requests to help troubleshoot memory issues or memory related performance issues.&amp;nbsp; Some just say &amp;ldquo;we have a memory issue, how do I troubleshoot it?&amp;rdquo; and others are far far more detailed with links to dumps and everything:) &lt;/p&gt;
&lt;p&gt;I love getting emails, but since I have a day job too (troubleshooting such issues:)) I unfortunately have to ignore most such requests through the blog:( to have time to help the customers that contact me through the normal support channels, and therefore I would recommend that if you do have a pressing issue, that you create a support case on &lt;a href="http://support.microsoft.com/" title="http://support.microsoft.com/"&gt;http://support.microsoft.com/&lt;/a&gt; to make sure that you get a dedicated support engineer and that your issue gets the attention it deserves.&lt;/p&gt;
&lt;p&gt;Having said all that, I wanted to point out one email I got today, both because I could see that the person writing it had put some effort into try troubleshooting the issue before contacting me, and because I think and hope that my answer might be able to give some starting points to other people in his situation. &lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;  &lt;p&gt;Hi Tess, &lt;/p&gt;
&lt;p&gt;We have a week to go for production and are stuck in one performance issue. 
Please guide me in resolving this. &lt;/p&gt;
&lt;p&gt;We are running an ASP .Net (2.0) App on Windows Server 2003 (SP2), dual-processor, 4GB RAM. 
During stess-testing our app with 60 users, we see a drop in throughput from 17th minute to 22nd minute. &lt;br /&gt;It rises and drops again around 40th minute. &lt;/p&gt;
&lt;p&gt;I took 4 memory dumps for 8 mins, ran the perfmon counters. 
Here are the details: &lt;/p&gt;
&lt;p style="FONT-FAMILY: "&gt;&lt;span style="font-family: courier new,courier;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;              Dump1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dump2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dump3&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Dump4 &lt;br /&gt;Size&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;             1.16G&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1.12G&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1.04G&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1.13G &lt;br /&gt;GC&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;             802MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 750MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 648MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 738MB &lt;br /&gt;Loader&amp;nbsp;&amp;nbsp;             18MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  18MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  18MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  18MB 
Image                236MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 236MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 236MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 236MB &lt;br /&gt;MEM_RESV&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;         220MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 236MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 347MB&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 255MB &lt;br /&gt;MEM_COMM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;         1.19GB&amp;nbsp;&amp;nbsp;&amp;nbsp; 1.06GB&amp;nbsp;&amp;nbsp;&amp;nbsp; 1021MB&amp;nbsp;&amp;nbsp;&amp;nbsp; 1.08GB &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Perfmon Counters (8 mins) &lt;br /&gt;LOH:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;                    307MB, &lt;br /&gt;#Bytes in all heaps:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 798MB, &lt;br /&gt;%Time in GC:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;       49%(avg), &lt;br /&gt;#Induced GC:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;        14 (avg). &lt;/p&gt;
&lt;p&gt;So I can deduce the following: &lt;/p&gt; &lt;p&gt;1. We are stuck in GC for the 8 minutes. 
&lt;br /&gt;2. Assembly leak is not the problem. 
&lt;br /&gt;3. Am not sure if Finalizer thread is being blocked. &lt;/p&gt;  &lt;p&gt;The kb reads as below: &lt;/p&gt;  &lt;p&gt;&lt;em&gt;0:017&amp;gt; kb &lt;br /&gt;ChildEBP RetAddr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Args to Child &lt;br /&gt;0e1afc74 7c827d0b&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 77e61d1e 00000334 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ntdll!KiFastSystemCallRet &lt;br /&gt;0e1afc78 77e61d1e&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 00000334 00000000 0e1afcbc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ntdll!NtWaitForSingleObject+0xc &lt;br /&gt;0e1afce8 79e8c5f9&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 00000334 000007d0 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; kernel32!WaitForSingleObjectEx+0xac &lt;br /&gt;0e1afd2c 79e8c52f&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 00000334 000007d0 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!PEImage::LoadImage+0x1af &lt;br /&gt;0e1afd7c 79e8c54e&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 000007d0 00000000 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!CLREvent::WaitEx+0x117 &lt;br /&gt;0e1afd90 79fc2397&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 000007d0 00000000 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!CLREvent::Wait+0x17 &lt;br /&gt;0e1afdac 79fc24b4&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 000f2b28 0e1afeb0 000f3328&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!SVR::WaitForFinalizerEvent+0x4a &lt;br /&gt;0e1afdc0 79e9845f&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0e1afeb0 00000000 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!SVR::GCHeap::FinalizerThreadWorker+0x49 &lt;br /&gt;0e1afdd4 79e983fb&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0e1afeb0 0e1afe5c 79f7759b&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!Thread::DoADCallBack+0x32a &lt;br /&gt;0e1afe68 79e98321&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0e1afeb0 9b91703f 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!Thread::ShouldChangeAbortToUnload+0xe3 &lt;br /&gt;0e1afea4 79eef6cc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0e1afeb0 00000000 0010f770&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!Thread::ShouldChangeAbortToUnload+0x30a &lt;br /&gt;0e1afecc 79eef6dd&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 79fc2469 00000008 0e1aff14&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!ManagedThreadBase_NoADTransition+0x32 &lt;br /&gt;0e1afedc 79ef12ab&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 79fc2469 9b91718f 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!ManagedThreadBase::FinalizerBase+0xd &lt;br /&gt;0e1aff14 79f92015&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 00000000 00000000 89244470&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!SVR::GCHeap::FinalizerThreadStart+0xbb &lt;br /&gt;0e1affb8 77e64829&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 000f3328 00000000 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscorwks!Thread::intermediateThreadProc+0x49 &lt;br /&gt;0e1affec 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 79f91fcf 000f3328 00000000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; kernel32!BaseThreadStart+0x34 &lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;4. !finalizequeue results &lt;br /&gt;Heap 0 &lt;br /&gt;generation 0 has 158 finalizable objects (1d1d42c8-&amp;gt;1d1d4540) &lt;br /&gt;generation 1 has 269 finalizable objects (1d1d3e94-&amp;gt;1d1d42c8) &lt;br /&gt;generation 2 has 1961 finalizable objects (1d1d1ff0-&amp;gt;1d1d3e94) &lt;br /&gt;Ready for finalization 0 objects (1d1d4540-&amp;gt;1d1d4540) &lt;br /&gt;------------------------------ &lt;br /&gt;Heap 1 &lt;br /&gt;generation 0 has 830 finalizable objects (1d23d7c0-&amp;gt;1d23e4b8) &lt;br /&gt;generation 1 has 284 finalizable objects (1d23d350-&amp;gt;1d23d7c0) &lt;br /&gt;generation 2 has 1238 finalizable objects (1d23bff8-&amp;gt;1d23d350) &lt;br /&gt;Ready for finalization 0 objects (1d23e4b8-&amp;gt;1d23e4b8) &lt;br /&gt;&lt;/em&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;How do I proceed from here to isolate the issue? &lt;/p&gt;&lt;p&gt;Thanks, &lt;/p&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Looking at the above, these were the comments and suggestions for further troubleshooting that I sent him.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t agree that you are stuck in a GC for 8 minutes, you can check with # Gen 0/Gen 1/Gen 2 collections and will probably see them increasing.&amp;nbsp; The reason I say that you are not stuck is because the % time in GC counter will only update on completion of a GC so if you were stuck it would not update.&lt;/p&gt;
&lt;p&gt;I do think however that your % Time in GC looks really high and I think there might be two reasons for this&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You are reaching the point where mem usage gets really close the OOM range (&lt;a href="http://blogs.msdn.com/b/tess/archive/2005/11/25/496898.aspx"&gt;typically around 1 GB private bytes&lt;/a&gt;) so the process is probably working really hard to get rid of everything it can.&amp;nbsp; # Induced GC here is not 0 which means that someone called GC.Collect, and unless it is your app that calls GC.Collect it is probably ASP.NET doing this to clean up at an OOM. &lt;br /&gt;&lt;br /&gt;Each induced GC will be a full GC which can get pretty costly performance wise. &lt;br /&gt;&lt;b&gt;&lt;br /&gt;Recommendation: &lt;/b&gt;Look at general memory usage, i.e. look at !dumpheap &amp;ndash;stat etc. and see what is using all this .net memory and try to find places where you can reduce the memory usage, or alternatively, if you need to use all this memory, then you would need to move to a 64-bit environment.&amp;nbsp; (You might want to look at some of &lt;a href="http://blogs.msdn.com/b/tess/archive/tags/memory+issues/"&gt;my posts on troubleshooting .net memory issues&lt;/a&gt; to narrow this down).&amp;nbsp; A potential also, if you are running multiple sites here, would be to separate them into different app pools. &lt;/li&gt;
&lt;li&gt;Your LOH looks pretty large (307 MB), if you are continuously allocating on the LOH you will also trigger a lot of full GC&amp;rsquo;s. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Recommendation:&lt;/b&gt;&amp;nbsp; have a look at !dumpheap &amp;ndash;min 85000 and see if there are any unexpected large objects, or if there are any that you can reduce in size or in number of objects. (See &lt;a href="http://blogs.msdn.com/b/tess/archive/2006/06/22/asp-net-case-study-high-cpu-in-gc-large-objects-and-high-allocation-rates.aspx" title="http://blogs.msdn.com/b/tess/archive/2006/06/22/asp-net-case-study-high-cpu-in-gc-large-objects-and-high-allocation-rates.aspx"&gt;http://blogs.msdn.com/b/tess/archive/2006/06/22/asp-net-case-study-high-cpu-in-gc-large-objects-and-high-allocation-rates.aspx&lt;/a&gt;&amp;nbsp; for more details)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Regarding the finalizer, the finalizer is not stuck, it is sitting in mscorwks!SVR::WaitForFinalizerEvent+0x4a which means that it is just idling, waiting for the GC to tell it to finalize.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;I have a post with common asp.net threads and how they look in the &amp;ldquo;normal&amp;rdquo; idling state here &lt;a href="http://blogs.msdn.com/b/tess/archive/2007/04/02/things-to-ignore-when-debugging-an-asp-net-hang-update-for-net-2-0.aspx"&gt;http://blogs.msdn.com/b/tess/archive/2007/04/02/things-to-ignore-when-debugging-an-asp-net-hang-update-for-net-2-0.aspx&lt;/a&gt; that might be useful for further debugging.&lt;/p&gt;
&lt;p&gt;You can further see that finalization is not a problem because !finalizequeue reports no objects to ready for finalization in either heap &amp;ldquo;Ready for finalization 0 objects&amp;rdquo;.&amp;nbsp; Here you can find &lt;a href="http://blogs.msdn.com/b/tess/archive/2006/03/27/561715.aspx?PageIndex=2"&gt;an example of what it would look like if the finalizer was actually stuck&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Hope that helps, &lt;br /&gt;Tess&lt;/p&gt;
&lt;/blockquote&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10100695" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/Memory+issues/">Memory issues</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Performance+issues+and+hangs/">Performance issues and hangs</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category></item><item><title>Fix for RestartWWWService=false in Visual Studio 2010</title><link>http://blogs.msdn.com/b/tess/archive/2010/11/09/fix-for-restartwwwservice-false-in-visual-studio-2010.aspx</link><pubDate>Tue, 09 Nov 2010 08:34:30 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10088035</guid><dc:creator>Tess1</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10088035</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/11/09/fix-for-restartwwwservice-false-in-visual-studio-2010.aspx#comments</comments><description>&lt;p&gt;We recently published a fix for the following problem:&lt;/p&gt;  &lt;p&gt;You create a deployment project for a web application in Visual Studio 2010, set the deployment property RestartWWWService=false and deploy to a Windows 2003 server.   &lt;br /&gt;&lt;a title="http://msdn.microsoft.com/en-us/library/22f9106b.aspx" href="http://msdn.microsoft.com/en-us/library/22f9106b.aspx"&gt;http://msdn.microsoft.com/en-us/library/22f9106b.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;In this situation the w3wp.exe process will still be recycled even though the RestartWWWService is set to false.&lt;/p&gt;  &lt;p&gt;The fix is available at &lt;a title="http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=32285" href="http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=32285"&gt;http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=32285&lt;/a&gt; and should only be installed on development machines if you experience this problem.&amp;#160; &lt;/p&gt;  &lt;p&gt;Have a good one,&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10088035" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category></item><item><title>Debug Diag 1.2 (Beta)</title><link>http://blogs.msdn.com/b/tess/archive/2010/09/30/debug-diag-1-2-beta.aspx</link><pubDate>Thu, 30 Sep 2010 12:36:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10069795</guid><dc:creator>Tess1</dc:creator><slash:comments>22</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10069795</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/09/30/debug-diag-1-2-beta.aspx#comments</comments><description>&lt;p&gt;Are you looking for some good stuff to put in your family’s Christmas stockings this year? Maybe a new phone, a controller for your gaming console, why not a brand new debugging tool:)&lt;/p&gt;  &lt;p&gt;Jokes aside, I get peppered with questions about Debug Diag and if there is a new version coming that will support Windows 7 / Windows 2008 and luckily some of my EE colleagues have been and are still working hard at making this happen. &lt;/p&gt;  &lt;p&gt;While it is not available for public download yet at the MS download site, Beta 1 of Debug Diag has been released and is ready for use.&amp;#160; The main new stuff in Beta 1 is that it now supports the aforementioned Windows 7 and 2008, and if you need it right now, you can send an email to dbgdiag (at) microsoft.com, or if you have a case open, you can ask the support engineer you are working with to send it to you.&lt;/p&gt;  &lt;p&gt;It has a 32-bit and a 64-bit version (for 1.2, install the 64bit version on 64bit OSes and 32bit version on 32bit OSes, independently of the bitness of the target process).&lt;/p&gt;  &lt;p&gt;I will write more when Beta2 is out but Beta2 looks very promising with some new features that will help our apps easier to debug.&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10069795" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/General+debugging+tidbits/">General debugging tidbits</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category></item><item><title>Do you know ISA/Forefront and want to work in the cube next to mine (Sweden)?</title><link>http://blogs.msdn.com/b/tess/archive/2010/09/29/do-you-know-isa-forefront-and-want-to-work-in-the-cube-next-to-mine-sweden.aspx</link><pubDate>Wed, 29 Sep 2010 09:43:19 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10069169</guid><dc:creator>Tess1</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10069169</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/09/29/do-you-know-isa-forefront-and-want-to-work-in-the-cube-next-to-mine-sweden.aspx#comments</comments><description>&lt;p&gt;If you live in Stockholm, know a lot about ISA/Foreftont/TMG/UAG and you’re just aching to spend the days debugging and troubleshooting interesting problems, we have a full-time Microsoft position open right now.&lt;/p&gt;  &lt;p&gt;Not only that, but you would get to have your morning “fika” with some fine people like &lt;a href="http://blogs.msdn.com/b/grahamk/"&gt;Graham&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/b/spike/"&gt;Spike&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/b/johan/"&gt;Johan&lt;/a&gt; :)    &lt;br /&gt;(ok, better stop now before this turns into an infomercial)&lt;/p&gt;  &lt;p&gt;Anyways, if it tickles your fancy, you can read more about it on the &lt;a href="http://blogs.technet.com/b/isablog/archive/2010/09/15/forefront-tmg-uag-help-wanted-at-microsoft-in-stockholm.aspx"&gt;ISA blog&lt;/a&gt; and send your CV to my manager Roffe - rolfhe(at)microsoft.com.&lt;/p&gt;  &lt;p&gt;/Tess&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10069169" width="1" height="1"&gt;</description></item><item><title>Capturing memory dumps for 32-bit processes on an x64 machine</title><link>http://blogs.msdn.com/b/tess/archive/2010/09/29/capturing-memory-dumps-for-32-bit-processes-on-an-x64-machine.aspx</link><pubDate>Wed, 29 Sep 2010 09:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10069161</guid><dc:creator>Tess1</dc:creator><slash:comments>11</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10069161</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/09/29/capturing-memory-dumps-for-32-bit-processes-on-an-x64-machine.aspx#comments</comments><description>&lt;p&gt;This is an issue that I often get questions around and we often have cases where we have to re-capture memory dumps because the memory dumps were captured the &amp;ldquo;wrong&amp;rdquo; way.&lt;/p&gt;
&lt;p&gt;The short story is: If you are executing a 32-bit process on a 64-bit machine, (which is the default case for IIS on x64 machines for example) you need to capture the dump with a tool that allows you to create 32-bit dumps.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do you know if your process is 32-bit?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you are on a 64-bit machine, you can check task manager to see what architecture your process is using.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-55-89-metablogapi/1157.image_5F00_2.png"&gt;&lt;img height="156" width="244" src="http://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-55-89-metablogapi/4762.image_5F00_thumb.png" alt="image" border="0" title="image" style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Processes with *32 are 32-bit and the rest are 64-bit so in the example above we can see that for example w3wp.exe is&amp;nbsp;executing 32-bit code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why is it important to capture them with the right tools?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you capture a dump with a tool that captures 64-bit dumps you will still get a memory dump, but you will get a memory dump of the syswow64 which means that a lot of extensions like sos and psscor2 won&amp;rsquo;t be able to read the data.&amp;nbsp; Some things may still work but it is very limited and you might get errors or erroneous call stacks etc.&lt;/p&gt;
&lt;p&gt;Typical stuff that happens when you try to read a 64-bit memory dump of a 32-bit process is:&lt;/p&gt;
&lt;p&gt;1. You may see warnings like&lt;/p&gt;
&lt;pre class="debug"&gt;  WARNING: wkscli overlaps srvcli
  ..............WARNING: wship6 overlaps dnsapi
  .WARNING: IPHLPAPI overlaps dsrole
  ...WARNING: FWPUCLNT overlaps rasadhlp
  WARNING: FWPUCLNT overlaps dnsapi
  .....WARNING: compstat overlaps iisres&lt;/pre&gt;
&lt;p&gt;2.&amp;nbsp; The stacks show wow64cpu methods &lt;/p&gt;
&lt;pre class="debug"&gt;0:000&amp;gt; kp 
   Child-SP&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RetAddr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Call Site 
   00000000`000ce728 00000000`73a22bcd wow64cpu!CpupSyscallStub+0x9 
   00000000`000ce730 00000000`73a9d07e wow64cpu!Thunk0ArgReloadState+0x1a 
   00000000`000ce7f0 00000000`73a9c549 wow64!RunCpuSimulation+0xa 
   00000000`000ce840 00000000`76d684c8 wow64!Wow64LdrpInitialize+0x429 
   00000000`000ced90 00000000`76d67623 ntdll!LdrpInitializeProcess+0x17e2 
   00000000`000cf290 00000000`76d5308e ntdll! ?? ::FNODOBFM::`string'+0x2bea0 
   00000000`000cf300 00000000`00000000 ntdll!LdrInitializeThunk+0xe&lt;/pre&gt;
&lt;p&gt;3. You see that all addresses are 64 bit addresses, (i.e. 00000000`76d5308e rather than 76d5308e), even though it is a 32-bit process.&lt;/p&gt;
&lt;p&gt;4. You get errors like the below when trying to run sos commands.&amp;nbsp;&amp;nbsp; &lt;br /&gt;(Note: You can get these errors if you don&amp;rsquo;t have symbols properly set up as well, so this is not the only reason for getting these errors)&lt;/p&gt;
&lt;pre class="debug"&gt;0:000&amp;gt; !eeheap -gc 
Failed to load data access DLL, 0x80004005 
Verify that 1) you have a recent build of the debugger (6.2.14 or newer)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2) the file mscordacwks.dll that matches your version of clr.dll is&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; in the version directory&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3) or, if you are debugging a dump file, verify that the file&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; mscordacwks_&amp;lt;arch&amp;gt;_&amp;lt;arch&amp;gt;_&amp;lt;version&amp;gt;.dll is on your symbol path.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4) you are debugging on the same architecture as the dump file.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; For example, an IA64 dump file must be debugged on an IA64&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; machine. &lt;/pre&gt;
&lt;p&gt;You can also run the debugger command .cordll to control the debugger's &lt;br /&gt;load of mscordacwks.dll.&amp;nbsp; .cordll -ve -u -l will do a verbose reload. &lt;br /&gt;If that succeeds, the SOS command should work on retry. &lt;/p&gt;
&lt;p&gt;If you are debugging a minidump, you need to make sure that your executable &lt;br /&gt;path is pointing to clr.dll as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What tools should you use?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The best way to capture a process dump in this scenario is to use 32-bit versions of tools like Debug Diag, or adplus+cdb (32 bit debugging tools for windows).&amp;nbsp; You can install the 32-bit versions of these tools on a 64-bit system.&amp;nbsp;&amp;nbsp; In the next version of Debug Diag you will be able to capture 32-bit dumps with the 64-bit version of Debug Diag.&lt;/p&gt;
&lt;p&gt;I have mentioned before that you can capture memory dumps with task manager on Vista+, but if you do this on a 64-bit machine you will get a 64-bit dump.&amp;nbsp; You can however use the 32-bit task manager, located in C:\Windows\SysWOW64\taskmgr.exe to get 32-bit dumps.&amp;nbsp; If you want to verify that you are running the 32-bit version of task manager, you can check that taskmgr.exe is listed with *32 in task manager itself.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Edit:&lt;/em&gt;&lt;/strong&gt;&amp;nbsp; Sorry Mark and David, I of course didn't mean to leave out the nice and very lightweight&amp;nbsp;&lt;a href="http://technet.microsoft.com/en-us/sysinternals/dd996900.aspx"&gt;procdump tool&lt;/a&gt; from SysInternals&amp;nbsp;which will capture 32-bit dumps of 32-bit processes even on 64-bit Windows.&amp;nbsp; Thanks for reminding me:)&lt;br /&gt;For some reason I thought that I had written about this tool in an earlier post but a quick search reminded me that this is still in my blog-todo bin.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;For all other dump capturing tools, I would suggest that you read the documentation to see if there is a 32-bit version (like for procmon where you can pass in the /run32 parameter) or if they will capture 32-bit dumps of 32-bit processes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Is it important to read the dump with the right &amp;ldquo;bit&amp;rdquo; debugger?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Yes, to read 32-bit dumps you should use 32-bit windbg (either on a 32-bit or 64-bit OS), and for 64-bit dumps, the machine that you debug the dumps on, needs to be a 64-bit machine, running 64-bit windbg.&lt;/p&gt;
&lt;p&gt;Remember that you should also use the 64-bit versions of sos, psscor2, sosex and any other extensions that you might use, if you are debugging a 64-bit dump.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Have a good one, &lt;br /&gt;/Tess&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10069161" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/General+debugging+tidbits/">General debugging tidbits</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category></item><item><title>Help! !clrstack is not showing any method names</title><link>http://blogs.msdn.com/b/tess/archive/2010/08/25/help-clrstack-is-not-showing-any-method-names.aspx</link><pubDate>Wed, 25 Aug 2010 11:50:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10054054</guid><dc:creator>Tess1</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10054054</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/08/25/help-clrstack-is-not-showing-any-method-names.aspx#comments</comments><description>&lt;p&gt;From time to time I get questions about missing method names in the sos !clrstack output, like this:&lt;/p&gt;
&lt;pre class="debug"&gt;0:019&amp;gt; !clrstack 
OS Thread Id: 0x5d0 (19) 
ESP      EIP 
0f31f340 7c80bef7 [HelperMethodFrame_1OBJ: 0f31f340] 
0f31f398 1449167a 
0f31f3c4 144915e6 
0f31f3f4 10d81b48 
0f31f4b4 793e25cf 
0f31f4bc 79366b3d 
0f31f4d4 793e2734 
0f31f4e8 793e26ac 
0f31f678 79e7c0e3 [GCFrame: 0f31f678]&lt;/pre&gt;
&lt;p&gt;Jonathan Dickinson from SourceCode, just emailed me and told me that he had written an article about this and how to resolve it.&amp;nbsp; You can read the whole article here: &lt;a href="http://jonathan.dickinsons.co.za/blog/2010/08/windbg-stack-fix/" title="http://jonathan.dickinsons.co.za/blog/2010/08/windbg-stack-fix/"&gt;http://jonathan.dickinsons.co.za/blog/2010/08/windbg-stack-fix/&lt;/a&gt; &lt;br /&gt;Thanks Jonathan for writing that article.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As mentioned in the article there are a couple of things you need to get rid of the problem.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. The correct version of MSCORDACWKS.dll &lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;You can get this in two ways&amp;hellip;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;a. from the Microsoft public symbol server by setting the symbol path to srv*c:\mycache*http://msdl.microsoft.com/download/symbols&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;or &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;b. by copying it from the machine you got the dump from, it is located in the Framework\&amp;lt;version&amp;gt; directory.&amp;nbsp; The mscordacwks.dll needs to be copied to your symbol path, and to differentiate them if you work with multiple versions you can name it mscordacwks_x86_x86_2.0.50727.42.dll for example.&amp;nbsp;&amp;nbsp;&amp;nbsp; On my machine, because I am working with so many different versions i have a c:\dac\x86 and a c:\dac\x64 directory where I store these.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;2. A compatible version of sos.dll &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;sos.dll can be found in your framework\&amp;lt;version&amp;gt; directory and needs to match the architecture and major version of the framework used in the dump.&amp;nbsp; If there is too big of a difference between the minor versions of the framework on your machine and the machine where you got the dump, you can try copying the sos.dll from the machine that the dump was taken from. Or you can use &lt;a href="http://blogs.msdn.com/b/tess/archive/2010/03/30/new-debugger-extension-for-net-psscor2.aspx"&gt;psscor2.dll&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Have a good one, &lt;br /&gt;Tess &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10054054" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/General+debugging+tidbits/">General debugging tidbits</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item><item><title>Getting full user mode dumps automatically when your process crashes</title><link>http://blogs.msdn.com/b/tess/archive/2010/08/23/getting-full-user-mode-dumps-automatically-when-your-process-crashes.aspx</link><pubDate>Mon, 23 Aug 2010 09:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10053057</guid><dc:creator>Tess1</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10053057</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/08/23/getting-full-user-mode-dumps-automatically-when-your-process-crashes.aspx#comments</comments><description>&lt;p&gt;I recently got a question about if it is possible to generate full user mode dumps automatically every time the process crashes (without having debug diag or adplus installed and monitoring your system).&amp;nbsp;&amp;nbsp; This would be useful for example if you are setting up a site, and you want to make sure you get dumps if it ever crashes so that you don&amp;rsquo;t have to repro the issue at that point, just to get data.&lt;/p&gt;
&lt;p&gt;It turns out that starting with Windows Server 2008 and Vista + SP1, Windows Error Reporting (WER) will let you do just that.&amp;nbsp; It even worked on my Win 7 machine.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx" title="http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The documentation here says that &amp;ldquo;Applications that do their own custom crash reporting, including .NET applications, are not supported by this feature&amp;rdquo;.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;It&amp;rsquo;s a bit hard to tell what this actually means but I think this is added here due to ambiguity about what constitutes a crash.&amp;nbsp; For example if you have an exception in an ASP.NET application that is handled by the ASP.NET error handler (i.e. showing you the yellow ASP.NET error page) that is not a &amp;ldquo;crash&amp;rdquo; since ASP.NET handles the error, and the process just continues.&amp;nbsp; However for example a StackOverflow, or any unhandled .net exceptions on finalizers or non-request threads, that cause the process to &amp;ldquo;terminate unexpectedly&amp;rdquo; will be caught by WER and produce a dump if you configure it to do so.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setting this up&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I set this up on my machine (&lt;a href="http://msdn.microsoft.com/en-us/library/bb787181(VS.85).aspx"&gt;per the article&lt;/a&gt;) by adding a registry key specific to w3wp.exe to monitor crashes for my ASP.NET applications&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;HKLM\Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\w3wp.exe &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Under this key I added 3 values (types and descriptions can be found in the MSDN article)&lt;/p&gt;
&lt;blockquote sizset="0" sizcache="3"&gt;
&lt;table cellpadding="2" cellspacing="0" border="1" style="width: 830px;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="112" valign="top"&gt;&amp;nbsp;&lt;/td&gt;
&lt;td width="149" valign="top"&gt;Value&lt;/td&gt;
&lt;td width="567" valign="top"&gt;Comment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="118" valign="top"&gt;DumpFolder&lt;/td&gt;
&lt;td width="155" valign="top"&gt;c:\mycrashdumps&lt;/td&gt;
&lt;td width="563" valign="top"&gt;This is the location where the dumps will be generated, so the user that the W3WP.exe process is running under needs access to write to this location.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="123" valign="top"&gt;DumpCount&lt;/td&gt;
&lt;td width="160" valign="top"&gt;10&lt;/td&gt;
&lt;td width="554" valign="top"&gt;Maximum # of dumps in the folder, depending on the size of the process 10 dumps can take up a lot of disk space, so monitor carefully.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="128" valign="top"&gt;DumpType&lt;/td&gt;
&lt;td width="165" valign="top"&gt;2&lt;/td&gt;
&lt;td width="546" valign="top"&gt;To debug .net crashes a full user mode dump is often necessary.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/blockquote&gt;
&lt;p&gt;I also had to disable the JIT debugger for this to work, under &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HKLM\Software\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug &lt;/p&gt;
&lt;p&gt;By renaming the Debugger value to Debugger-unused, and now it is producing crash dumps for stackoverflows and other unhandled exceptions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A word of caution&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As always, any modifications to the registry should only be done by trained professionals:) and only after carefully backing up the registry first etc. etc.&amp;nbsp; I take no responsibility for any issues caused by such modifications. &lt;/p&gt;
&lt;p&gt;Also, keep in mind that as mentioned before, the dumps can get pretty big if you have processes that produce a lot of memory so be wary about the amount of disk space that this can consume.&lt;/p&gt;
&lt;p&gt;Have a good one, &lt;br /&gt;Tess&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10053057" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/Crash+scenarios/">Crash scenarios</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/General+debugging+tidbits/">General debugging tidbits</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item><item><title>The SQL Server Support Team in Stockholm is hiring</title><link>http://blogs.msdn.com/b/tess/archive/2010/06/23/the-sql-server-support-team-in-stockholm-is-hiring.aspx</link><pubDate>Wed, 23 Jun 2010 10:45:46 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10028939</guid><dc:creator>Tess1</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10028939</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/06/23/the-sql-server-support-team-in-stockholm-is-hiring.aspx#comments</comments><description>&lt;p&gt;If you are a contractor in Stockholm, skilled in SQL, have a look at this post:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://blogs.msdn.com/b/grahamk/archive/2010/06/22/the-sql-server-support-team-in-stockholm-is-hiring.aspx" href="http://blogs.msdn.com/b/grahamk/archive/2010/06/22/the-sql-server-support-team-in-stockholm-is-hiring.aspx"&gt;http://blogs.msdn.com/b/grahamk/archive/2010/06/22/the-sql-server-support-team-in-stockholm-is-hiring.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Have a good one,&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10028939" width="1" height="1"&gt;</description></item><item><title>.NET Memory Leak: XslCompiledTransform and “leaked” dynamic assemblies</title><link>http://blogs.msdn.com/b/tess/archive/2010/05/05/net-memory-leak-xslcompiledtransform-and-leaked-dynamic-assemblies.aspx</link><pubDate>Wed, 05 May 2010 14:39:19 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10007783</guid><dc:creator>Tess1</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10007783</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/05/05/net-memory-leak-xslcompiledtransform-and-leaked-dynamic-assemblies.aspx#comments</comments><description>&lt;p&gt;I have written before about high memory usage caused by improper usage of XmlSerializer objects both in a &lt;a href="http://blogs.msdn.com/tess/archive/2006/02/15/532804.aspx"&gt;case study&lt;/a&gt; and in a &lt;a href="http://blogs.msdn.com/tess/archive/2008/03/17/net-debugging-demos-lab-6-memory-leak.aspx"&gt;debugging lab&lt;/a&gt;.&amp;#160; The problem there was that every time you create a new XmlSerializer object with a non-default constructor, you generate a new dynamic assembly that contains the definition and methods for the serializer.&amp;#160; Since assemblies can’t be unloaded from a process unless the application domain they are loaded in is unloaded memory will keep increasing if you create new XmlSerializer objects until eventually you end up with a System.OutOfMemoryException.&lt;/p&gt;  &lt;p&gt;In the case of the XmlSerializer dynamic assemblies, they are quite easy to spot as you can look at meta-data (see previous posts) and figure out that they are XmlSerializer generated assemblies, and you can even see what type is being serialized.&lt;/p&gt;  &lt;p&gt;This time I’m going to walk through a similar issue where unfortunately the dynamic assembly generator is a bit more difficult to spot.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Symptoms:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Any issue where you are leaking dynamic assemblies will have very similar symptoms and they go something like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1. The perfmon counter Process/Private Bytes keeps increasing (Mem Usage in task manager will keep increasing too for that matter)&lt;/p&gt;    &lt;p&gt;2. .NET CLR Memory/#Bytes in all heaps may increase but unless you also have a .net object “memory leak” #Bytes in all heaps should not follow the Private Bytes pattern as the dynamic assemblies are not stored on the GC heaps.&amp;#160;&amp;#160; For a typical assembly leak problem, #Bytes in all heaps will be relatively low compared to Private Bytes.&lt;/p&gt;    &lt;p&gt;3. .NET CLR Loading/Current assemblies keeps increasing throughout the lifetime of the process.&amp;#160; Normally the number of loaded assemblies should flatten out once all components in the process are loaded so if Current assemblies keeps increasing, that is a pretty sure sign that you have an assembly leak.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;Debugging:&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Once memory usage for the process is fairly high, you can capture a memory dump of the process with any of your favorite tools (&lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&amp;amp;displaylang=en"&gt;debug diag&lt;/a&gt;, adplus, task manager, procdmp etc.).&amp;#160; Using debug diag for example, you just right-click the w3wp.exe process in the processes view and select the “Create Full Userdump” option.&lt;/p&gt;  &lt;p&gt;In my case, &lt;strong&gt;&lt;em&gt;Private Bytes&lt;/em&gt;&lt;/strong&gt; was around 790 MB, &lt;strong&gt;&lt;em&gt;#Bytes in all heaps&lt;/em&gt;&lt;/strong&gt; was 28 MB and I had 1031 &lt;strong&gt;&lt;em&gt;Current assemblies &lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If you only have a memory dump but no perfmon counters, you can get this data from the dump as well if you open it up in windbg.    &lt;br /&gt;&lt;em&gt;Note: for some commands in this article you will need to load &lt;/em&gt;&lt;a href="http://blogs.msdn.com/tess/archive/2010/03/30/new-debugger-extension-for-net-psscor2.aspx"&gt;&lt;em&gt;psscor.dll&lt;/em&gt;&lt;/a&gt;&lt;em&gt; in windbg. &lt;/em&gt;&lt;/p&gt;  &lt;pre class="debug"&gt;0:026&amp;gt; !address -summary
&lt;br /&gt;...
&lt;br /&gt;&lt;br /&gt;-------------------- State SUMMARY --------------------------
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; TotSize (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; KB)&amp;#160;&amp;#160; Pct(Tots)&amp;#160; Usage
&lt;br /&gt;&lt;strong&gt;&amp;#160;&amp;#160; 3081a000 (&amp;#160; 794728) : 18.95%&amp;#160;&amp;#160; : MEM_COMMIT      &amp;lt;- very similar to private bytes
&lt;/strong&gt;&lt;br /&gt;&amp;#160;&amp;#160; a5eaf000 ( 2718396) : 64.81%&amp;#160;&amp;#160; : MEM_FREE
&lt;br /&gt;&amp;#160;&amp;#160; 29927000 (&amp;#160; 681116) : 16.24%&amp;#160;&amp;#160; : MEM_RESERVE 
&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;

&lt;pre class="debug"&gt;0:026&amp;gt; !eeheap -gc
&lt;br /&gt;Number of GC Heaps: 2
&lt;br /&gt;------------------------------
...
&lt;br /&gt;GC Heap Size&amp;#160; 0x1b5396c(&lt;strong&gt;28,653,932&lt;/strong&gt;)                &lt;strong&gt;&amp;lt;- #Bytes in all heaps&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;For current assemblies, you can’t easily get the total number of assemblies, but !dumpdomain –stat will tell you how many assemblies are loaded in each domain.&amp;#160; Note however that there may be some overlap here as some assemblies will be listed in multiple domains.&amp;#160; Also, the size of the dynamic assemblies may or may not show up here in the size assemblies column.&amp;#160; &lt;/p&gt;

&lt;p&gt;The cool thing about this output though is that you can easily identify the domain that is leaking assemblies.&amp;#160; In this case it is probably not all that surprising that it happens to be my XSLMemoryLeak demo application where I am reproducing the problem:)&lt;/p&gt;

&lt;pre class="debug"&gt;0:026&amp;gt; !dumpdomain -stat
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Domain&amp;#160;&amp;#160;&amp;#160;&amp;#160; Num Assemblies&amp;#160;&amp;#160;&amp;#160;&amp;#160; Size Assemblies&amp;#160;&amp;#160;&amp;#160;&amp;#160; Name
&lt;br /&gt;7a3bd058&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0&amp;#160;&amp;#160;&amp;#160;&amp;#160; System Domain
&lt;br /&gt;7a3bc9a8&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 27&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 85,086,720&amp;#160;&amp;#160;&amp;#160;&amp;#160; Shared Domain
&lt;br /&gt;0019f280&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 9&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 48,486,400&amp;#160;&amp;#160;&amp;#160;&amp;#160; DefaultDomain
&lt;br /&gt;001d3038&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1,031&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 85,100,032&amp;#160;&amp;#160;&amp;#160;&amp;#160; /LM/w3svc/1/ROOT/XSLMemoryLeak-1-129175353121633629&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;What are these assemblies?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Btw, if you don’t care for a deep dive in potentially non-interesting windbg / psscor gory details, feel free to move right to the conclusion at the bottom of the post:)&lt;/p&gt;

&lt;p&gt;Time for a new function in psscor called !dumpdynamicassemblies (or !dda for those of us who don’t want to end up with &lt;a href="http://www.answers.com/topic/cobol-fingers-computer-jargon"&gt;COBOL fingers&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This function has two purposes &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;a. list all the dynamic assemblies in the process, or 
    &lt;br /&gt;b. save all dynamic assemblies to disc using !dda –save, so that you can open them up in reflector or similar&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Running this on the dump I can see that there is a total of 1002 dynamic assemblies in the dump and that all of them are in the XSLMemoryLeak domain.&amp;#160; Each assembly seems to have 2 modules associated with it so there is a total of 2004 modules associated with these assemblies.&lt;/p&gt;

&lt;pre class="debug"&gt;0:026&amp;gt; !dda
&lt;br /&gt;Domain: DefaultDomain
&lt;br /&gt;------------------- 
&lt;br /&gt;Domain: /LM/w3svc/1/ROOT/XSLMemoryLeak-1-129175353121633629
&lt;br /&gt;------------------- &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Assembly: 0x10514528 [] Dynamic Module: 0x02af8740 loaded at: 0x00000000 Size: 0x00000000(0)
&lt;br /&gt;Assembly: 0x10514528 [] Dynamic Module: 0x02af8ac0 loaded at: 0x00000000 Size: 0x00000000(0) &lt;br /&gt;
&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Assembly: 0x10589558 [] Dynamic Module: 0x106122c4 loaded at: 0x00000000 Size: 0x00000000(0)
&lt;br /&gt;Assembly: 0x10589558 [] Dynamic Module: 0x10612644 loaded at: 0x00000000 Size: 0x00000000(0)&lt;br /&gt;
&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Assembly: 0x3472c168 [] Dynamic Module: 0x53402e8c loaded at: 0x00000000 Size: 0x00000000(0)
&lt;br /&gt;Assembly: 0x3472c168 [] Dynamic Module: 0x5340320c loaded at: 0x00000000 Size: 0x00000000(0)

&lt;br /&gt;&lt;br /&gt;Assembly: 0x347728b8 [] Dynamic Module: 0x53403630 loaded at: 0x00000000 Size: 0x00000000(0)
&lt;br /&gt;Assembly: 0x347728b8 [] Dynamic Module: 0x534039b0 loaded at: 0x00000000 Size: 0x00000000(0) 

&lt;br /&gt;&lt;br /&gt;Assembly: 0x347b9010 [] Dynamic Module: 0x53403dd4 loaded at: 0x00000000 Size: 0x00000000(0)
&lt;br /&gt;Assembly: 0x347b9010 [] Dynamic Module: 0x53404154 loaded at: 0x00000000 Size: 0x00000000(0) 
&lt;br /&gt;--------------------------------------
&lt;br /&gt;Total 1,002 Dynamic Assemblies, Total size: 0x0(0) bytes.
&lt;br /&gt;=======================================&lt;/pre&gt;

&lt;p&gt;Unfortunately, because the reported size is 0, saving them out will do me no good as they don’t have any meta-data so I will have to find another way to figure out what they are.&lt;/p&gt;

&lt;p&gt;I was working on this issue with my colleague &lt;a href="http://blogs.msdn.com/dougste"&gt;Doug&lt;/a&gt; and after doing some random “checking around the dump to see if we can find anything even remotely interesting” we noticed that on the heap we had exactly the same amount of System.Reflection.Emit.ModuleBuilderData objects as the number of modules listed above.&lt;/p&gt;

&lt;pre class="debug"&gt;0:026&amp;gt; !dumpheap -stat -type System.Reflection.Emit*
&lt;br /&gt;Loading the heap objects into our cache.
&lt;br /&gt;------------------------------
&lt;br /&gt;Heap 0
&lt;br /&gt;total 38,045 objects
&lt;br /&gt;------------------------------
&lt;br /&gt;Heap 1
&lt;br /&gt;total 40,553 objects
&lt;br /&gt;------------------------------
&lt;br /&gt;total 78,598 objects
 &lt;br /&gt;Statistics:
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; MT&amp;#160;&amp;#160;&amp;#160; Count&amp;#160;&amp;#160;&amp;#160; TotalSize&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Change Class Name
&lt;br /&gt;0x79305120&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;2,004&lt;/strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 64,128&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2,004 System.Reflection.Emit.AssemblyBuilder
&lt;br /&gt;0x79318c9c&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;2,004&lt;/strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 88,176&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2,004 System.Reflection.Emit.ModuleBuilderData
 &lt;br /&gt;&lt;/pre&gt;

&lt;p&gt;From this we were able to get some very important data…&lt;/p&gt;

&lt;p&gt;First we dumped out the ModuleBuilderData objects:&lt;/p&gt;

&lt;pre class="debug"&gt;0:026&amp;gt; !dumpheap -type System.Reflection.Emit.ModuleBuilderData
&lt;br /&gt;Loading the heap objects into our cache.
&lt;br /&gt;------------------------------
&lt;br /&gt;&amp;#160;&amp;#160; Address&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; MT&amp;#160;&amp;#160;&amp;#160;&amp;#160; Size
&lt;br /&gt;...
&lt;br /&gt;07c8bc98 79318c9c&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 44&amp;#160;&amp;#160;&amp;#160; 0 System.Reflection.Emit.ModuleBuilderData 
&lt;br /&gt;07c8c6ec 79318c9c&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 44&amp;#160;&amp;#160;&amp;#160; 0 System.Reflection.Emit.ModuleBuilderData 
&lt;br /&gt;07cc04d8 79318c9c&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 44&amp;#160;&amp;#160;&amp;#160; 0 System.Reflection.Emit.ModuleBuilderData 
&lt;br /&gt;&lt;strong&gt;07cc0f2c&lt;/strong&gt; 79318c9c&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 44&amp;#160;&amp;#160;&amp;#160; 0 System.Reflection.Emit.ModuleBuilderData &lt;/pre&gt;

&lt;p&gt;And took a closer look at one of them&lt;/p&gt;

&lt;pre class="debug"&gt;0:026&amp;gt; !do &lt;strong&gt;07cc0f2c&lt;/strong&gt; 
&lt;br /&gt;Name: System.Reflection.Emit.ModuleBuilderData
&lt;br /&gt;...
&lt;br /&gt;Fields:
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; MT&amp;#160;&amp;#160;&amp;#160; Field&amp;#160;&amp;#160; Offset&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Type VT&amp;#160;&amp;#160;&amp;#160;&amp;#160; Attr&amp;#160;&amp;#160;&amp;#160; Value Name
&lt;br /&gt;793308ec&amp;#160; 4002612&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 4&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; System.String&amp;#160; 0 instance 02dc67fc m_strModuleName
&lt;br /&gt;793308ec&amp;#160; 4002613&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 8&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; System.String&amp;#160; 0 instance &lt;strong&gt;02dc67fc&lt;/strong&gt; m_strFileName
&lt;br /&gt;...
&lt;br /&gt;79318b90&amp;#160; 4002617&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 10 ...mit.ModuleBuilder&amp;#160; 0 instance &lt;strong&gt;07cc0c94&lt;/strong&gt; m_module
&lt;br /&gt;79332b38&amp;#160; 4002618&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 20&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; System.Int32&amp;#160; 1 instance&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 m_tkFile
&lt;br /&gt;...&lt;/pre&gt;

&lt;p&gt;The m_strFileName proved to be a crucial piece of information telling us that the module was called System.Xml.Xsl.CompiledQuery so now we know that they are generated when loading XSL Transforms&lt;/p&gt;

&lt;pre class="debug"&gt;0:026&amp;gt; !do 02dc67fc 
&lt;br /&gt;Name: System.String
&lt;br /&gt;MethodTable: 793308ec
&lt;br /&gt;EEClass: 790ed64c
&lt;br /&gt;Size: 74(0x4a) bytes
&lt;br /&gt;GC Generation: 2
&lt;br /&gt;String: &lt;strong&gt;System.Xml.Xsl.CompiledQuery&lt;/strong&gt;
&lt;br /&gt;...&lt;/pre&gt;

&lt;p&gt;But how can we prove that these ModuleBuilderData objects are really related to the dynamic assemblies?&lt;/p&gt;

&lt;p&gt;For this we need to look closer at the ModuleBuilderData objects m_module field and dump out this ModuleBuilder and later also its m_internalModuleBuilder&lt;/p&gt;

&lt;pre class="debug"&gt;0:026&amp;gt; !do &lt;strong&gt;07cc0c94&lt;/strong&gt; 
&lt;br /&gt;Name: System.Reflection.Emit.ModuleBuilder
&lt;br /&gt;...
&lt;br /&gt;Fields:
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; MT&amp;#160;&amp;#160;&amp;#160; Field&amp;#160;&amp;#160; Offset&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Type VT&amp;#160;&amp;#160;&amp;#160;&amp;#160; Attr&amp;#160;&amp;#160;&amp;#160; Value Name
&lt;br /&gt;...
&lt;br /&gt;79318b90&amp;#160; 400260e&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2c ...mit.ModuleBuilder&amp;#160; 0 instance &lt;strong&gt;07cc0c5c&lt;/strong&gt; m_internalModuleBuilder
&lt;br /&gt;79305120&amp;#160; 400260f&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 30 ...t.AssemblyBuilder&amp;#160; 0 instance 07cc0418 m_assemblyBuilder
&lt;br /&gt;... &lt;/pre&gt;

&lt;pre class="debug"&gt;0:026&amp;gt; !do &lt;strong&gt;07cc0c5c&lt;/strong&gt; 
Name: System.Reflection.Emit.ModuleBuilder
&lt;br /&gt;...
&lt;br /&gt;Fields:
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; MT&amp;#160;&amp;#160;&amp;#160; Field&amp;#160;&amp;#160; Offset&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Type VT&amp;#160;&amp;#160;&amp;#160;&amp;#160; Attr&amp;#160;&amp;#160;&amp;#160; Value Name
&lt;br /&gt;...
&lt;br /&gt;793331b4&amp;#160; 4000d21&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 14&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; System.IntPtr&amp;#160; 1 instance&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 m__pRefClass
&lt;br /&gt;793331b4&amp;#160; 4000d22&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 18&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; System.IntPtr&amp;#160; 1 instance &lt;strong&gt;1396719956&lt;/strong&gt; m__pData
&lt;br /&gt;793331b4&amp;#160; 4000d23&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1c&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; System.IntPtr&amp;#160; 1 instance 669415152 m__pInternalSymWriter
&lt;br /&gt;793331b4&amp;#160; 4000d24&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 20&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; System.IntPtr&amp;#160; 1 instance&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 m__pGlobals
&lt;br /&gt;...&lt;/pre&gt;

&lt;p&gt;Don’t ask me how you come up with this and the next part:)&amp;#160; This is the fruit of some serious desperation, trying to find anything that fits :)&lt;/p&gt;

&lt;p&gt;We then see that the m__pData member variable is an IntPtr so we can turn this into hex by running&lt;/p&gt;

&lt;pre class="debug"&gt;0:026&amp;gt; ?&lt;strong&gt;0n1396719956&lt;/strong&gt; 
&lt;br /&gt;Evaluate expression: 1396719956 = &lt;strong&gt;53404154&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;And voilà, this just happens to be the address of one of the dynamic assembly modules, so Houston, we have a match…&lt;/p&gt;

&lt;pre class="debug"&gt;Assembly: 0x347b9010 [] Dynamic Module: 0x53403dd4 loaded at: 0x00000000 Size: 0x00000000(0) 
&lt;br /&gt;Assembly: 0x347b9010 [] Dynamic Module: &lt;strong&gt;0x53404154&lt;/strong&gt; loaded at: 0x00000000 Size: 0x00000000(0) &lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ok, so all that crazy debugging to find out that the dynamic assemblies were related to XSL Transforms.&lt;/p&gt;

&lt;p&gt;As it turns out, if you create a new XslCompiledTransform(true) where true means enable debugging, a new dynamic assembly will be generated when you load the stylesheet.&lt;/p&gt;

&lt;p&gt;On the other hand if this is set to false, or if you use new XslCompiledTransform() this will not happen, so just remember to turn it off when you go into production, not only for this but to stop emitting debug info at that point.&lt;/p&gt;

&lt;p&gt;Have a good one, 
  &lt;br /&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10007783" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/Memory+issues/">Memory issues</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item><item><title>New Visual Studio 2010 and .NET 4 debugging content</title><link>http://blogs.msdn.com/b/tess/archive/2010/04/28/new-visual-studio-2010-and-net-4-debugging-content.aspx</link><pubDate>Wed, 28 Apr 2010 12:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10003138</guid><dc:creator>Tess1</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10003138</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/04/28/new-visual-studio-2010-and-net-4-debugging-content.aspx#comments</comments><description>&lt;p&gt;It’s been a pretty busy few weeks at work coupled with some vacation so I’ve been lagging a bit with the blogging, so sorry for bombarding the blog with new posts now:)&lt;/p&gt;  &lt;p&gt;As you all know, Visual Studio 2010 just released and there is a lot of new content out there and I thought I’d mention a few in the debugging/troubleshooting space.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://weblogs.asp.net/scottgu" target="_blank"&gt;ScottGu&lt;/a&gt; wrote a post on the &lt;a href="http://weblogs.asp.net/scottgu/archive/2010/04/21/vs-2010-debugger-improvements-breakpoints-datatips-import-export.aspx" target="_blank"&gt;VS 2010 debugger improvements&lt;/a&gt; as part of his &lt;a href="http://weblogs.asp.net/scottgu/archive/2009/08/25/vs-2010-and-net-4-series.aspx" target="_blank"&gt;VS 2010 and .NET 4&lt;/a&gt; post series where he talks about news with Data Tips and Breakpoints.&lt;/li&gt;    &lt;li&gt;The &lt;a href="http://blogs.msdn.com/profiler" target="_blank"&gt;Visual Studio Profiler Team Blog&lt;/a&gt; has a lot of posts worth reading about &lt;a href="http://blogs.msdn.com/profiler/archive/tags/vs2010/default.aspx" target="_blank"&gt;profiling in VS 2010&lt;/a&gt;, including Silverlight Profiling and guidance for profiling.&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.stevestechspot.com" target="_blank"&gt;Steve&lt;/a&gt; released a &lt;a href="http://www.stevestechspot.com/SOSEXV40NowAvailable.aspx" target="_blank"&gt;new version of SOSex.dll&lt;/a&gt; with features that work for both 2.0 and 4.0&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.wintellect.com/cs/blogs/jrobbins/default.aspx" target="_blank"&gt;John Robbins&lt;/a&gt; released &lt;a href="http://channel9.msdn.com/posts/egibson/MSDN-Simulcast-Techniques-in-Advanced-NET-Debugging-with-John-Robbins-Part-1-of-3/" target="_blank"&gt;3 new really good webcasts&lt;/a&gt; (unfortunately the encoding is a bit poor but the content makes up for it) on channel 9 about Advanced .NET Debugging in VSTS 2010 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;There is probably plenty more out there but that should at least get you started.&lt;/p&gt;  &lt;p&gt;My presentation from &lt;a href="http://www.microsoft.com/sverige/techdays/"&gt;TechDays&lt;/a&gt; Sweden 2010 was also recorded (in Swedish).     &lt;br /&gt;&lt;a href="http://www.microsoft.com/sverige/techdays/inspelning.aspx?d=http://download.microsoft.com/download/2/6/5/2655127A-A872-4FA3-8E64-28CCA07B618C/64.pdf&amp;amp;m=http://mediadl.microsoft.com/mediadl/www/s/sverige/techdays10/64.wmv"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; margin: 15px 15px 0px 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" align="left" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/NewVisualStudio2010.NET4debuggingcontent_CEBF/image_3.png" width="244" height="179" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Last minute, I was chatting with one of my friends &lt;a href="http://blog.multi-core.net/"&gt;Tiberiu Covaci&lt;/a&gt; who specializes in parallel programming.&amp;#160; Since I was given the graveyard slot (last slot of the conference) we decided to have some fun with it and present together figuring people would be half-asleep anyways after the party from the day before:)&lt;/p&gt;  &lt;p&gt;The first few minutes are meant as a joke and a bit of a nudge to those who like to do death-by-powerpoint and spend 30 mins presenting their company and their careers :) If you stay past that you’ll see a demo from start to finish of a performance problem (with profiling, dump debugging in VS 2010 and dump debugging in windbg).&amp;#160; &lt;/p&gt;  &lt;p&gt;If you want to know who is who in the video, I’m the girl who forgot to comb her hair before the presentation, and Tibi is the funny guy with the big Romanian family:)&lt;/p&gt;  &lt;p&gt;Laters,&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10003138" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/presentation/">presentation</category></item><item><title>Debugging a classic ReaderWriterLock deadlock with SOSex.dll</title><link>http://blogs.msdn.com/b/tess/archive/2010/04/27/debugging-a-classic-readerwriterlock-deadlock-with-sosex-dll.aspx</link><pubDate>Tue, 27 Apr 2010 11:07:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10003088</guid><dc:creator>Tess1</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10003088</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/04/27/debugging-a-classic-readerwriterlock-deadlock-with-sosex-dll.aspx#comments</comments><description>&lt;p&gt;I was helping out on an issue the other day where the process would stall if they added enough users in their load tests.&amp;#160; Btw, serious kudos to them for making load tests, so much nicer to work with a problem in test rather than when it is getting critical on a production machine.&lt;/p&gt;  &lt;p&gt;We gathered some memory dumps with &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&amp;amp;displaylang=en" target="_blank"&gt;debug diag&lt;/a&gt; of the asp.net process (w3wp.exe) and found that most of the threads were waiting in this type of callstack:&amp;#160; &lt;br /&gt;&lt;em&gt;     &lt;br /&gt;NOTE:&amp;#160; I have changed a lot of function names and code snippets since it is not relevant for the post.&lt;/em&gt;&lt;/p&gt;  &lt;pre class="debug"&gt;0:071&amp;gt; !clrstack 
&lt;br /&gt;OS Thread Id: 0x21ac (71) 
&lt;br /&gt;ESP&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; EIP&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;1c8ceb88 7c8285ec [HelperMethodFrame_1OBJ: 1c8ceb88] System.Threading.ReaderWriterLock.AcquireReaderLockInternal(Int32) 
&lt;br /&gt;1c8cebe4 1c880d72 DataStore.get_SomeItem() 
&lt;br /&gt;...&lt;/pre&gt;

&lt;p&gt;So they were sitting in DataStore.get_SomeItem, waiting to acquire a ReaderLock for some resource.&amp;#160; A ReaderWriterLock is used to synchronize access to resources, where you want to allow multiple readers at the same time, or one writer.&amp;#160; &lt;br /&gt;

  &lt;br /&gt;To be honest, I can’t say that I see it used all that often, and now there is also a &lt;a href="http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx" target="_blank"&gt;ReaderWriterLockSlim&lt;/a&gt; that is similar to the ReaderLock but designed to avoid some of the more common deadlocks.&lt;/p&gt;

&lt;p&gt;Sosex from &lt;a href="http://www.stevestechspot.com/" target="_blank"&gt;Steve’s Techspot&lt;/a&gt; has some really nice commands for reader writer locks that both display information about the RWlocks as well as detects deadlocks between them.&lt;/p&gt;

&lt;p&gt;First we have &lt;strong&gt;!rwlock&lt;/strong&gt;… this is similar to !syncblk for locks/monitors and here we can get some basic information about the readerwriterlocks in the process.&lt;/p&gt;

&lt;pre class="debug"&gt;0:174&amp;gt; !rwlock
&lt;br /&gt;Address&amp;#160;&amp;#160;&amp;#160; ReaderCount&amp;#160;&amp;#160; WaitingReaderCount&amp;#160;&amp;#160; WriterThread&amp;#160;&amp;#160; WaitingWriterCount
&lt;br /&gt;---------------------------------------------------------------------------------------
…&lt;br /&gt;0e9167d0&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;strong&gt;50&lt;/strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2
&lt;br /&gt;0e9167fc&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 45&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1&lt;/pre&gt;

&lt;p&gt;We have two interesting locks here (0e9167d0, and 0e9167fc)&lt;/p&gt;

&lt;p&gt;For 0e9167d0 (I’ll call this Lock1 in the future), thread 50 owns the WriterLock so no-one else can acquire neither a ReaderLock nor WriterLock for this, and we have 2 threads waiting to acquire the WriterLock on this.&lt;/p&gt;

&lt;p&gt;For 0e9167fc (I’ll call this Lock2 in the future), we have two threads that own ReaderLocks on this, we have 1 thread waiting to acquire a WriterLock on it, and 45 other threads waiting to acquire a ReaderLock on it.&amp;#160; The thread waiting to acquire the WriterLock is probably first in queue, but until the current readers give up their locks, the WriterLock can’t be acquired.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(I will get back to these thread numbers in a moment because it gets pretty tricky)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can also dig into a particular lock by running !rwlock &amp;lt;lock address&amp;gt;&lt;/p&gt;

&lt;pre class="debug"&gt;0:068&amp;gt; !rwlock 0e9167d0      (&amp;lt;- Lock1)
&lt;br /&gt;WriterThread:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 50
&lt;br /&gt;WriterLevel:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1
&lt;br /&gt;WaitingWriterCount:&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2
&lt;br /&gt;WriterEvent:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; e54
&lt;br /&gt;WaitingWriterThreadIds: &lt;strong&gt;14,47&lt;/strong&gt;
&lt;br /&gt;ReaderCount:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0
&lt;br /&gt;CurrentReaderThreadIds: None
&lt;br /&gt;WaitingReaderCount:&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0
&lt;br /&gt;ReaderEvent:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0
&lt;br /&gt;WaitingReaderThreadIds: None&lt;/pre&gt;

&lt;pre class="debug"&gt;0:174&amp;gt; !rwlock 0e9167fc&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;lt;-Lock2)&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;WriterThread:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0
&lt;br /&gt;WriterLevel:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0
&lt;br /&gt;WaitingWriterCount:&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1
&lt;br /&gt;WriterEvent:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; e00
&lt;br /&gt;WaitingWriterThreadIds: &lt;strong&gt;50&lt;/strong&gt;
&lt;br /&gt;ReaderCount:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 2
&lt;br /&gt;CurrentReaderThreadIds: &lt;strong&gt;14,47&lt;/strong&gt;
&lt;br /&gt;WaitingReaderCount:&amp;#160;&amp;#160;&amp;#160;&amp;#160; 45
&lt;br /&gt;ReaderEvent:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; e7c
&lt;br /&gt;WaitingReaderThreadIds: 54,57,58,61,62,66,67,70,71,74,75,78,79,82,83,86,87,90,91,94,95,98,99,102,103,106,107,110,111,114,115,118,119,122,123,126,127,130,131,134,137,140,143,146,149&lt;/pre&gt;

&lt;p&gt;With this info, we can now gather that threads 14 and 47 own readerlocks for Lock2, but they won’t give them up until they can get WriterLocks for Lock1.&amp;#160;&amp;#160; Thread 50 on the other hand, has a WriterLock on Lock1 and wont give it up until it can get the WriterLock on Lock2, hence we have a deadlock.&lt;/p&gt;

&lt;p&gt;The good thing here is that if you don’t care to do this investigation on your own, SOSEX has a function that will do it for you called !dlk (deadlock).&lt;/p&gt;

&lt;pre class="debug"&gt;0:174&amp;gt; !dlk
&lt;br /&gt;Examining SyncBlocks...
&lt;br /&gt;Scanning for ReaderWriterLocks...
&lt;br /&gt;Scanning for lock holders on ReaderWriterLocks...
&lt;br /&gt;Scanning for threads waiting on SyncBlocks...
&lt;br /&gt;Scanning for threads waiting on ReaderWriterLocks...&lt;br /&gt;
&lt;br /&gt;&lt;strong&gt;Deadlock detected:
&lt;/strong&gt;&lt;br /&gt;CLR thread 14 holds a Reader lock on ReaderWriterLock 0e9167fc
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; is waiting for a Writer lock on ReaderWriterLock 0e9167d0
&lt;br /&gt;CLR thread 50 holds a Writer lock on ReaderWriterLock 0e9167d0
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; is waiting for a Writer lock on ReaderWriterLock 0e9167fc
&lt;br /&gt;CLR Thread 14 is waiting at DataStore.InitializeDataIfNotInitialized()(+0x0 IL)(+0x0 Native)
&lt;br /&gt;CLR Thread 50 is waiting at System.Threading.ReaderWriterLock.UpgradeToWriterLock(Int32)(+0x0 IL)(+0x0 Native)&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Deadlock detected:
&lt;/strong&gt;&lt;br /&gt;CLR thread 47 holds a Reader lock on ReaderWriterLock 0e9167fc
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; is waiting for a Writer lock on ReaderWriterLock 0e9167d0
&lt;br /&gt;CLR thread 50 holds a Writer lock on ReaderWriterLock 0e9167d0
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; is waiting for a Writer lock on ReaderWriterLock 0e9167fc
&lt;br /&gt;CLR Thread 47 is waiting at DataStore.InitializeDataIfNotInitialized()(+0x0 IL)(+0x0 Native)
&lt;br /&gt;CLR Thread 50 is waiting at System.Threading.ReaderWriterLock.UpgradeToWriterLock(Int32)(+0x0 IL)(+0x0 Native) &lt;br /&gt;
&lt;strong&gt;2 deadlocks detected.&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Explanation of the Thread IDs coming from the SOSEX RWLock methods&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So this is all nice and good, but what are these thread IDs? is it the logical thread ID (1st column in !threads), the CLR ID (2nd column in !threads) or the OSID (OS Thread ID)?&amp;#160; Turns out it is neither…&amp;#160; or rather it is actually the CLR ID in decimal form:)&amp;#160; Steve mentioned he might change this later to be the hex value so stay tuned for new updates of SOSEX for that and other functionality.&lt;/p&gt;

&lt;pre class="debug"&gt;0:054&amp;gt; !threads
&lt;br /&gt;ThreadCount: 154
&lt;br /&gt;UnstartedThread: 1
&lt;br /&gt;BackgroundThread: 103
&lt;br /&gt;PendingThread: 0
&lt;br /&gt;DeadThread: 1
&lt;br /&gt;Hosted Runtime: no
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; PreEmptive&amp;#160;&amp;#160; GC Alloc&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Lock
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ID OSID ThreadOBJ&amp;#160;&amp;#160;&amp;#160; State&amp;#160;&amp;#160;&amp;#160;&amp;#160; GC&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Context&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Domain&amp;#160;&amp;#160; Count APT Exception
&lt;br /&gt;&amp;#160; 16&amp;#160;&amp;#160;&amp;#160; 1 1474 0010c0a8&amp;#160;&amp;#160; 3808220 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1 MTA (Threadpool Worker)
&lt;br /&gt;...
&lt;br /&gt;&amp;#160; 32&amp;#160;&amp;#160;&amp;#160; d 2520 1abd0948&amp;#160;&amp;#160; 200b020 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 MTA
&lt;br /&gt;&amp;#160; &lt;font color="#ff0000"&gt;&lt;strong&gt;11&amp;#160;&amp;#160;&amp;#160; e&lt;/strong&gt;&lt;/font&gt; 1fcc 1abdc9e8&amp;#160;&amp;#160; a80a220 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1 MTA (Threadpool Completion Port)
&lt;br /&gt;&amp;#160; 33&amp;#160;&amp;#160;&amp;#160; f 1224 1abe5c10&amp;#160;&amp;#160; 380b220 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1 MTA (Threadpool Worker)
&lt;br /&gt;...
&lt;br /&gt;&amp;#160; 37&amp;#160;&amp;#160; 13 1cc8 1ac22618&amp;#160;&amp;#160; 380b220 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1 MTA (Threadpool Worker)
&lt;br /&gt;&amp;#160; 38&amp;#160;&amp;#160; 14 23e8 1ac229e8&amp;#160;&amp;#160; 200b020 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 MTA
&lt;br /&gt;&amp;#160; 39&amp;#160;&amp;#160; 15 2230 1ac22db8&amp;#160;&amp;#160; 380b220 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1 MTA (Threadpool Worker)
&lt;br /&gt;...
&lt;br /&gt;&amp;#160; 63&amp;#160;&amp;#160; 2d 23e0 1ab934c0&amp;#160;&amp;#160; 380b220 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1 MTA (Threadpool Worker)
&lt;br /&gt;&amp;#160; 64&amp;#160;&amp;#160; 2e 19ac 1ac3d190&amp;#160;&amp;#160; 200b020 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 MTA
&lt;br /&gt;&amp;#160; &lt;strong&gt;&lt;font color="#ff0000"&gt;65&amp;#160;&amp;#160; 2f&lt;/font&gt;&lt;/strong&gt; 1644 1aba8f40&amp;#160;&amp;#160; a80b220 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1 MTA (Threadpool Completion Port)
&lt;br /&gt;&amp;#160; 66&amp;#160;&amp;#160; 30 10f4 1abaaaa8&amp;#160;&amp;#160; 380b220 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1 MTA (Threadpool Worker)
&lt;br /&gt;&amp;#160; 67&amp;#160;&amp;#160; 31 121c 1ac47418&amp;#160;&amp;#160; 200b020 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 MTA
&lt;br /&gt;&amp;#160; &lt;strong&gt;&lt;font color="#ff0000"&gt;68&amp;#160;&amp;#160; 32&lt;/font&gt;&lt;/strong&gt; 1b00 1abfdd70&amp;#160;&amp;#160; a80b220 Enabled&amp;#160; 00000000:00000000 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1 MTA (Threadpool Completion Port)
&lt;br /&gt;&amp;#160; 69&amp;#160;&amp;#160; 33 2198 1ac55358&amp;#160;&amp;#160; 200b220 Enabled&amp;#160; 06e140e4:06e150b4 0013fa58&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 MTA&lt;/pre&gt;

&lt;p&gt;In our case, the threads we were interested in were 14 (0xe) = 11, 47 (0x2f) = 65 and 50 (0x32) = 68&lt;/p&gt;

&lt;p&gt;If we take a look at these threads (11 and 68), the stacks look like this:&lt;/p&gt;

&lt;pre class="debug"&gt;0:011&amp;gt; !clrstack
&lt;br /&gt;OS Thread Id: 0x1fcc (11)
&lt;br /&gt;ESP&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; EIP&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;01c7f250 7c8285ec [HelperMethodFrame_1OBJ: 01c7f250] System.Threading.ReaderWriterLock.AcquireWriterLockInternal(Int32)
&lt;br /&gt;01c7f2ac 1c880e07 DataStore.InitializeDataIfNotInitialized()
&lt;br /&gt;01c7f2e4 1c880d78 DataStore.get_SomeItem()
&lt;br /&gt;... &lt;br /&gt;&lt;br /&gt;
0:068&amp;gt; !clrstack
&lt;br /&gt;OS Thread Id: 0x1b00 (68)
&lt;br /&gt;ESP&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; EIP&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;1c71ed0c 7c8285ec [GCFrame: 1c71ed0c] 
&lt;br /&gt;1c71ed28 7c8285ec [HelperMethodFrame_1OBJ: 1c71ed28] System.Threading.ReaderWriterLock.FCallUpgradeToWriterLock(System.Threading.LockCookie ByRef, Int32)
&lt;br /&gt;1c71ed88 792af05d System.Threading.ReaderWriterLock.UpgradeToWriterLock(Int32)
&lt;br /&gt;1c71edac 1c880e19 DataStore.InitializeDataIfNotInitialized()
&lt;br /&gt;1c71ede4 1c880d78 DataStore.get_SomeItem()&lt;br /&gt;&lt;br /&gt;... &lt;/pre&gt;

&lt;p&gt;And the code for the get_SomeItem, and InitializeDataIfNotInitialized methods look something like this:&lt;/p&gt;

&lt;div class="SampleCode"&gt;public static SomeItem get_SomeItem() 
  &lt;br /&gt;{ 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ... 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DataLock.AcquireReaderLock(timeOut); 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; try 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; { 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; InitializeDataIfNotInitialized(); 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ... 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; finally 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; { 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DataLock.ReleaseReaderLock(); 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ... 

  &lt;br /&gt;} 

  &lt;br /&gt;

  &lt;br /&gt;private static void InitializeDataIfNotInitialized() 

  &lt;br /&gt;{ 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if (DataIsNotInitialized) 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; { 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; InitLock.AcquireWriterLock(timeOut); 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; LockCookie lockCookie = DataLock.UpgradeToWriterLock(timeOut); 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; try 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ... 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; finally 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DataLock.DowngradeFromWriterLock(ref lockCookie); 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; finally 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; { 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; InitLock.ReleaseWriterLock(); 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } 

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } 

  &lt;br /&gt;}&lt;/div&gt;

&lt;p&gt;So what happened here was that thread 11 and 68 both grabbed the DataLock ReaderLock in get_SomeItem.&lt;/p&gt;

&lt;p&gt;Then 68 grabbed the WriterLock for InitLock in InitializeDataIfNotInitialized, and now it is trying to upgrade the DataLock to a WriterLock but can’t do so since thread 11 has the ReaderLock on it.&lt;/p&gt;

&lt;p&gt;Thread 11 on the other hand now needs to grab the WriterLock on the InitLock but can’t do so because 68 owns it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a pretty typical deadlock situation, and the solution is to re-design the initialization methods so that this can never happen, but hopefully the walkthrough has given some insight into how you can debug these types of issues with SOSEX if you do run into them.&lt;/p&gt;

&lt;p&gt;
  &lt;br /&gt;Have a good one,&lt;/p&gt;

&lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10003088" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/Performance+issues+and+hangs/">Performance issues and hangs</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/SOSEX/">SOSEX</category></item><item><title>IIS and PAE</title><link>http://blogs.msdn.com/b/tess/archive/2010/04/27/iis-and-pae.aspx</link><pubDate>Tue, 27 Apr 2010 08:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10003036</guid><dc:creator>Tess1</dc:creator><slash:comments>12</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=10003036</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/04/27/iis-and-pae.aspx#comments</comments><description>&lt;P&gt;I recently got a question by one of my customers about PAE and IIS that I thought I’d share the answer to.&lt;/P&gt;
&lt;P&gt;Their environment looked something like this:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;32bit OS (Windows 2003)&lt;/LI&gt;
&lt;LI&gt;IIS 6 with multiple application pools, where each app pool hosts a number of applications&lt;/LI&gt;
&lt;LI&gt;~20 GB RAM&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;They were having problems with out of memory exceptions and also with paging under high load.&amp;nbsp; They knew a lot about their application and memory usage in general, so they knew what they were using the memory for and &lt;A href="http://blogs.msdn.com/tess/archive/2005/11/25/496898.aspx" target=_blank mce_href="http://blogs.msdn.com/tess/archive/2005/11/25/496898.aspx"&gt;why they got the OOMs&lt;/A&gt;, in this case, memory usage was relatively high per application (intentionally), but it remained stable so no leak.&amp;nbsp; With this in mind, we discussed solutions to the OOMs like splitting up the applications further etc. to avoid this.&amp;nbsp; Now their question was:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Is IIS 6 PAE aware, i.e. will we be using the full 20 GB of RAM or only 4 GB?&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I didn’t really know much about this so I consulted with one of our IIS escalation engineers &lt;A href="http://blogs.msdn.com/andrekl/" target=_blank mce_href="http://blogs.msdn.com/andrekl/"&gt;Andreas&lt;/A&gt; to get the scoop.&lt;/P&gt;
&lt;P&gt;The answer (which &lt;A href="http://misfitgeek.com/" target=_blank mce_href="http://misfitgeek.com/"&gt;Joe Stagner&lt;/A&gt; points out in this &lt;A href="http://forums.iis.net/t/1069409.aspx" target=_blank mce_href="http://forums.iis.net/t/1069409.aspx"&gt;forum thread&lt;/A&gt;) is that IIS 6 is not PAE aware, and since they are running on W2k3 x86 which will not manage memory above 4GB they will effectively only use 4 GB, leaving 16 GB unused.&amp;nbsp; (Unless of course they run other PAE aware apps on it, SQL server for example I believe is PAE aware).&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;STRONG&gt;Update:&lt;/STRONG&gt;&amp;nbsp; As per Dave's comments below the statement above seems to be incorrect,&amp;nbsp;if you have multiple&amp;nbsp;w3wp.exe processes they can&amp;nbsp;have a total workingset bigger than 4GB&amp;nbsp;(combined for all w3wp.exe processes) even on 32-bit if /PAE is on...&amp;nbsp; So in retrospect, I suspect that the above statement is talking about RAM used for HTTP.SYS etc.&amp;nbsp;&amp;nbsp; This should teach me to not blog about things that I'm only hearing 2nd hand:)&amp;nbsp; even still, it has been a good learning experience for me... and thanks to blogging about it, I now know more... Thanks Dave for commenting on it.&amp;nbsp;&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;On the other hand, a solution that would solve both the RAM question and the OOM issue is to move to a 64bit OS (preferably 2008 R2 because of improvements in the kernel, memory management and IO management).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Since it is a 64bit OS it can take advantage of all of the RAM, and even if you run 32bit IIS, you can then address 4 GB of Virtual Memory rather than 2 GB which means that there is more room for memory usage before an OOM (in this case since memory usage was stable but relatively high, that is exactly what we want).&amp;nbsp;&amp;nbsp; In fact, as Bernard Cheah also mentions in the same thread, there is no reason to move to 64bit IIS unless you need to, i.e. unless you need to use even more memory than the 4GB of virtual bytes that the 32bit process can address. &lt;/P&gt;
&lt;P&gt;Have a good one, &lt;BR&gt;Tess&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10003036" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/Memory+issues/">Memory issues</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category></item><item><title>New debugger extension for .NET (PSSCOR2)</title><link>http://blogs.msdn.com/b/tess/archive/2010/03/30/new-debugger-extension-for-net-psscor2.aspx</link><pubDate>Tue, 30 Mar 2010 14:31:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9987427</guid><dc:creator>Tess1</dc:creator><slash:comments>18</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=9987427</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/03/30/new-debugger-extension-for-net-psscor2.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/tom/archive/2010/03/29/new-debugger-extension-for-net-psscor2-released.aspx" target="_blank"&gt;Tom&lt;/a&gt; just blogged about a new debugger extension called PSSCor2, which is a superset to the SOS.dll extension that ships with the .net framework.&lt;/p&gt;  &lt;p&gt;PSSCor2.dll has been around for quite some time at Microsoft, and pretty much everyone debugging .net code with windbg within Microsoft is using this since it contains all the goodness of sos.dll plus a lot of special methods for asp.net and other technologies running on top of the .net framework.&amp;#160; The news now is that after a lot of hard work by Tom and Jon Langdon in the CLR team, it is finally released publicly, YAY!!!&lt;/p&gt;  &lt;p&gt;You can &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=5c068e9f-ebfe-48a5-8b2f-0ad6ab454ad4&amp;amp;displayLang=en" target="_blank"&gt;download it here&lt;/a&gt; and Tom promised to write some posts about the new commands so you might want to follow that… I will likely do the same later on as well…&lt;/p&gt;  &lt;p&gt;Just to name two of the commands in there that I use a lot:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;strong&gt;!dae&amp;#160; &lt;/strong&gt;(Dumps out all the exceptions on the .net heaps with callstacks)&lt;/p&gt;    &lt;p&gt;&lt;strong&gt;!aspxpages&amp;#160; &lt;/strong&gt;(Dumps out all the asp.net pages that are currently executing or have been executing recently, along with the thread they are running on, what the timeout is and how long they have been running… excellent stuff)&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt; Have a good one,&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9987427" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/General+debugging+tidbits/">General debugging tidbits</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item><item><title>Videos of developer sessions at Oredev (including mine on .net debugging)</title><link>http://blogs.msdn.com/b/tess/archive/2010/03/09/videos-of-developer-sessions-at-oredev-including-mine-on-net-debugging.aspx</link><pubDate>Tue, 09 Mar 2010 08:30:15 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9975356</guid><dc:creator>Tess1</dc:creator><slash:comments>13</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=9975356</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/03/09/videos-of-developer-sessions-at-oredev-including-mine-on-net-debugging.aspx#comments</comments><description>&lt;p&gt;Just a quick post to share a link to last years videos for the &lt;a href="http://oredev.org" target="_blank"&gt;Oredev&lt;/a&gt; developer conference&lt;/p&gt;  &lt;p&gt;&lt;a title="http://oredev.org/video" href="http://oredev.org/video"&gt;http://oredev.org/video&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Here is my &lt;a href="http://oredev.org/prod/oredev/site.nsf/docsbycodename/session?opendocument&amp;amp;sid=12201594012B3B23C125759200289A81&amp;amp;track=5EA1ADD99261C8A5C12575A500494952&amp;amp;day=3" target="_blank"&gt;.net debugging presentation&lt;/a&gt; where I show off some windbg + new VS.NET features and apart from all the good developer content, you might also want to check out Scott Hanselmans session on &lt;a href="http://oredev.org/prod/oredev/site.nsf/docsbycodename/session?opendocument&amp;amp;sid=F5513DE6A2AF7BE9C1257598006BB18F&amp;amp;track=71EDB5B62F6F88A2C12575A500499802&amp;amp;day=5" target="_blank"&gt;Information Overload and managing the workflow&lt;/a&gt; with some tips and tricks on how he manages twitter/facebook/email etc.&lt;/p&gt;  &lt;p&gt;Thank you to the organizers of Oredev for posting these,&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9975356" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item><item><title>Tool for generating DGML graphs showing why your object can’t be collected (VisualGCRoot)</title><link>http://blogs.msdn.com/b/tess/archive/2010/03/03/tool-for-generating-dgml-graphs-showing-why-your-object-can-t-be-collected-visualgcroot.aspx</link><pubDate>Wed, 03 Mar 2010 13:57:50 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9972145</guid><dc:creator>Tess1</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=9972145</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/03/03/tool-for-generating-dgml-graphs-showing-why-your-object-can-t-be-collected-visualgcroot.aspx#comments</comments><description>&lt;p&gt;Visual Studio.NET 2010 has a new feature that allows you to create nice directed graphs with a markup language called &lt;a href="http://blogs.msdn.com/camerons/archive/2009/01/26/directed-graph-markup-language-dgml.aspx" target="_blank"&gt;DGML&lt;/a&gt; (Directed Graph Markup Language).&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Visualizing object graphs with DGML&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.lovettsoftware.com/blogengine.net/" target="_blank"&gt;Chris Lovett&lt;/a&gt; wrote &lt;a href="http://www.lovettsoftware.com/blogengine.net/post/2010/01/15/Visualizing-Runtime-Object-Graphs.aspx" target="_blank"&gt;a tool that takes GCRoot output and transforms it to a DGML document&lt;/a&gt; so that you can see the roots of an object in a more visual way, and finally &lt;a href="http://blogs.msdn.com/mohamedg" target="_blank"&gt;Mohamed Mahmoud&lt;/a&gt; went one step further and made a &lt;a href="http://blogs.msdn.com/mohamedg/archive/2010/03/02/visual-gcroot-via-dgml.aspx" target="_blank"&gt;debugger extension&lt;/a&gt; that does this for you directly.&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;The debugger extension is called VGCRoot and you can get the extension, and some instructions and demos for it &lt;a href="http://blogs.msdn.com/mohamedg/archive/2010/03/02/visual-gcroot-via-dgml.aspx" target="_blank"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The VGCRoot extensions&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If you are looking at a memory dump in windbg and try to figure out why your object is still sticking around, collection after collection, you can use the sos extension to run a command called !GCRoot which will give you a textual representation of how your object is rooted.&amp;#160; &lt;/p&gt;  &lt;p&gt;In other words, it will give you several “stacks” linking your object all the way up to one or more “roots”, where the roots may be threads, static objects, reference counted objects and until you break the chain between the root and your object your object can’t be garbage collected.&lt;/p&gt;  &lt;p&gt;A typical root chain looks something like the one below taken from one of &lt;a href="http://blogs.msdn.com/tess/archive/2007/08/13/asp-net-memory-investigation.aspx" target="_blank"&gt;my memory investigation posts&lt;/a&gt;&lt;/p&gt;  &lt;pre class="debug"&gt;0:000&amp;gt; !gcroot &lt;strong&gt;00000000800dfb98&lt;/strong&gt; &lt;br /&gt;... DOMAIN(000000000017E210):HANDLE(Strong):4b41308:Root: 00000000c0020990(System.Threading._TimerCallback)-&amp;gt; &lt;br /&gt;00000000c0020908(System.Threading.TimerCallback)-&amp;gt; &lt;br /&gt;00000000c001b530(System.Web.Caching.CacheExpires)-&amp;gt; &lt;br /&gt;00000000c001b568(System.Object[])-&amp;gt; &lt;br /&gt;00000000c001bef8(System.Web.Caching.ExpiresBucket)-&amp;gt; &lt;br /&gt;00000001008fbf40(System.Web.Caching.ExpiresPage[])-&amp;gt; &lt;br /&gt;00000001008fbff8(System.Web.Caching.ExpiresEntry[])-&amp;gt; &lt;br /&gt;000000010001ebd8(&lt;strong&gt;System.Web.Caching.CacheEntry&lt;/strong&gt;)-&amp;gt; &lt;br /&gt;000000010001eb98(&lt;strong&gt;System.Web.SessionState.InProcSessionState&lt;/strong&gt;)-&amp;gt; &lt;br /&gt;00000000800dd340(System.Web.SessionState.SessionStateItemCollection)-&amp;gt; &lt;br /&gt;00000000800dd3f0(System.Collections.Hashtable)-&amp;gt; &lt;br /&gt;00000000802fe7e0(System.Collections.Hashtable+bucket[])-&amp;gt; &lt;br /&gt;&lt;strong&gt;00000000800e09e8&lt;/strong&gt;(System.Collections.Specialized.NameObjectCollectionBase+NameObjectEntry)-&amp;gt; &lt;br /&gt;&lt;strong&gt;00000000800dfb98(System.Xml.XmlDocument)&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;In this case we have an XmlDocument that can’t be garbage collected because it is stored in session scope so until it is removed from session scope (breaking the link between XmlDocument and SessionStateItemCollection)&amp;#160; it can’t be garbage collected.&lt;/p&gt;

&lt;p&gt;With !VGcRoot we can now get all the roots in a DGML file that we can open up in Visual Studio .NET 2010, making this much easier to digest.&lt;/p&gt;

&lt;p&gt;You run it from windbg using !vgcroot /do /fields &amp;lt;objectaddress&amp;gt; [&amp;lt;DGML File path&amp;gt;] and the resulting graph (in this case for a Form object) looks like this.&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/mohamedg/WindowsLiveWriter/VisualGCRootviaDGML_184E/Field%20Names_6.png"&gt;&lt;img title="Field Names" border="0" alt="Field Names" src="http://blogs.msdn.com/blogfiles/mohamedg/WindowsLiveWriter/VisualGCRootviaDGML_184E/Field%20Names_thumb_2.png" width="644" height="345" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we can see for example that the Form is linked by a UserPreferenceChangedEventHandler through the _target member variable, in other words, one reason that the Form can’t be garbage collected is because it is handling a UserPreferenceChangedEvent. &lt;/p&gt;

&lt;p&gt;I will probably be showing this off more in context in future memory investigation posts but just wanted to show off the extension so that you can start playing around with it.&amp;#160; Be sure to check out his post to see other stuff you can do with the graph once you have it generated.&lt;/p&gt;

&lt;p&gt;Have a good one,
  &lt;br /&gt;(and thanks to Mohamed for writing the extension)&lt;/p&gt;

&lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9972145" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/Memory+issues/">Memory issues</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/General+debugging+tidbits/">General debugging tidbits</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item><item><title>New commands in SOS for .NET 4.0 Part 1</title><link>http://blogs.msdn.com/b/tess/archive/2010/03/01/new-commands-in-sos-for-net-4-0-part-1.aspx</link><pubDate>Mon, 01 Mar 2010 15:21:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9970876</guid><dc:creator>Tess1</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=9970876</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/03/01/new-commands-in-sos-for-net-4-0-part-1.aspx#comments</comments><description>&lt;p&gt;My friend and fellow debugger Brian at &lt;a href="http://Kodehoved.dk"&gt;http://Kodehoved.dk&lt;/a&gt; recently wrote a couple of posts on news with sos for .NET framework 4.0 (in Danish)&lt;/p&gt;  &lt;p&gt;&lt;a title="http://kodehoved.dk/?p=277" href="http://kodehoved.dk/?p=277" target="_blank"&gt;New SOS Commands in .NET 4&lt;/a&gt;     &lt;br /&gt;&lt;a title="http://kodehoved.dk/?p=323" href="http://kodehoved.dk/?p=323" target="_blank"&gt;More debugging news in CLR 4&lt;/a&gt;     &lt;br /&gt;    &lt;br /&gt;Since Danish, although a beautiful language is probably foreign to most of you I figured I’d write a summary of the new commands in English and add some comments of my own.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Loading sos for .NET 4.0&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;As in 2.0 you will find sos.dll in the framework directory so you can load it in windbg or cdb using the full path&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;.load C:\Windows\Microsoft.NET\Framework\v4.0.30128\sos.dll&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;You can also use the short hand .loadby method but since the name of the core dll has changed in 4.0, you will no longer load it using .loadby sos mscorwks, instead you can now load it using&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;.loadby sos clr&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;SOS now takes advantage of windbg’s DML feature making it easier to debug&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;DML stands for Debugger Markup Language and allows commands to emit hyper links in the command output.&amp;#160; For example, in the !threads command output there are DML links for the OSID column, the State column and the Domain column.&amp;#160; &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;Clicking on the first link in the OSID column (below) for example would execute the command ~~[ff4]s which would set the context to that thread.&amp;#160; Clicking on a link in the state column would show you the !ThreadState output so you can see exactly what the state 8220 means etc.&amp;#160; This is very handy as you don’t have to remember all the various commands.&lt;/p&gt;  &lt;pre class="debug"&gt;0:042&amp;gt; !threads
&lt;br /&gt;ThreadCount:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 25
&lt;br /&gt;UnstartedThread:&amp;#160; 0
&lt;br /&gt;BackgroundThread: 17
PendingThread:&amp;#160;&amp;#160;&amp;#160; 0
&lt;br /&gt;DeadThread:&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 8
&lt;br /&gt;Hosted Runtime:&amp;#160;&amp;#160; no
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; PreEmptive&amp;#160;&amp;#160; GC Alloc&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Lock
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ID&amp;#160; OSID ThreadOBJ&amp;#160;&amp;#160;&amp;#160; State GC&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Context&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Domain&amp;#160;&amp;#160; Count APT Exception
&lt;br /&gt;&amp;#160; 11&amp;#160;&amp;#160;&amp;#160; 1&amp;#160;&amp;#160; &lt;font color="#0080ff"&gt;ff4&lt;/font&gt; 012923d0&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0080ff"&gt;8220&lt;/font&gt; Enabled&amp;#160; 00000000:00000000 &lt;font color="#0080ff"&gt;01289450&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 Ukn
&lt;br /&gt;&amp;#160; 18&amp;#160;&amp;#160;&amp;#160; 2&amp;#160; &lt;font color="#0080ff"&gt;1dbc&lt;/font&gt; 0129a3a0&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0080ff"&gt;b220&lt;/font&gt; Enabled&amp;#160; 00000000:00000000 &lt;font color="#0080ff"&gt;01289450&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 MTA (Finalizer)
&lt;br /&gt;&amp;#160; 20&amp;#160;&amp;#160;&amp;#160; 4&amp;#160; &lt;font color="#0080ff"&gt;114c&lt;/font&gt; 012b1650&amp;#160;&amp;#160; &lt;font color="#0080ff"&gt;8008220&lt;/font&gt; Enabled&amp;#160; 00000000:00000000 &lt;font color="#0080ff"&gt;01289450&lt;/font&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0 MTA (Threadpool Completion Port)
&lt;br /&gt;…&lt;/pre&gt;

&lt;p&gt;In order to turn on DML in your debugger you can run the command .prefer_dml 1&amp;#160; or if you only want to enable it for a specific command you can run !threads /D for example.&lt;/p&gt;

&lt;p&gt;DML is used in many places in sos… in !dumpheap –stat you get links for each type that executed !dumpheap –mt &amp;lt;methodtable&amp;gt; so that you can see all the objects of that type, and the !dumpobj output emits links so that you can easily click and look at the member variables in more detail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New commands&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To find a list of all the commands sos has to offer you can run !help in windbg (if sos is the last extension that was loaded) and to get help (including examples) for a specific command you can run !help &amp;lt;command&amp;gt;,&amp;#160; for example !help DumpObj.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Understanding why an object is not garbaqe collected (!GCWhere, !FindRoots !HandleCLRN)&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Previously we only had the !GCRoot command which was nice for strong references but didn’t work well when your object was not “really” rooted.&amp;#160; &lt;/p&gt;

&lt;p&gt;Running !GCRoot &amp;lt;object address&amp;gt; will tell us the root chain of any rooted object, in other words, if your object is not being collected because it is linked, directly or indirectly from a thread, a static object, a ref counted object etc. it will give you this link chain so that you can determine which links you need to break in order to make your object collectable.&lt;/p&gt;

&lt;p&gt;Sometimes however you may be troubleshooting an issue where your object is not necessarily rooted but it still doesn’t get collected.&amp;#160; The answer to why it is not collected is either that the generation your object is in has yet to be collected, or it is rooted by an object in a higher generation, and that it is waiting for this object to be collected.&lt;/p&gt;

&lt;p&gt;If you are live debugging your application with Windbg you can now find out why your object is not collected by going through this sequence.&lt;/p&gt;

&lt;p&gt;1. Find out which generation your object is in by running !GCWhere&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre class="debug"&gt;0:030&amp;gt; !GCWhere 057cca48
&lt;br /&gt;Address&amp;#160; Gen Heap segment&amp;#160; begin&amp;#160;&amp;#160;&amp;#160; allocated size
&lt;br /&gt;057cca48&amp;#160;&amp;#160; &lt;strong&gt;2&lt;/strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1&amp;#160;&amp;#160;&amp;#160;&amp;#160; 056f0000&amp;#160;&amp;#160; 056f0038&amp;#160;&amp;#160; 065c8a04&amp;#160;&amp;#160;&amp;#160; 0x40(64)&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;!GCWhere tells you what generation your object currently belongs to, as well as some info about the segment in which it is allocated. In this case our object is in Gen 2 on Heap 1.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;2. Turn on CLR GC Notifications&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Next we run !HandleCLRN to tell the debugger to stop on GC CLR Notifications&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;3. Enable break on GC&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;!FindRoots –gen 2 tells the debugger to stop on the next Gen 2 collection, so we issue this command and hit g (for go) to allow the debugger to continue executing&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;pre class="debug"&gt;0:030&amp;gt; !FindRoots -gen 2   &lt;br /&gt;0:030&amp;gt; g&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;4. Find the roots for your object&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When the garbage collection occurs the following is displayed in windbg and the debugger stops&lt;/p&gt;

  &lt;p&gt;(21d0.1a74): CLR notification exception - code e0444143 (first chance) 
    &lt;br /&gt;CLR notification: GC - Performing a gen 2 collection. Determined surviving objects...&lt;/p&gt;

  &lt;p&gt;Now we can run !FindRoots &amp;lt;object address&amp;gt; to determine what is holding on to the object.&amp;#160; This might be a root graph similar to what you see with !gcroot if the object is strongly rooted.&lt;/p&gt;

  &lt;p&gt;It might also be something like: &lt;/p&gt;

  &lt;pre class="debug"&gt;0:016&amp;gt; !FindRoots 05e54f4c
&lt;br /&gt;Object 05e54f4c will survive this collection:
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; gen(0x5e54f4c) = 2 &amp;gt; 1 = condemned generation.&lt;/pre&gt;

  &lt;p&gt;… if you do findroots for an object in a higher generation than the one you stopped on… or something like &lt;/p&gt;

  &lt;pre class="debug"&gt;0:002&amp;gt; !findroots 06808094 
&lt;br /&gt;older generations::Root:&amp;#160; 068012f8(AAA.Test+a)-&amp;gt;
&lt;br /&gt;&amp;#160; 06808094(AAA.Test+b)&lt;/pre&gt;
… if your object is being held on to by an object in an older generation 

  &lt;p&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;There are plenty of other new commands as well but to avoid making this post all too long, I will continue with the other commands in my next post instead.&lt;/p&gt;

&lt;p&gt;Until then,&lt;/p&gt;

&lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9970876" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item><item><title>It’s time for TechDays Sweden again…</title><link>http://blogs.msdn.com/b/tess/archive/2010/02/17/it-s-time-for-techdays-sweden-again.aspx</link><pubDate>Wed, 17 Feb 2010 10:24:47 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9964948</guid><dc:creator>Tess1</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=9964948</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/02/17/it-s-time-for-techdays-sweden-again.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://dynamicsuser.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/mark_5F00_brummel/2260.TechDays.jpg"&gt;&lt;img style="margin: 0px 25px 0px 0px; display: inline" border="0" alt="" align="left" src="http://dynamicsuser.net/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/mark_5F00_brummel/2260.TechDays.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;March 23rd and 24th I will be presenting at TechDays Sweden in Örebro.&amp;#160; &lt;/p&gt;  &lt;p&gt;The agenda for my session is not set in stone yet but the plan is to talk about debugging .NET production type issues as usual (Performance, Memory, Crashes, Exceptions etc.) since that is what I know best.&lt;/p&gt;  &lt;p&gt;I will be talking about them both from a developers perspective, using some of the nice features in Visual Studio .NET 2010 like dump debugging, profiling, and perhaps IntelliTrace as well as discuss options for debugging issues that occur in environments where you don’t have Visual Studio, concentrating on WinDbg/Debug Diag and other tools that lend themselves well for production environment debugging. &lt;/p&gt;  &lt;p&gt;Hope to see you there,&lt;/p&gt;  &lt;p&gt;Tess&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dynamicsuser.net/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/mark_5F00_brummel/2260.TechDays.jpg"&gt;&amp;#160;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9964948" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item><item><title>System.Configuration.ConfigurationErrosException “Unrecognized element ‘setting’” and other unrecognized elements</title><link>http://blogs.msdn.com/b/tess/archive/2010/02/16/system-configuration-configurationerrosexception-unrecognized-element-setting-and-other-unrecognized-elements.aspx</link><pubDate>Tue, 16 Feb 2010 14:47:41 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9964295</guid><dc:creator>Tess1</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=9964295</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/02/16/system-configuration-configurationerrosexception-unrecognized-element-setting-and-other-unrecognized-elements.aspx#comments</comments><description>&lt;p&gt;If you have a .NET configuration file with multiple &amp;lt;setting&amp;gt; elements, you may get the following exception:&lt;/p&gt;  &lt;pre class="debug"&gt;Unhandled Exception: System.Configuration.ConfigurationErrorsException: Unrecognized element 'setting'. (F:\MyApp\bin\Debug\MyApp.exe.config line 11)&amp;#160; at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult) 
&lt;br /&gt;&amp;#160;&amp;#160; at System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult, Boolean getLkg, Boolean getRuntimeObject, Object&amp;amp; result, Object&amp;amp; resultRuntimeObject) 
&lt;br /&gt;&amp;#160;&amp;#160; at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object&amp;amp; result, Object&amp;amp; resultRuntimeObject) 
&lt;br /&gt;&amp;#160;&amp;#160; at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object&amp;amp; result, Object&amp;amp; resultRuntimeObject) 
&lt;br /&gt;&amp;#160;&amp;#160; at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object&amp;amp; result, Object&amp;amp; resultRuntimeObject) 
&lt;br /&gt;&amp;#160;&amp;#160; at System.Configuration.BaseConfigurationRecord.GetSection(String configKey) 
&lt;br /&gt;&amp;#160;&amp;#160; at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName) 
&lt;br /&gt;&amp;#160;&amp;#160; at System.Configuration.ConfigurationManager.GetSection(String sectionName) 
&lt;br /&gt;&amp;#160;&amp;#160; at System.Configuration.ClientSettingsStore.ReadSettings(String sectionName, Boolean isUserScoped) 
&lt;br /&gt;&amp;#160;&amp;#160; at System.Configuration.LocalFileSettingsProvider.GetPropertyValues(SettingsContext context, SettingsPropertyCollection properties) 
&lt;br /&gt;&amp;#160;&amp;#160; at System.Configuration.SettingsBase.GetPropertiesFromProvider(SettingsProvider provider) 
&lt;br /&gt;...&lt;/pre&gt;

&lt;p&gt;This happens if you have a configuration section with multiple &amp;lt;setting&amp;gt; elements like in this example&lt;/p&gt;

&lt;div class="SampleCode"&gt;&amp;lt;setting name=&amp;quot;Setting1&amp;quot; serializeAs=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;value&amp;gt;Setting1&amp;lt;/value&amp;gt;&amp;lt;/setting&amp;gt; 
  &lt;br /&gt;&amp;lt;setting name=&amp;quot;Setting2&amp;quot; serializeAs=&amp;quot;String&amp;quot;&amp;gt;&amp;lt;value&amp;gt;Setting2&amp;lt;/value&amp;gt;&amp;lt;/setting&amp;gt; &lt;/div&gt;

&lt;p&gt;and you keep the whole &amp;lt;setting&amp;gt; element on one line.&lt;/p&gt;

&lt;p&gt;To get rid of this error, split the &amp;lt;setting&amp;gt; element on multiple lines, or add any kind of whitespace after the &amp;lt;/value&amp;gt; tag like this:&lt;/p&gt;

&lt;div class="SampleCode"&gt;&amp;lt;setting name=&amp;quot;Setting1&amp;quot; serializeAs=&amp;quot;String&amp;quot;&amp;gt; 
  &lt;br /&gt;&amp;#160;&amp;#160; &amp;lt;value&amp;gt;Setting1&amp;lt;/value&amp;gt; 

  &lt;br /&gt;&amp;lt;/setting&amp;gt; 

  &lt;br /&gt;&lt;/div&gt;

&lt;p&gt;Similar Unrecognized element errors will occur if you use an expanded &amp;lt;clear&amp;gt;&amp;lt;/clear&amp;gt; tag instead of &amp;lt;clear/&amp;gt;.&amp;#160; In that case you may get an Unrecognized element ‘add’ for example if &amp;lt;add&amp;gt; is the first element that appears after the expanded &amp;lt;clear&amp;gt;&amp;lt;/clear&amp;gt; tag.&amp;#160;&amp;#160; The resolution here is to simply change &amp;lt;clear&amp;gt;&amp;lt;/clear&amp;gt; to its short form &amp;lt;clear/&amp;gt;&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://connect.microsoft.com/VisualStudio/feedback/details/508146/valid-rolemanager-app-config-setting-fails-to-parse"&gt;&lt;font color="#333333"&gt;We have &lt;/font&gt;&lt;/a&gt;received a few reports about this issue &lt;/p&gt;

&lt;p&gt;&lt;a href="https://connect.microsoft.com/VisualStudio/feedback/details/508146/valid-rolemanager-app-config-setting-fails-to-parse"&gt;https://connect.microsoft.com/VisualStudio/feedback/details/508146/valid-rolemanager-app-config-setting-fails-to-parse&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://connect.microsoft.com/VisualStudio/feedback/details/352591/configurationerrorsexception-thrown-on-service-start-when-no-whitespace-between-value-and-setting"&gt;http://connect.microsoft.com/VisualStudio/feedback/details/352591/configurationerrorsexception-thrown-on-service-start-when-no-whitespace-between-value-and-setting&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;but because there are very simple workarounds to both issues, and thus the potential problems that can arise from changing the code are bigger than the gain from fixing them for the clients reporting the issue, there hasn’t been a fix for this as of yet.&lt;/p&gt;

&lt;p&gt;If for some reason you can not use the workarounds given above you can either vote up the connect bug to give it higher priority for future releases or contact support to help find a solution that fits your needs.&lt;/p&gt;

&lt;p&gt;Laters,&lt;/p&gt;

&lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9964295" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category></item><item><title>MSDN Radio (Swedish) - Tess Corner</title><link>http://blogs.msdn.com/b/tess/archive/2010/01/15/msdn-radio-swedish-tess-corner.aspx</link><pubDate>Fri, 15 Jan 2010 12:04:48 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9948899</guid><dc:creator>Tess1</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=9948899</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/01/15/msdn-radio-swedish-tess-corner.aspx#comments</comments><description>&lt;p&gt;MSDN Radio is a Swedish MSDN podcast that is &lt;a href="http://buzzfrog.blogs.com/"&gt;Dag König&lt;/a&gt; puts together every other week.&amp;#160; The show contains a number of different segments and is usually pretty fun to listen to.&lt;/p&gt;  &lt;p&gt;Starting this week, and hopefully every other week or so during the spring, I will have a 5-15 min segment on the show called Tess Corner where I’ll be talking about current ASP.NET and other .net issues or something special I’m working on.&amp;#160; &lt;/p&gt;  &lt;p&gt;In the first episode posted here &lt;a title="http://channel9.msdn.com/posts/buzzfrog/MSDN-Radio-11-Jan--Tess-Corner/" href="http://channel9.msdn.com/posts/buzzfrog/MSDN-Radio-11-Jan--Tess-Corner/"&gt;http://channel9.msdn.com/posts/buzzfrog/MSDN-Radio-11-Jan--Tess-Corner/&lt;/a&gt; I talk about debugging .NET apps with IntelliTrace in Visual Studio.NET 2010.&lt;/p&gt;  &lt;p&gt;Check out the other MSDN episodes on &lt;a title="http://channel9.msdn.com/tags/MSDN+Radio/" href="http://channel9.msdn.com/tags/MSDN+Radio/"&gt;http://channel9.msdn.com/tags/MSDN+Radio/&lt;/a&gt; (also in Swedish) and if you listen to the show and want to hear about something special, feel free to post me a comment.&lt;/p&gt;  &lt;p&gt;Have a good one&amp;#160; &lt;br /&gt;Tess &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9948899" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item><item><title>Debugging Native memory leaks with Debug Diag 1.1</title><link>http://blogs.msdn.com/b/tess/archive/2010/01/14/debugging-native-memory-leaks-with-debug-diag-1-1.aspx</link><pubDate>Thu, 14 Jan 2010 13:21:02 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9948358</guid><dc:creator>Tess1</dc:creator><slash:comments>27</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=9948358</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2010/01/14/debugging-native-memory-leaks-with-debug-diag-1-1.aspx#comments</comments><description>&lt;p&gt;I often get questions about debugging native memory leaks. In other words, cases where you have high memory usage in your application but you can see that .net memory usage is not all that high.&lt;/p&gt;  &lt;p&gt;Recently I was helping out on such a case and this post details both generally how you go about troubleshooting these issues as well as what troubleshooting steps we went through in this particular case.&lt;/p&gt;  &lt;p&gt;Essentially you would go through these steps to troubleshoot a native memory leak:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1. Find out if your memory usage / leak is mostly .net memory or native memory      &lt;br /&gt;2. If it is native memory that is “leaking”, use a tool like debug diag 1.1. to track allocations and deallocations       &lt;br /&gt;3. Look at the main allocators and the stacks associated with the biggest chunks of allocations to determine who is making the allocations and why the memory is not released.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;1. Find out if your memory usage / leak is mostly .net memory or native memory&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;There are various ways to find out if your memory usage is mostly .net or native.&amp;#160; &lt;br /&gt;    &lt;br /&gt;&lt;strong&gt;&lt;em&gt;Using perfmon to determine where your memory is going&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;The best way is probably to use performance monitor and collect a log over the lifetime of the process that is leaking with at least the following counters for the specific process (note that _total or _global counters are not very helpful here)&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;.NET CLR Memory/#Bytes in all heaps &lt;/li&gt;    &lt;li&gt;Process/Private Bytes &lt;/li&gt;    &lt;li&gt;Process/Virtual Bytes &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Simplified, Virtual Bytes is the memory that the process reserves, Private Bytes is how much of that the memory that the process actually uses and #Bytes in all Heaps is how much of the Private Bytes goes to memory stored on the .NET GC heap.&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;This is not entirely accurate if you want to be a nitpicker about what Private Bytes really means, but it is accurate enough for the purposes of troubleshooting a memory issue.&lt;/p&gt;  &lt;p&gt;You can create such a logfile by following these steps&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1. Open perfmon (Performance under Administrative Tools)      &lt;br /&gt;2. Under Performance Logs and Alerts, right-click Counter Logs and choose New Log Settings, give it a name and click ok.       &lt;br /&gt;3. Click “Add Counters” and choose the counters above.&amp;#160; The best way to make sure you get the instance counters, rather than _Total and _Global is to choose All instances       &lt;br /&gt;4. Once you have added the counters, fill in the name of an administrator in the Run As: box and fill out the password.&amp;#160; (This is important if you are logging for w3wp.exe for example as some counters are only available when you run the log as an admin)       &lt;br /&gt;5. The counter log will now be running, collecting data (shows up as green in the counter logs view) but you can start and stop it at any time.&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Once you have this performance log you can now compare these values and specifically compare the trend and amounts for Private Bytes and #Bytes in all heaps to see if your memory leak is native (non .net) or .net related.&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;If your memory growth/usage is mostly .net, have a look through some of the other posts on debugging memory issues to check into how to troubleshoot them.&lt;/p&gt;  &lt;p&gt;If however # Bytes in all heaps is pretty moderate you should continue reading from step 2 and on.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;em&gt;Getting memory usage info from a dump file &lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;If you got a memory dump of the process but “forgot” to create a perfmon log with the counters described above, you can find out from the memory dump where the memory is used.&lt;/p&gt;  &lt;p&gt;Open the memory dump in Windbg (File/Open Crash Dump) and run the command !address –summary&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Note: The output might differ with different versions of windbg&lt;/p&gt; &lt;/blockquote&gt;  &lt;pre class="debug"&gt;0:000&amp;gt; !address -summary 
-------------------- Usage SUMMARY --------------------------&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;TotSize   (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; KB)&amp;#160;&amp;#160; Pct(Tots) Pct(Busy)&amp;#160;&amp;#160; Usage&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;1bf2f000  (&amp;#160; 457916) : 21.84%&amp;#160;&amp;#160;&amp;#160; 23.18%&amp;#160;&amp;#160;&amp;#160; : RegionUsageIsVAD&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;772b000   (&amp;#160; 122028) : 05.82%&amp;#160;&amp;#160;&amp;#160; 00.00%&amp;#160;&amp;#160;&amp;#160; : RegionUsageFree&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;5881000   (&amp;#160;&amp;#160; 90628) : 04.32%&amp;#160;&amp;#160;&amp;#160; 04.59%&amp;#160;&amp;#160;&amp;#160; : RegionUsageImage&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;22bc000   (&amp;#160;&amp;#160; 35568) : 01.70%&amp;#160;&amp;#160;&amp;#160; 01.80%&amp;#160;&amp;#160;&amp;#160; : RegionUsageStack&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;8b000     (&amp;#160;&amp;#160;&amp;#160;&amp;#160; 556) : 00.03%&amp;#160;&amp;#160;&amp;#160; 00.03%&amp;#160;&amp;#160;&amp;#160; : RegionUsageTeb&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;54dcb000  ( 1390380) : 66.30%&amp;#160;&amp;#160;&amp;#160; 70.40%&amp;#160;&amp;#160;&amp;#160; : RegionUsageHeap&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;0         (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0) : 00.00%&amp;#160;&amp;#160;&amp;#160; 00.00%&amp;#160;&amp;#160;&amp;#160; : RegionUsagePageHeap&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;1000      (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 4) : 00.00%&amp;#160;&amp;#160;&amp;#160; 00.00%&amp;#160;&amp;#160;&amp;#160; : RegionUsagePeb&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;1000      (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 4) : 00.00%&amp;#160;&amp;#160;&amp;#160; 00.00%&amp;#160;&amp;#160;&amp;#160; : RegionUsageProcessParametrs&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;1000      (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 4) : 00.00%&amp;#160;&amp;#160;&amp;#160; 00.00%&amp;#160;&amp;#160;&amp;#160; : RegionUsageEnvironmentBlock&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;   Tot: 7fff0000 (2097088 KB) Busy: 788c5000 (1975060 KB) 
-------------------- Type SUMMARY --------------------------&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;TotSize   (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; KB)&amp;#160;&amp;#160; Pct(Tots)&amp;#160; Usage&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;772b000   (&amp;#160; 122028) : 05.82%&amp;#160;&amp;#160; : &amp;lt;free&amp;gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;5ee5000   (&amp;#160;&amp;#160; 97172) : 04.63%&amp;#160;&amp;#160; : MEM_IMAGE&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;5fb000    (&amp;#160;&amp;#160;&amp;#160; 6124) : 00.29%&amp;#160;&amp;#160; : MEM_MAPPED&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;723e5000  ( 1871764) : 89.26%&amp;#160;&amp;#160; : MEM_PRIVATE &lt;p&gt;&lt;/p&gt;-------------------- State SUMMARY --------------------------
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; TotSize (&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; KB)&amp;#160;&amp;#160; Pct(Tots)&amp;#160; Usage
&lt;br /&gt;&amp;#160;&amp;#160; 5a1e4000 ( 1476496) : 70.41%&amp;#160;&amp;#160; : MEM_COMMIT
&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 772b000 (&amp;#160; 122028) : 05.82%&amp;#160;&amp;#160; : MEM_FREE
&lt;br /&gt;&amp;#160;&amp;#160; 1e6e1000 (&amp;#160; 498564) : 23.77%&amp;#160;&amp;#160; : MEM_RESERVE &lt;br /&gt;
&lt;p&gt;Largest free region: Base 06b10000 - Size 02170000 (34240 KB)&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;From this we can deduce a couple of things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;MEM_COMMIT&lt;/em&gt;&lt;/strong&gt; is the committed memory, this should be fairly close to &lt;strong&gt;&lt;em&gt;Private Bytes&lt;/em&gt;&lt;/strong&gt;.&amp;#160; In this particular case this process was using almost 1.4 GB of memory 

  &lt;br /&gt;

  &lt;br /&gt;&lt;strong&gt;&lt;em&gt;MEM_RESERVE + MEM_COMMIT&lt;/em&gt; &lt;/strong&gt;is the total reserved bytes, so this is &lt;strong&gt;&lt;em&gt;Virtual Bytes&lt;/em&gt;&lt;/strong&gt; in Perfmon.&amp;#160; Here we can see that the process has reserved about 500 MB more than it committed, i.e. 500 MB more than it actually used.&amp;#160; This is fairly normal for a big process as for example it will reserve chunks of memory for the .NET GC heap that it might not use all of, and there is some overhead reservations for dlls etc. as well as other types of reservations.&lt;/p&gt;

&lt;p&gt;From the &lt;strong&gt;&lt;em&gt;Usage SUMMARY&lt;/em&gt;&lt;/strong&gt; section we can see where the reservations were made. RegionUsageIsVAD for example is allocations made with VirtualAlloc (.NET GC Heap for example goes here).&amp;#160; RegionUsageIsImage is memory used for dlls and executables.&amp;#160; RegionUsageStack is stack space for the threads, and RegionUsageHeap is for allocations on the NT Heaps.&amp;#160;&amp;#160;&amp;#160; In this particular case we can see that most of the reservations (66.3%) and the commits (70.4%) are done on the NT heaps.&amp;#160;&amp;#160;&amp;#160; This is typical for a native leak.&amp;#160; If it was high .NET memory usage we would see a lot of the memory used for RegionUsageIsVAD.&lt;/p&gt;

&lt;p&gt;If you want to learn more about the !address –summary output, check out the help in windbg for the command or check the &lt;a href="http://blogs.msdn.com/tess/archive/2008/02/20/net-debugging-demos-lab-3-memory-review.aspx"&gt;lab 3 review&lt;/a&gt; where I have described some of this in more detail.&lt;/p&gt;

&lt;p&gt;We can also check out exactly how much memory is used for .net objects by loading up sos in windbg (.loadby sos mscorwks) and then run !eeheap –gc.&amp;#160; I have truncated the output below to just show the important parts&lt;/p&gt;

&lt;pre class="debug"&gt;0:000&amp;gt; !eeheap -gc&lt;br /&gt;Number of GC Heaps: 8&lt;br /&gt;------------------------------&lt;br /&gt;…&lt;br /&gt;------------------------------&lt;br /&gt;GC Heap Size&amp;#160;&amp;#160; 0x84680(&lt;strong&gt;542,336&lt;/strong&gt;)&lt;/pre&gt;

&lt;p&gt;In this process we were using an incredibly small amount of .NET object, ~540k, so we can say for sure here that the leak is native.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. If it is native memory that is “leaking”, use a tool like debug diag 1.1. to track allocations and deallocations &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next step in the process is to collect data about the leak and for this we can use&amp;#160; &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&amp;amp;displaylang=en"&gt;Debug Diag 1.1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The download page gives the instructions needed, in order to start monitoring for leaks&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;To debug memory and handle usage, use one of the following: 
    &lt;br /&gt;

    &lt;br /&gt;1. Create a leak rule against the process in question. The leak monitoring feature will track memory allocations inside the process. Tracking is implemented by injecting a DLL (leaktrack.dll) into the specified process and monitoring memory allocations over time. When configuring a memory and handle leak rule, you can specify memory dump generation based on time or memory usage. 

    &lt;br /&gt;2. Using the “processes” view, right-click the process in question and select the “monitor for leaks” option. When the process has grown to the suspected problem size, manually dump the process by right-clicking on the same process in the processes view and choosing the “Create Full Userdump” option.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A few notes about this:&amp;#160; Leak tracking will only record leaks that occur while leak tracking is turned on.&amp;#160; I know this may sound obvious but I am mentioning this because we often get leak track dumps that span only over a small period of time and does not include the allocations, because people have started leaktracking when memory was already high.&lt;/p&gt;

&lt;p&gt;The other thing that is important to note is that by default, leak tracking will start recording stacks 15 minutes after leak tracking begins.&amp;#160; This is to allow for an app to do the initial allocations like build up the cache, start up the form etc. before starting to monitor, so that the tracking only contains the relevant leak info.&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_6.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_thumb_2.png" width="404" height="331" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’ve found that the best way to get all the info i need is to start up the application and let it initialize things, and then run leak tracking with the checkbox to record call stacks immediately checked.&amp;#160; (This is under tools/options in debug diag)&lt;/p&gt;

&lt;p&gt;When you start Debug Diag you will be greeted with the Select Rule Type and here you choose Memory and Handle Leak and follow the steps above.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_2.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_thumb.png" width="404" height="354" /&gt;&lt;/a&gt;&amp;#160; &lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;You can choose to have debug diag automatically generate dumps when the process reaches a certain size, but the easiest is probably to just choose the Memory and Handle Leak rule, and click next next finish, and then right-click on the process in the processes tab once the leak has manifested itself to get a memory dump (as per the original instructions.&lt;/p&gt;

&lt;p&gt;
  &lt;br /&gt;&lt;strong&gt;3. Look at the main allocators and the stacks associated with the biggest chunks of allocations to determine who is making the allocations and why the memory is not released.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ok, so now we have the memory dump containing the information about the leak.&amp;#160; The cool thing here is that Debug Diag has an analysis feature that analyzes the dump for you.&lt;/p&gt;

&lt;p&gt;Under the Advanced Analysis tab in Debug Diag, select the MemoryAnalysis.asp script and click add data files to add your memory dump, then click on “Start Analysis”.&lt;/p&gt;

&lt;p&gt;This will generate a report that will pop up in your browser showing you information about all the allocations etc.&lt;/p&gt;

&lt;p&gt;The first part of the report is an analysis summary showing a list of the components that allocated the most memory (and didn’t release them).&amp;#160; In this case rsaenh.dll allocated 703 MB so we probably don’t even have to worry about the advapi32.dll allocations.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_8.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_thumb_3.png" width="1104" height="132" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If you happen to debug a dump where most of the memory is .net you will probably see mscorwks.dll as one of the top allocators.&amp;#160; This doesn’t mean that mscorwks.dll is leaking, it just means that the GC allocated a lot of segments that it didn’t release because the .net objects are still in use.&amp;#160; If that is the case you need to follow some of the other articles on how to debug .net memory leaks instead.&lt;/p&gt;

&lt;p&gt;If you don’t see any big allocators in this list, you probably didn’t leak track for long enough.&amp;#160; You can see how long tracking has been turned on, and how much has been allocated during that time by following the Leak Analysis Report a bit further down in the report output.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_10.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_thumb_4.png" width="244" height="82" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Going back to the issue at hand, we saw that most allocations were made by rsaenh!ContAlloc+17.&amp;#160; Does that mean that this method leaks?&amp;#160; Not neccessarily… we will have to look at the call stacks leading up to the allocations to see why it doesn’t release the memory.&lt;/p&gt;

&lt;p&gt;If we follow the link for rsaenh!ContAlloc+17 we will see some statistics about the allocations&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_12.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://blogs.msdn.com/blogfiles/tess/WindowsLiveWriter/DebuggingNativememoryleakswithDebugDia.1_9E76/image_thumb_5.png" width="804" height="374" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;So from here we find that most of the problematic allocations are the 422 byte allocations since a total of 689 MB was allocated in 422 byte chunks.&lt;/p&gt;

&lt;p&gt;From here we can then drop down and look at the call stacks for the 422 byte allocations and find&lt;/p&gt;

&lt;div class="SampleCode"&gt;
  &lt;p&gt;&lt;b&gt;Call stack sample 4&lt;/b&gt;&lt;/p&gt;

  &lt;p&gt;Address&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0x0e309518
    &lt;br /&gt;Allocation Time&amp;#160;&amp;#160; 00:05:00 since tracking started

    &lt;br /&gt;Allocation Size&amp;#160;&amp;#160; 422 Bytes&lt;/p&gt;

  &lt;p&gt;Function&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Source&amp;#160;&amp;#160; Destination
    &lt;br /&gt;rsaenh!ContAlloc+17&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ntdll!RtlAllocateHeap

    &lt;br /&gt;rsaenh!MakeNewKey+6c&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; rsaenh!ContAlloc

    &lt;br /&gt;rsaenh!CPDeriveKey+3b1&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; rsaenh!MakeNewKey

    &lt;br /&gt;advapi32!CryptDeriveKey+af

    &lt;br /&gt;SomeCryptoComponent+8328&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; advapi32!CryptDeriveKey

    &lt;br /&gt;SomeCryptoComponent+4ef5

    &lt;br /&gt;oleaut32!DispCallFunc+16a

    &lt;br /&gt;oleaut32!CTypeInfo2::Invoke+234&amp;#160;&amp;#160; oleaut32!DispCallFunc

    &lt;br /&gt;. . .&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Note: I have obfuscated the name of the 3rd party component here.&lt;/p&gt;

&lt;p&gt;This call stack tells us that a method in the component “SomeCryptoComponent.dll” is calling advapi32!CryptDeriveKey and this is what eventually leads to the allocations we are seeing.&amp;#160;&amp;#160; We can’t see the method in SomeCryptoComponent.dll because we don’t have the symbols (pdb files) for it, but if we did we could add them to the symbol path under tools/options and rerun the analysis to get a better stack.&lt;/p&gt;

&lt;p&gt;Either way,&amp;#160; whenever you call CryptDeriveKey, you need to pair it up with a CryptDestroyKey when you are done with the Key in order to release memory.&amp;#160; For some reason this is not happening here and thus the memory used for the keys is left allocated and this is what is causing the memory leak here.&lt;/p&gt;

&lt;p&gt;In this particular case, the vendor for the SomeCryptComponent.dll already had an update with a fix ready to go, but I wanted to write this case study to show how you can track down a native memory leak like this with debug diag.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;Have a good one,&lt;/p&gt;

&lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9948358" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/Memory+issues/">Memory issues</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item><item><title>High CPU in .NET app using a static Generic.Dictionary</title><link>http://blogs.msdn.com/b/tess/archive/2009/12/21/high-cpu-in-net-app-using-a-static-generic-dictionary.aspx</link><pubDate>Mon, 21 Dec 2009 10:02:20 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9939496</guid><dc:creator>Tess1</dc:creator><slash:comments>20</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/tess/rsscomments.aspx?WeblogPostID=9939496</wfw:commentRss><comments>http://blogs.msdn.com/b/tess/archive/2009/12/21/high-cpu-in-net-app-using-a-static-generic-dictionary.aspx#comments</comments><description>&lt;p&gt;A couple of weeks ago I helped out on a high CPU issue in an ASP.NET application.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Problem description&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Every so often they started seeing very slow response times and in some cases the app didn’t respond at all and at the same time the w3wp.exe process was sitting at very high CPU usage 80-90%.&amp;#160; This started happening under high load, and to get the application to start responding again they needed to restart IIS.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Debugging the problem&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;They gathered a few memory dumps during the high CPU situation for us to review and when running the sos.dll command ~* e !clrstack (in windbg) to see what all the threads were doing we found that they were all stuck in callstacks similar to this one:&lt;/p&gt;  &lt;pre class="debug"&gt;OS Thread Id: 0x27dc (124) 
  ESP&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; EIP&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;2f77ed24 795b3c5c System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.__Canon, mscorlib]].FindEntry(Int32) 
2f77ed3c 795b3835 System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.__Canon, mscorlib]].ContainsKey(Int32) 
2f77ed40 209f1932 MyComponent.Settings.get_Current() 
... 
SOME STACK FRAMES REMOVED AS THEY ARE NOT IMPORTANT FOR THIS ISSUE 
... 
2f77f0a4 209f7545 ASP.MyApp_default_aspx.ProcessRequest(System.Web.HttpContext) 
2f77f0a8 65fe6bfb System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 
2f77f0dc 65fe3f51 System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef) 
2f77f11c 65fe7733 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception) 
2f77f16c 65fccbfe System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object) 
2f77f188 65fd19c5 System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest) 
2f77f1bc 65fd16b2 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest) 
2f77f1c8 65fcfa6d System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32) 
2f77f3d8 79f047fd [ContextTransitionFrame: 2f77f3d8] 
2f77f40c 79f047fd [GCFrame: 2f77f40c] 
2f77f568 79f047fd [ComMethodFrame: 2f77f568]&lt;/pre&gt;

&lt;p&gt;In other words, the method MyComponent.Settings.get_Current() was calling ContainsKey on a Generic.Dictionary object and for some reason it was getting stuck when trying to find the entry.&lt;/p&gt;

&lt;p&gt;Looking at the MyComponent.Settings.get_Current() method, we found that the Generic.Dictionary it was calling ContainsKey on was a static dictionary and that all threads were working on the same dictionary.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/xfhwa508(VS.80).aspx"&gt;The MSDN documentation about Generic.Dictionary&lt;/a&gt; has the following information about the thread safety of Dictionary objects&amp;#160; &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A &lt;b&gt;Dictionary&lt;/b&gt; can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with write accesses, the collection must be locked during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What is happening here, and causing the high CPU is that the FindEntry method walks through the dictionary, trying to find the key.&amp;#160; If multiple threads are doing this at the same time, especially if the dictionary is modified in the meantime you may end up in an infinite loop in FindEntry causing the high CPU behavior and the process may hang.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resolution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These type of timing issues with static collections are fairly common in ASP.NET apps with high load.&lt;/p&gt;

&lt;p&gt;To resolve this timing issue you should take special care to synchronize (lock) around access to the dictionary if there is a possibility that you may have multiple writers working at the same time or if there is a possibility that you write while someone else is reading/enumerating through the same dictionary.&amp;#160; &lt;/p&gt;

&lt;p&gt;In general, I would recommend to always read the thread safety information carefully when using static collections as many of them require that you implement synchronization on concurrent read/write operations, to avoid this type of issue or issues with for example HashTables where you may get exceptions like InvalidOperationException “Load Factor Too High”. &lt;/p&gt;

&lt;p&gt;Have a good one,&lt;/p&gt;

&lt;p&gt;Tess&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9939496" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/tess/archive/tags/Performance+issues+and+hangs/">Performance issues and hangs</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/ASP-NET/">ASP.NET</category><category domain="http://blogs.msdn.com/b/tess/archive/tags/Debugging/">Debugging</category></item></channel></rss>
