Category: Performance


If the performance of a .NET application is effected during the peak load times, it is the end users who will be effected ultimately. This is the reason why distributed caching has become a hot cake for the .NET developers. it not only boost the performance of the application during peak load times, but it also provides scalability and reliability. There are numbers of third party distributed cache provider are available which are doing very good job, NCache and App Fabric being the two most famous ones.

NCache Features that App Fabric does not have

Below is a list of features which make NCache the premier distributed cache provider. Continue reading “NCache Features that App Fabric does not have” »

NCache Distributed In-memory Object Cache

Introduction

In my last post I discussed how you can setup Windows AppFabric Caching and use it from ASP.NET MVC.

AppFabric isn’t the only tool out there that provides you with a distributed in-memory object cache. NCache from Alachisoft is another excellent product which can solve your caching issues.

Let’s see it in action…

 

Table Of Contents

Installation

Lets first install NCache. At the time of writing, version 3.8 had just been launched. You can download the professional or enterprise edition on the following page: Continue reading “NCache Distributed In-memory Object Cache” »

Windows Server AppFabric Caching

Introduction

For those of you who haven’t heard about AppFabric yet, check out the Windows Server AppFabric Learning Center on MSDN. The first version is out now and can be downloaded here.

One key functionality of AppFabric that caught my attention was its caching feature also known as Velocity (Project Code Name). To quote MSDN:

For Web applications, AppFabric provides caching capabilities to provide high-speed access, scale, and high availability to application data.

Sounds interesting, especially as I am building a web application which is going to be hosted in a web farm. Instead of using ASP.NET’s built-in caching option, which is tied to a single AppDomain and thus one web server, I can opt to use a cache powered by AppFabric which is shared across web servers.

Let’s see it in action…

 

Table Of Contents

Installation

Lets first install AppFabric. Download the most appropriate Windows Server AppFabric version for you on the following page: Continue reading “Windows Server AppFabric Caching” »

Most of high scale web applications use MySQL + memcached. Many of them use also NoSQL like TokyoCabinet/Tyrant. In some cases people have dropped MySQL and have shifted to NoSQL. One of the biggest reasons for such a movement is that it is said that NoSQL performs better than MySQL for simple access patterns such as primary key lookups. Most of queries from web applications are simple so this seems like a reasonable decision.
Like many other high scale web sites, we at DeNA(*) had similar issues for years. But we reached a different conclusion. We are using “only MySQL”. We still use memcached for front-end caching (i.e. preprocessed HTML, count/summary info), but we do not use memcached for caching rows. We do not use NoSQL, either. Why? Because we could get much better performance from MySQL than from other NoSQL products. In our benchmarks, we could get 750,000+ qps on a commodity MySQL/InnoDB 5.1 server from remote web clients. We also have got excellent performance on production environments.
Maybe you can’t believe the numbers, but this is a real story. In this long blog post, I’d like to share our experiences.
(*) For those who do not know.. I left Oracle in August 2010. Now I work at DeNA, one of the largest social game platform providers in Japan. Continue reading “Using MySQL as a NoSQL – A story for exceeding 750,000 qps on a commodity server” »
Multithreading is tough. This is what John Robbins says about it in his excellent book Debugging Microsoft .NET 2.0 Applications:

“Don’t do it… Make sure there’s no other way you can structure your program before you decide to incorporate multithreading into your application… you are easily adding a minimum of an extra month of development and testing to your schedule”. I agree with it completely. But there are times multithreading is unavoidable. Especially when more and more Services popping up in the wild…

From Asynchronous Pages in ASP.NET 2.0

Customer Case Study

I am working with the customer to improve their ASP.NET 2.0 application performance. The application issues multiple requests to the backend middleware that is exposed as a web service. The application cannot get a hold on the actual proxies rather it is provided with the components that wrap the web services proxies. The application needs to issue concurrent  requests. Serial request would result in serious latency which is unacceptable by end users.

Analysis

Since we cannot get hold on web services proxies we cannot utilize available asynchronous methods available with it: BeginMyMethod/EndMyMethod and MyMethodAsync/MyMethodCompleted. But we definitely can utilize another option available with ASP.NET 2.0 – registering asynchronous tasks using PageAsyncTask class.

The following information is based on the following materials:

PageAsyncTask Implementation Steps

This is the summary of the steps to implement and register PageAsyncTask:

  • Create a class that contains lengthy operation
  • Declare AsyncTaskDelegate
  • Add OnBegin, OnEnd, OnTimeout methods to the class
  • Mark the calling page as Async=”true”
  • Register the PageAsyncTasks in the ASPX page and execute it

You can grab the Visual Studio 2008 project with the implementation from my SkyDrive here:

The Evolution of the Web Developer

In the past, memory leaks haven’t posed huge problems for Web developers. Pages were kept relatively simple and navigation between different locations within a site was a great way to clean up any loose memory. If there was a leak, it was most likely small enough to go unnoticed.

New Web applications live up to higher standards. A page might run for hours without being navigated and retrieve updated information dynamically through Web services. Language features are pushed to the breaking point by combining complex event schemes, object-oriented JScript, and closures to produce entire applications. With these and other changes, certain memory leak patterns are becoming more prominent, especially those previously hidden by navigation.

The good news is that memory leak patterns can be easily spotted if you know what to look for. Most of the troublesome patterns you might face have known workarounds requiring only a small amount of extra work on your behalf. While some pages might still fall prey to small memory leaks, the most noticeable ones can be easily removed.

Leak Patterns

The following sections will discuss patterns of memory leaks and point out some common examples of each pattern. One great example of a pattern is the closure feature of JScript, while another example is the use of closures in hooking events. If you’re familiar with the event hooking example, you might be able to find and fix many of your memory leaks, but other closure-related issues might go unnoticed.

Now, let’s look at the following patterns:

  1. Circular References—When mutual references are counted between Internet Explorer’s COM infrastructure and any scripting engine, objects can leak memory. This is the broadest pattern.
  2. Closures—Closures are a specific form of circular reference that pose the largest pattern to existing Web application architectures. Closures are easy to spot because they rely on a specific language keyword and can be searched for generically.
  3. Cross-Page Leaks—Cross-page leaks are often very small leaks of internal book-keeping objects as you move from site to site. We’ll examine the DOM Insertion Order issue, along with a workaround that shows how small changes to your code can prevent the creation of these book-keeping objects.
  4. Pseudo-Leaks—These aren’t really leaks, but can be extremely annoying if you don’t understand where your memory is going. We’ll examine the script element rewriting and how it appears to leak quite a bit of memory, when it is really performing as required.

Circular References

Circular references are the root of nearly every leak. Normally, script engines handle circular references through their garbage collectors, but certain unknowns can prevent their heuristics from working properly. The unknown in the case of IE would be the status of any DOM elements that a portion of script has access to. The basic principle would be as follows:

Figure 1 Basic Circular Reference Pattern

Figure 1. Basic Circular Reference Pattern

The cause of the leak in this pattern is based on COM reference counting. The script engine objects will hold a reference to the DOM element and will be waiting for any outstanding references to be removed before cleaning up and releasing the DOM element pointer. In our case we have two references on the script engine object: the script engine scope, and the DOM element expando property. While terminating the script engine will release the first reference, the DOM element reference will never be released because it is waiting on the script engine object to release it! You might think it would be easy to detect this scenario and fix the problem, but in practice the basic case presented is only the tip of the iceberg. You could have circular references at the end of a 30 object chain and those would be much harder to detect.

If you are wondering what this pattern looks like in HTML, you can cause a leak by using a global script engine variable and a DOM element as shown.

<html>
    <head>
        <script language="JScript">

        var myGlobalObject;

        function SetupLeak()
        {
            // First set up the script scope to element reference
            myGlobalObject =
                document.getElementById("LeakedDiv");

            // Next set up the element to script scope reference
            document.getElementById("LeakedDiv").expandoProperty =
                myGlobalObject;
        }

        function BreakLeak()
        {
            document.getElementById("LeakedDiv").expandoProperty =
                null;
        }
        </script>
    </head>

    <body onload="SetupLeak()" onunload="BreakLeak()">
        <div id="LeakedDiv"></div>
    </body>
</html>

To break the leak pattern you can make use of explicit null assignments. By assigning null before the document unloads you are telling the script engine there is no longer an association between the element and the object inside the engine. It can now properly clean up references and will release the DOM element. In this case, you as the Web developer know more about the relationships between your objects than the script engine does.

While that is the basic pattern, it can be difficult to spot more complex scenarios. A common usage of object-oriented JScript is to extend DOM elements by encapsulating them inside of a JScript object. During the construction process, you generally pass in the DOM element you want to attach to and then store a reference to the DOM element on the newly constructed object while at the same time storing an instance of the newly constructed object on the DOM element. That way your application model always has access to everything it needs. The problem is this is a very explicit circular reference, but because it uses different language aspects it might go unnoticed. Breaking up this kind of pattern can become more complex, and you can use the same simple methods discussed earlier.

<html>
    <head>
        <script language="JScript">

        function Encapsulator(element)
        {
            // Set up our element
            this.elementReference = element;

            // Make our circular reference
            element.expandoProperty = this;
        }

        function SetupLeak()
        {
            // The leak happens all at once
            new Encapsulator(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
            document.getElementById("LeakedDiv").expandoProperty =
                null;
        }
        </script>
    </head>

    <body onload="SetupLeak()" onunload="BreakLeak()">
        <div id="LeakedDiv"></div>
    </body>
</html>

More complex solutions to this problem involve registration schemes to note which elements/properties need to be unhooked, having the peer element hook events so that it can clean up before the document unloads, but often you can run into additional leak patterns without actually fixing the problem.

Closures

Closures are very often responsible for leaks because they create circular references without the programmer being fully aware. It isn’t immediately obvious that parent function parameters and local variables will be frozen in time, referenced, and held until the closure itself is released. In fact this has become such a common programming tactic, and users have run into issues so often, there are quite a few resources already available. Because they detail some of the history behind closures as well as some of the specific instances of closure leaks we’ll check those out after applying the closure model to our circular reference diagram and figuring out where these extra references are coming from.

Figure 2 Circular References with Closures

Figure 2. Circular References with Closures

With normal circular references there were two solid objects holding references to each other, but closures are different. Rather than make the references directly, they are made instead by importing information from their parent function’s scope. Normally, a function’s local variables and the parameters used when calling a function only exist for the lifetime of the function itself. With closures, these variables and parameters continue to have an outstanding reference as long as the closure is alive, and since closures can live beyond the lifetime of their parent function so can any of the locals and parameters in that function. In the example, Parameter 1 would normally be released as soon as the function call was over. Because we’ve added a closure, a second reference is made, and that second reference won’t be released until the closure is also released. If you happened to attach the closure to an event, then you would have to detach it from that event. If you happened to attach the closure to an expando then you would need to null that expando.

Closures are also created per call, so calling this function twice will create two individual closures, each holding references to the parameters passed in each time. Because of this transparent nature it is really easy to leak closures. The following example provides the most basic of leaks using closures:

<html>
    <head>
        <script language="JScript">

        function AttachEvents(element)
        {
            // This structure causes element to ref ClickEventHandler
            element.attachEvent("onclick", ClickEventHandler);

            function ClickEventHandler()
            {
                // This closure refs element
            }
        }

        function SetupLeak()
        {
            // The leak happens all at once
            AttachEvents(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
        }
        </script>
    </head\>

    <body onload="SetupLeak()" onunload="BreakLeak()">
        <div id="LeakedDiv"></div>
    </body>
</html>

If you are wondering how to break this leak, it won’t be as easy as a normal circular reference. The “closure” can be viewed as a temporary object that exists in the function scope. Once the function exits, you lose reference to the closure itself, so what would you end up calling detachEvent with? One of the most interesting approaches to this problem was demonstrated on MSN spaces thanks to Scott Isaacs. The approach uses a second closure to additionally hook the window’s onUnload event, and because this closure has the same “scoped” objects it is able to detach the event, detach itself, and finish the clean up process. To make everything easily fit with our model we can also store the closure on an expando, detach it, and then null the expando, as in the following example.

<html>
    <head>
        <script language="JScript">

        function AttachEvents(element)
        {
            // In order to remove this we need to put
            // it somewhere. Creates another ref
            element.expandoClick = ClickEventHandler;

            // This structure causes element to ref ClickEventHandler
            element.attachEvent("onclick", element.expandoClick);

            function ClickEventHandler()
            {
                // This closure refs element
            }
        }

        function SetupLeak()
        {
            // The leak happens all at once
            AttachEvents(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
            document.getElementById("LeakedDiv").detachEvent("onclick",
                document.getElementById("LeakedDiv").expandoClick);
            document.getElementById("LeakedDiv").expandoClick = null;
        }
        </script>
    </head>

    <body onload="SetupLeak()" onunload="BreakLeak()">
        <div id="LeakedDiv"></div>
    </body>
</html>

In a Knowledge Base article, we actually recommend that you try not to use closures unless they are necessary. In the example, I’ve given we don’t need to use a closure as the event handler, instead we can move the closure to a global scope. When the closure becomes a function, it no longer inherits the parameters or local variables from its parent function so we don’t have to worry about closure-based circular references at all. Most code can be fixed by creating an architecture that doesn’t rely on closures where they aren’t necessary.

Finally, Eric Lippert, one of the developers of the scripting engines, has a great post on closures in general. His final recommendations are also along the lines of only using closures when truly necessary. While his article doesn’t mention any of the workarounds for the closure pattern, hopefully we’ve covered enough examples here to get you started.

Cross-Page Leaks

Leaks that are based on order of insertion are almost always caused by the creation of intermediate objects that don’t get cleaned up properly. That is exactly the case when creating dynamic elements and then attaching them to the DOM. The basic pattern is attaching two dynamically created objects together temporarily which creates a scope from the child to the parent element. Later, when you attach this two-element tree to the primary tree, they both inherit the scope of the document and a temporary object is leaked. The following diagram shows two methods for attaching dynamically created elements to the tree. In the first model, attach each child element to its parent, and finally attach the entire subtree to the primary tree. This method can cause leaks through temporary objects if other conditions are met. In the second model, we attach elements into the primary tree working our way from top-level dynamically created element down through all of the children. Because each attachment inherits the scope of the primary document we never generate temporary scopes. This method is much better at avoiding potential memory leaks.

Figure 3 DOM Insertion Order Leak Model

Figure 3. DOM Insertion Order Leak Model

Next, we are going to cover an example of a leak that is transparent to most leak-detection algorithms. Because we don’t leak any publicly visible elements and the objects we leak are very small you might never notice this problem. For our example to work, the dynamically created elements will have to contain a script pointer in the form of an inline function. This will allow us to leak an internal script object that is created temporarily as we attach elements together. Because the leak is small, we’ll have to run thousands of samples. In fact, the objects leaked are only a few bytes. By running the sample and navigating to an empty page, you can see the difference in memory consumption between the two versions. When we use the first DOM model of attaching child to parent, then parent to the primary tree, our memory usage goes up a bit. This is a cross-navigation leak and the memory isn’t reclaimed until you restart the IE process. If you run the sample a few more times, using the second DOM model of attaching the parent to the primary tree and then the child to the parent, your memory won’t continue to climb and you’ll find that you’ve fixed the cross-page navigation leak.

<html>
    <head>
        <script language="JScript">

        function LeakMemory()
        {
            var hostElement = document.getElementById("hostElement");

            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i < 5000; i++)
            {
                var parentDiv =
                    document.createElement("<div onClick='foo()'>");
                var childDiv =
                    document.createElement("<div onClick='foo()'>");

                // This will leak a temporary object
                parentDiv.appendChild(childDiv);
                hostElement.appendChild(parentDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv = null;
                childDiv = null;
            }
            hostElement = null;
        }

        function CleanMemory()
        {
            var hostElement = document.getElementById("hostElement");

            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i < 5000; i++)
            {
                var parentDiv =
                    document.createElement("<div onClick='foo()'>");
                var childDiv =
                    document.createElement("<div onClick='foo()'>");

                // Changing the order is important, this won't leak
                hostElement.appendChild(parentDiv);
                parentDiv.appendChild(childDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv = null;
                childDiv = null;
            }
            hostElement = null;
        }
        </script>
    </head>

    <body>
        <button onclick="LeakMemory()">Memory Leaking Insert</button>
        <button onclick="CleanMemory()">Clean Insert</button>
        <div id="hostElement"></div>
    </body>
</html>

This leak deserves clarification, because our workaround goes against some best practices in IE. The key points to understand about the leak are that DOM elements are being created with scripts already attached. This is actually crucial to the leak, because if we create DOM elements that don’t contain any script and attach them together in the same manner we don’t have a leak problem. This gives rise to a second workaround that might be even better for larger subtrees (in the example we only have two elements, so building the tree off the primary DOM isn’t a performance hit). The second workaround would be to create your elements with no scripts attached initially so that you can safely build your subtree. After you’ve attached your subtree to the primary DOM, go back and wire up any script events at that point. Remember to follow the principles for circular references and closures so you don’t cause a different leak in your code as you hook up your events.

I really wanted to point out this issue because it shows that not all memory leaks are easy to find. It could take thousands of iterations of a smaller pattern to become visible, and it might be something slight, like the order of insertion of DOM elements that causes the problem to arise. If you tend to program using only best practices, then you think you are safe, but this leak shows that even best practices can exhibit leaks. Our solution here was to improve upon the best practice or even introduce a new best practice in order to remove the leaking condition.

Pseudo-Leaks

Often times the actual behavior and expected behavior of some APIs can lead you to misdiagnose memory leaks. Pseudo-leaks almost always appear on the same page during dynamic scripting operations and should rarely be visible after navigation away from the page to a blank page. That is how you can eliminate the issue as a cross-page leak and then start to work on whether the memory consumption is expected. We’ll use script text rewriting as our example of a pseudo-leak.

Like the DOM Insertion Order issue, this issue also relies on the creation of temporary objects in order to “leak” memory. By rewriting the script text inside of a script element over and over again, slowly you’ll begin to leak various script engine objects that were attached to the previous contents. In particular, objects related to debugging script are left behind as are fully formed code elements.

<html>
    <head>
        <script language="JScript">

        function LeakMemory()
        {
            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i < 5000; i++)
            {
                hostElement.text = "function foo() { }";
            }
        }
        </script>
    </head>

    <body>
        <button onclick="LeakMemory()">Memory Leaking Insert</button>
        <script id="hostElement">function foo() { }</script>
    </body>
</html>

If you run the above code and use the Task Manager trick again, while navigating between the “leaking” page and a blank page, you won’t notice a script leak. This script leak is entirely within a page and when you navigate away then you get your memory back. The reason this one is bad is due to expected behavior. You expect that after rewriting some script that the original script won’t stay around. But it really has to, because it might have been used already for event attachments and there might be outstanding reference counts. As you can see, this is a pseudo-leak. On the surface the amount of memory consumption looks really bad, but there is a completely valid reason.

Conclusion

Every Web developer builds a personal list of code examples that they know leak and learns to work around those leaks when they see them in code. This is extremely handy and is the reason the Web is relatively leak-free today. Thinking about the leaks in terms of patterns instead of individual code examples, you can start to develop even better strategies for dealing with them. The idea is to take them into account during the design phase and make sure you have plans for any potential leaks. Use defensive coding practices and assume that you’ll need to clean up all your own memory. While this is an overstatement of the problem, you very rarely need to clean up your own memory; it becomes obvious which variables and expando properties have the potential for leaking.

In the interest of patterns and design I highly recommend Scott’s short blog entry because it demonstrates a general purpose example of removing all closure-based leaks. It does require a bit more code, but the practice is sound and the improved pattern is easy to spot in code and to debug. Similar registration schemes can be used for expando-based circular references as long as care is taken that the registration method itself isn’t riddled with leaks (especially where closures are used)!

About the author

Justin Rogers recently joined the Internet Explorer team as an Object Model developer working on extensibility and previously worked on such notable projects as the .NET QuickStart Tutorials, .NET Terrarium, and SQL Reporting Services Management Studio in SQL Server 2005.

Code optimization: Memory management in .NET, part 2

In the .NET world, memory management is automatic. The recollection of memory, which is not in use, executes as a background task and lets the developer focus more on the task at hand rather than the plumbing work. The first part in this series ongarbage collection dealt with how garbage collection in .NET works. In this article, I’ll take a look at the interfaces exposed to the developer to aid and control garbage collection.

The Dispose design pattern: IDisposable, Dispose, and Finalize
The Common Language Runtime (CLR) cannot clean up resources like database connections, window handles, and file handles. Therefore, it is necessary for the developer to provide mechanisms for cleaning up these unmanaged resources. The clean up for this can be implemented in the Finalize method. The Finalize method is implemented as a destructor in C# language. The calling of Finalize is still under the control of the garbage collector.

Usually, you would need a deterministic way to clean up these unmanaged resources like file handles. For example if you have opened a file for reading and you have finished loading the contents of the file into a buffer, you might want to explicitly close the file handle. For this explicit clean up, .NET provides the dispose design pattern.

Objects which need explicit clean up of unmanaged resources implement theIDisposable interface. The IDisposable interface consists of the Dispose method, which unlike the Finalize method is under the control of the developer.

Since a call to Dispose represents an explicit clean up, it would not be necessary for the Garbage Collector to collect these objects. Hence a Dispose method should contain a call to GC.SuppressFinalize() notifying the garbage collector that finalization is not needed on that object.

The recommended practice is to implement both Finalize as well as Dispose methods on an object which needs to clean up unmanaged resources. The Finalize method would serve as a backup mechanism in the event that the Dispose is never called. The garbage collector would perform the object finalization and prevent a permanent leak of the unmanaged resource.

Figure A
Dispose design pattern

The code snippet in Listing A demonstrates these concepts more clearly.

The Listing A class SampleClass uses a file handle which is an unmanaged resource. Hence, it becomes necessary for this object to implement IDisposable and also to provide a Finalize method.

The cleanup code, which is the clean up of the file handle, is part of the Disposemethod. The GC.SuppressFinalize() is also called once the unmanaged resource has been cleaned up.

The class also provides the destructor (Finalize method). This again contains the code for clean up of the unmanaged resource, which is the file handle.

Weak references
The .NET Framework provides another interesting feature which can be used in implementing various caches. This is the concept of weak reference implemented in .NET as the System.WeakReference class. A weak reference provides a mechanism for referencing an object with the advantage that the referenced object would be available for garbage collection. The ASP.NET cache uses weak references. If the memory usage becomes too high the cache is cleaned up.

Forcing garbage collection
The .NET Framework exposes the System.GC class to the developer to control some aspects of the garbage collector. Garbage collection can be forced by invoking theGC.Collect method. The general advice is not to invoke the garbage collector manually and leave the decision of garbage collection to be automatic. In certain situations, the developer can justify that forcing garbage collection can provide a performance boost. However, great care should be taken when using this method because whenever the garbage collector runs, it suspends all currently executing threads. The GC.Collectmethod should not be located in a place where it would be called frequently. Doing so would degrade the performance of the application.

Server build and workstation build in .NET
The .NET Framework consists of two builds of the same CLR, each tuned for a specific purpose. These are classified as the server runtime and the workstation runtime, and are implemented in the mscorsvr.dll and mscorwks.dll, respectively. The server build of the CLR is built to take advantage of multiprocessing so that garbage collection can be done in parallel. On a single processor machine only the workstation build gets loaded and it is not possible to load the server build.

Also, there is a further setting known as concurrent garbage collection andnonconcurrent garbage collection for the garbage collector. The nonconcurrent setting is used for server environments where the application does not need to be responsive. In a client environment where a user interface is present and the application needs to be responsive, the concurrent setting is used.

Figure B

Processor environments

Microsoft has created some default settings on the project templates available in Visual Studio .NET, and an ASP.NET application should be able to take advantage of multiprocessors and load up the server build of the CLR. However, since a Windows application is usually user-interface rich, it would load the workstation build of the CLR.

It is possible to override these settings and control which build of the CLR would get loaded on a multiprocessor machine by using the CorBindToRuntimeEx API.

Productivity
With the Dispose design pattern, used in conjunction with the two CLR builds, developers can clean up unmanaged resources. The .NET Framework provides the infrastructure for garbage collection, freeing the developer from the task of keeping track of memory clean up. The developer needs to keep track of only the unmanaged resources which he has used, thus making life easier for the developer and improving productivity.

The .NET Framework provides memory management techniques that differ from the way memory management worked in a COM-based world. The memory management in COM was through reference counting. .NET provides an automatic memory management technique that involves reference tracing. In this article, we’ll take a look at the garbage collection technique used by the Common Language Runtime (CLR).

Automatic memory management: How different is it?
In reference counting, the reference count is increased each time memory is allocated for an object. The count is decreased whenever an object goes out of scope. The memory is reclaimed when the reference count reaches zero. This reference counting is manually managed by the developer in a language such as C++. If the developer fails to decrease the reference count when an object is freed, a memory leak is created. Also, the developer might decrease the reference count when he or she is not supposed to, which leads to memory being reclaimed before the proper time.

In comparison, in the managed world of .NET, the memory is handled by CLR. The task of garbage collection runs in the background, and the developer doesn’t have to spend time checking for memory leaks.

The garbage collection algorithm
The garbage collector runs when the memory heap is full. It starts from the root objects that are identified by the JIT compiler and traverses the object chain, tracing the references and adding them to the graph. The application roots are usually global and static object pointers.

When there’s an attempt to add an object that is already present on the graph, the garbage collector stops. In this way, the garbage collector recursively traverses all objects that are linked from the application root objects. Once the traversal is complete, the graph contains all objects that are somehow reachable. Any object that isn’t part of this graph is not reachable and therefore considered garbage. Each object that can’t be reached is marked and then collected.

Figure A
Memory blocks

In Figure A, blocks 1, 3, and 5 are reachable from the application roots. Blocks 2 and 4 are not reachable and hence can be marked for collection. Once the collection is complete, the memory space is compacted. That is, all the objects are moved so that they occupy a contiguous block of memory.

However, there’s one caveat to automatic memory management. The garbage collection algorithm is complex and runs only periodically, which means the memory is not freed immediately after a variable goes out of scope. This type of memory management is referred to as nondeterministic finalization. Only when the memory usage reaches a threshold will the garbage collector be triggered and trace through the object references to reclaim the memory. The main drawback of this method is that it doesn’t give the programmer the precise control as to when the objects are destroyed.

Circular references
Circular reference is a problem that occurs when there are two objects that refer to each other. Let’s say you have Class A that refers to Class B. If Class B also refers to Class A, then we have a circular reference. This happens in many situations. A typical example for this is a parent-child relationship between objects, where the child interacts with the parent object and also holds a reference to the parent object. This could lead to objects that would not get cleaned up until the application was shut down. The .NET way of garbage collection solves the problem of circular reference because the garbage collector is able to clean up any object that is reachable from the root.

Generations
The garbage collector algorithm is highly optimized. As it forms the graph and traces the references, the garbage collector further divides the graph into subgraphs called generations. The CLR classifies the heap in three generations. The objects that are created newly are maintained in generation 0. When the references to these objects are held for a long time, they survive garbage collection. Such objects are then promoted to generation 1 and generation 2. This classification increases performance because the garbage collector can perform collections on a specific generation, as shown in Figure B.

Figure B

Generations

Usually, the short-lived objects that are frequently created and destroyed remain in generation 0. The garbage collector performs a collection on generation 0 only when generation 0 is full. This happens when a request is made for the creation of a new object and there’s insufficient memory to allocate for that object. If the memory reclaimed from generation 0 is sufficient to create the object, the garbage collector does not perform the collection on other generations.

Good coding practices
Knowing the intricacies of how the CLR manages garbage collection should aid developers in writing management code. Automatic garbage collection is designed to complement good coding practices, but not to replace it. In the next installment in this two-part series, we’ll look at the aspects of garbage collection that are under the developer’s control.

Tracing or Instrumentation is invaluable, most effective, and efficient when dealing with performance problems in ASP.NET Applications. The problem is that it requires coding that too often cut or even never planned to be made.

Quick Resource Box

The other downside is some instrumentation implementations are based on heavyweight logging that introduces even more performance problems.

In this post I am sharing my simple techniques I was using for tracing ASP.NET applications without heavy weight coding and without affecting performance significantly. It produced results relatively quick – we were able to put our fingers on the root cause for slowly performing functions relatively quick.

Instrument with System.Diagnostics.Trace

I am using simple class to report function Entry and Exit using System.Diagnostics.Trace class similar to this [I am sure you can prettify it even more]:

namespace Instrumentation
{
public class Tracing
{
public static void TraceFunctionEnter()
{
StackTrace st = new StackTrace();
System.Diagnostics.Trace.WriteLine(true, ”TRC: ENTERING: “ + st.GetFrame(1).GetMethod() + ”USER:” + System.Web.HttpContext.Current.User.Identity.Name);
}
public static void TraceFunctionExit()
{
CheckAndFixDefaultListener();
StackTrace st = new StackTrace();
Trace.WriteLineIf(true, ”TRC: EXITING: “ + st.GetFrame(1).GetMethod() + ”USER:” + System.Web.HttpContext.Current.User.Identity.Name);
}
public static void CheckAndFixDefaultListener()
{
DefaultTraceListener dtl = null;
TraceListenerCollection listeners = System.Diagnostics.Trace.Listeners;

if (listeners.Count == 0)
{
dtl = new DefaultTraceListener();
Trace.Listeners.Add(dtl);
return;
}
foreach (TraceListener listener in listeners)
{
string listenerType = listener.ToString();
if ((string.Compare(listenerType, ”System.Diagnostics.DefaultTraceListener”,true) == 0))
{
return;
}
}
dtl = new DefaultTraceListener();
Trace.Listeners.Add(dtl);
}
}
}

Next is simply calling on static methods when entering and exiting the functions:

protected void Button1_Click(object sender, EventArgs e)
{
Instrumentation.Tracing.TraceFunctionEnter();
//DO STUFF
System.Threading.Thread.Sleep(3000);
Instrumentation.Tracing.TraceFunctionExit();
}

Collecting Instrumentation Information

Until recently I was using freely available Sysinternals DebugView. Here is how instrumented code would look in DebugView:

Even though I have not reported timestamps, DebugView have it’s own stop watch and shows the timestamps precisely.

Recently I discovered new and improved [freely available] Procmon that is able to capture System.Diagnostics.Trace events alongside with system events, so I next time I am on assignment I’d probably use Procmon :) .

Conclusion and Recommendations

The techniques I have outlined in this post does not require heavy weight coding and do not affect performance itself significantly. These techniques also use readily available tools for collecting and parsing the results.

To achieve best performance you need to make decisions based on trade-off between coolness, coding productivity, and personal engineering values. I never thought I would be recommending my customer considering using old fashion Response.Write() in his Internet facing ASP.NET web application in order to significantly improve the application’s performance.

Customer Case Study

During load/stress testing customer’s ASP.NET web application we identified high CPU utilization (up to 90%). After quick investigation we noticed that %Time in GC performance counter is less than optimal. Our assumption was that the application uses memory allocation techniques that are less than optimal. From GC Performance Counters:

“First thing you may want to look at is “% Time in GC”… What is a health value for this counter? It’s hard to say. It depends on what your app does. But if you are seeing a really high value (like 50% or more) then it’s a reasonable time to look at what’s going on inside of the managed heap.”

Another resource we used is timeless patterns & practices’ Chapter 15 — Measuring .NET Application Performance:

.NET CLR Memory\% Time in GC

“…The most common cause of a high value is making too many allocations, which may be the case if you are allocating on a per-request basis for ASP.NET applications. You need to study the allocation profile for your application if this counter shows a higher value.”

So we headed to looking into the code and this is what we found out.

Analysis

During performance code inspection we identified massive usage of collections. The collections were used to transfer the data between the logical layers and then the collections were transferred into datatables to be bindable for DataGrid (yes, it is .Net 1.1 app).

Eureka! We just spotted 3 performance anti-patterns. Massive memory allocation, massive loops, massive type conversions. I’ve shown it to 4 very respected professionals and everyone was saying the same – current situation is pure performance anti-pattern. Here are few suggestions that came up:

  • Bind collections directly to DataGrid eliminating additional memory allocations and loops.
  • Create Datatable directly from XML skipping collection creation step eliminating additional memory allocations and loops.
  • Use Xslt transformation transforming original Xml into Html table using Xslt elminating memory allocations and loops for both collections and datatables.
  • Use Response.Write() as it’s suggested by patterns & practices:

“Use the Response.Write method. It is one of the fastest ways to return output back to the browser.”

Case close? Not really…

Secretly I’ve built Visual Studio 2003 project with these implementations and ran simple stress test using TinyGet utility. The results left us all a bit surprised.

Converting Collection To Datatable (Current Situation)

//create custom collection
MyCollection myCollection = (MyCollection)SampleServices.GenerateCollection(200);
//convert collection to datatable

DataTable datatable = SampleServices.ConvertCollectionTableIntoDataTalbe(myCollection);
//bind datatalbe to dynamically created datagrid
datagrid.DataSource = datatable;
datagrid.DataBind();
The stress test:
tinyget.exe  -srv:192.168.50.68 -uri:/dynamiccontrolsloadingrelease/UseDataTable.aspx -loop:100 -threads:15
The result:

Bind Collection Directly To Grid

MyCollection myCollection = (MyCollection)SampleServices.GenerateCollection(200);
//bind datatalbe to dynamically created datagrid
datagrid.DataSource = myCollection;
datagrid.DataBind();

The stress test:

tinyget.exe  -srv:192.168.50.68 -uri:/dynamiccontrolsloadingrelease/UseCustomCollection.aspx -loop:100 -threads:15

The result:

Create Datatable From Xml

string xml = SampleServices.GenerateXml(200);
StringReader theReader = new StringReader(xml);
DataSet theDataSet = new DataSet();
theDataSet.ReadXml(theReader);
datagrid.DataSource = theDataSet.Tables[0].DefaultView;;
datagrid.DataBind();

string xml = SampleServices.GenerateXml(200);  StringReader theReader = new StringReader(xml);DataSet theDataSet = new DataSet();theDataSet.ReadXml(theReader); datagrid.DataSource = theDataSet.Tables[0].DefaultView;;datagrid.DataBind();

The stress test:

tinyget.exe  -srv:192.168.50.68 -uri:/dynamiccontrolsloadingrelease/LoadXmlIntoDataTable.aspx -loop:100 -threads:15

The result:

Use Xslt Transformation To Create Html Table
Xml1.DocumentContent = SampleServices.GenerateXml(200);
Xml1.TransformSource=@”xsl.xml”;

The stress test:
tinyget.exe -srv:192.168.50.68 -uri:/dynamiccontrolsloadingrelease/XmlXslTransformation.aspx -loop:100 -threads:15
The result:

Use Response.Write()
MyCollection myCollection = (MyCollection)SampleServices.GenerateCollection(200);
// Put user code to initialize the page here
Response.Write(”
“);
foreach(MyModelItem item in myCollection)
{
Response.Write(”
“);
Response.Write(”

“);
}
Response.Write(”

” + item.Address + “ “);
Response.Write(“
” + item.City + “ “);
Response.Write(“
” + item.Education+ “ “);
Response.Write(“
” + item.Family + “ “);
Response.Write(“
” + item.Name + “ “);
Response.Write(“

“);
The stress test:
tinyget.exe -srv:192.168.50.68 -uri:/dynamiccontrolsloadingrelease/ResponseWrite.aspx -loop:100 -threads:15
The result:

Sample Visual Studio 2003 Project

Interested in testing it yourself? Grab the source code from my SkyDrive here:

Conclusion

After conducting this simple test these are the conclusions I’ve made:

  • “Don’t be afraid to challenge the pros, even in their own backyard.” - How to Get Things Done – Colin Powell Version
  • Testing IS DA thing. Assumptions are good but nothing speaks louder than facts.
  • Test early – avoid massive rework afterwards. Create POC’s (Proof of concept) early in architecture/design stages.
  • Best performance comes on expense of productivity and coolness.

Powered by WordPress | Theme: by 85ideas. Editor by Khoanguyen