Performance Optimization in ASP.NET Web Sites

Performance is an important aspect of a modern day web application development. Not only it makes sites seamless to use but also increase the scalability and future proof. In this article, we will look at various aspects of improving the performance of web applications. We would only concentrate on the browser/web server side performance as oppose to server/app server/database server performance optimizations.

Before we getting into detail, the first question is, do we really need optimized the web sites?

Amazon.com has performed a test on their web site, and when they slower the site in 100ms, the sales dropped by 1%. As you would imagine a company like Amazon, 1% is a huge lost

Google slower their Search Engine in 500ms, the traffic dropped by 20%

As you can see, it is a very important aspect of modern web site development.

This even becomes more important as nowadays most sites require optimized sites for mobile, tablet devices and other portable devices that often run on low throughput wireless networks.

Below are few tips that you can take to make a better performing website.

Using the right ASP.NET framework

Check your .NET framework. If you can upgrade your site to use .NET 4.5, then it has some great performance optimizations. .NET 4.5 has a new Garbage Collector which can handle large heap sizes (i.e tens of gigabytes). The other improvements are Multi-core JIT compilation improvements, and ASP.NET App Suspension. These optimizations do not require code changes, it either upgrading the framework or changing the configuration i.e IIS etc.

Below is a great article on an overview of performance improvements of .NET 4.5

http://msdn.microsoft.com/en-us/magazine/hh882452.aspx

File compression

There are often requests bloated within the web server with lot of static content. These content can be compressed hence reducing the bandwidth on requests.

The below setting is only available in II7 and later.


<configuration>

<system.webServer>

<urlCompression doStaticCompression="true" doDynamicCompression="true" />

</system.webServer>

</configuration>

The above configuration setting has direct association with IIS and has nothing to with ASP.NET. The urlCompression name sounds strange but it is not really the compressing of URLs. It is compressing or gzipping the content and that sent to the browser. By setting this to true/enabling you can gzip content sent to the browser while saving lot of bandwidth. Also notice that the above settings is not only include static content such as CSS/JS, but also dynamic content such as aspx pages or razor view.
If your webserver running in Windows Server 2008R2 (IIS7.5) these settings are enabled by default. For other server environments, you would want to tweak the configuration as above so you can take the advantage of compression.

Reducing the number of requests to the Server

ASP.NET provides a great way to bundle and minify these static content files. This way the number of requests to the server can be reduced.
There are many ways to bundle and minify files. For example, MSbuild, third party tools, Bundle Configs etc. But the end result is the same.
One of the easiest ways is to use the new Visual Studio Web Essentials Pack. You can download this extention from the below Url.
http://vswebessentials.com/

Once installed, you can create minified and bundled CSS and Script files using the Web Essential Pack as below.

web essentials

The above menu items would create bundled/minified files, and added to your project. Now instead of referencing multiple CSS and JS files, you can simply reference the minified and bundled versions. This would also mean that there will be lesser requests made to the server, which result in less bandwidth and faster responses.
You may also wonder that even if we have bundled all files together, still the total number of Kilobytes remain the same as if we were to server them as individually. This is not necessarily true. For example,

  • The minified process would reduce the size of the files by removing comments, shortening variable, and removing spaces etc.
  • Bundling them together would also remove the additional Http headers that would require for each individual request.

You can also find some great information on the bundling and minification process below.
http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

Get control of your image requests

It is also possible that you can reduce the number of requests for images.
There are couple of ways to do this.

a. You may create an Image Sprite. With image sprite, you can combine multiple different images into a single large image. Then use the CSS to reposition those images within the site.
Below article shows how you would create Image Sprites using web essentials.
http://www.itorian.com/2014/02/creating-image-sprite-in-visual-studio.html

b. Base64 Data URIs
With this you would never make any requests to the server to obtain any images. You can take your smaller images and directly embed them into you CSS/Stylesheet.
code1

This will become.

.main-content {
    background: url('data:image/png;base64,iVBORw0KGgoA………..+ ') 
    padding-left: 10px;
    padding-top: 30px;
}

Setting up expiry headers

By default the static content served by the web server does not have the expiry dates. We can instruct the browser on how to cache the content, and for how long.
image2

If you set the expiration to a future date, the browser would not make a request to the server but instead the static content will be served within browser’s internal cache.
In the web.config, there is a section that you can control these settings.

  <configuration>
      <system.webServer>
        <staticContent>
          <clientCache cacheControlMode="DisableCache" />
        </staticContent>
      </system.webServer>
    </configuration>

We can change these settings to say cache all the static content requested from the server, for instance cache it maximum for a year. Note the expiration is a sliding expiration, which means the content will be serve from the cache from today up to a year.

<configuration>
      <system.webServer>
        <staticContent>
          <clientCache cacheControlMode="UserMaxAge" httpExpires="365.00:00:00" />
        </staticContent>
      </system.webServer>
    </configuration>

Now the web server will automatically add this header to the static files.

image3

(Note : The above Type ‘doc(1)’ would be the Html dynamic file hence the cache settings are not applied.)
This is all good, but what happen if you make a change to your CSS/JS file. With the above settings in place, it will not serve those changes for the entire year. A one way to tackle this issue is to force the browser to refresh the cache. You may also change the URL (i.e add query string, fingerprint/timestamp) to treat the page as a new URL so the cache get refreshed.

Script rendering order

If possible, you can move the script tags >script< to the very bottom of the page. The reason this is important because during the rendering, when browser comes across with a >script< tag, it stops rendering the rest of the page. If you leave the script tags at the bottom of the page, the page/HTML would render faster, the script can execute later on.

Sometimes this not possible due to some DOM elements or CSS requires those scripts to be present so they can be rendered. If that’s the case you could move those scripts further up on the page. However, as a rule of thumb, try to keep the scripts as lower as possible.
Lower positioning of the >script< tag is not the only option but there are other ways you can defer the load of script files.
For example, you can use the defer attribute.

<script src="some.js" defer></script>

By using the defer attribute, you can specify the script not to run until the page has been fully loaded.

Another way is to configure is to run your scripts asynchronously.

<script src="some.js" async></script>

Using the above async tag, the scripts will be run asynchronously as soon as it is available.

Optimizing images

Images are static content and they do take some bandwidth when requested via web server. A one way to solve this is to reduce the size of the images, in other words optimize the images.

Image “Optimize” does not mean that it reduces the quality of the image. But it will re-arrange the pixels and palettes to make the overall size smaller.

Web Definition of “Image Optimization”
“This term is used to describe the process of image slicing and resolution reduction. This is done to make file sizes smaller so images will load faster.”

So how you optimize images?
There are many third-party tools would optimize images. Below VS extension would do the trick for you.
http://visualstudiogallery.msdn.microsoft.com/a56eddd3-d79b-48ac-8c8f-2db06ade77c3

Size of favicon:
This is often ignored but you may have not noticed that sometimes the size of favicon is considerably large.

Caching HTML

If you have pages that never get updated, you can cache those pages for a certain period. For example, if you use Web Forms or ASP.NET MVC you could use ASP.NET Output Caching.
http://msdn.microsoft.com/en-us/library/xsbfdd8c(v=vs.90).aspx
With ASP.NET Web Pages you can modify the response headers for caching. Please see below on some caching techniques on web pages.
http://msdn.microsoft.com/en-us/library/vstudio/06bh14hk(v=vs.100).aspx
http://www.asp.net/web-pages/tutorials/performance-and-traffic/15-caching-to-improve-the-performance-of-your-website
It is important to note that this would only work if you have pages that do not require updates often.

Tooling support for Optimizing Web Sites

I believe that this is the most important aspect of this article, as the right tool goes long way in producing optimized web sites. There are number of tools, but there are 2 tools that always stand out.
a. Yahoo’s YSlow (https://developer.yahoo.com/yslow/)

image4

It is a Firefox Add-On and one of the most popular among web developers.
It has some great feature including a grading system, and instructions to make your site optimized. Most of the content I described in this article is also provided as tips in this tool, so once optimized your grading should go up.
b. Google’s PageSpeed
This is another great chrome browser extension. Once installed this should also be available part of the chrome developer tool bar.

image5

There is no guarantee that you could make all optimisations that these tools suggested. It is all based on the site, and requirements you need to support. But combining both of these tools to measure your site’s performance and applying some of the tips I mentioned before is a great a start.

Summary
In this article, we looked at some of the approaches that you can take to make optimized and better performing web site. This include, reducing number of requests to the server, changes to the .NET framework, compressing techniques and finally some tools that allows you to make better decision on web site performances.
It is also important to consider that whilst these techniques optimize web site/ web server performances, the overall performance can be based on number of other factors. This includes performance of Application Server, Database Server (in a multi-tiered setup). But there is lot of improvements you can gain optimizing sites as described in this article.

Debugging, Visualizing and Querying data using LINQ

One of the challenging things that I have confronted in my day-to-day work is writing complex LINQ queries. I’m sure there are lot of developers out there who have experienced the same when writing complex LINQ queries. This is a simple article to assist for those developers to debug, visualize and query using LINQ to SQL.

Those who new to LINQ to SQL, it is a database development model in the context of an Object Oriented Programming Model. LINQ is a broad topic. If you need to know more about LINQ, there lots of great articles in the web including some excellent sources from MSDN. .NET Framework 4.0 has also made significant enhancements to its LINQ model. This includes improvements to areas such as performances, query stabality, usability, LINQ to SQL class designer and much more. You can find some of those improvement in here.

LINQ to SQL translates the queries you write into parameterized SQL queries (in text form) and send them to the SQL server for processing. Sometimes debugging LINQ queries can be problematic. If you want to know more about debugging LINQ queries please refer to this article.

There are other ways to output LINQ to SQL queries so you can see the entire query that get executed. For example you can output to a debug window, file, or to a memory. Some examples are described in the below articles.

LINQ to SQL log to debug window.

View LINQ to SQL..

VS2010 has a Historical Debugger  which can also be used to view and debug LINQ queries. More info is here.

 

Debug Visualisers

LINQ to SQL Debug Visualiser enables you to view and execute the LINQ queries on the fly. It was a part of beta releases of VS2008, but for some reason MS has dropped it from the RTM release. I cannot see this is integrated into VS2010 either. It is a separate download. You can download it from here.

Take a look at this article on LINQ to SQL Debug Visualizer, which explains how it is integrated and used within Visual Studio. VS LINQ to SQL Debug Visualizer has its own limitations to it. For example it does not diplay the complete query. It is hard to edit and execute while debugging. This article discribe some of limitations.

There is another similar tool that you can download from VS Gallary. This tool should work with any database as well as MS SQL. You can find more information here.

 

LINQPad 

I think this is an excellent tool to write and test your LINQ queries. It is a great tool to help you build any type of queries with LINQ. Standard edition is free and I recon every developer should have it. You save lot of time by having these tools which allows you to be more productive when writng queries

LINQ

You can also connect to a SQL Server DB (Express or Compact Edition) and with a connection to your LINQ Data component (if you have built one) you can perform queries right against your data with LINQ – that’s excellent!  The standard edition is free to download and it supports .NET 4.0 as well. Standard edition does not have the Autocompletion feature.  For more information on Autocompletion please click here.

There is also great webcast that explains the new features of LINQPad with respect to the Entity framework.

More importantly it is a great tool to learn and improve your skills on LINQ to SQL. You can download this tool from here.

Glimpse

Few years back, Phil Haack introduced a Routing Debugger. You might have also seen this niceMvc Route Debugger Visualizer.

What I’m about to show you is a really cool tool, which allows you to debug ASP.NET MVC applications. It is called Glimpse. Glimpse includes not only route debugging support but also many other features. As you know Firebug is a debugging tool for client, and Glimpse does it for the server. Glimpse only works with the version MVC3. It can support MVC2, however you need to have MVC3 installed. It should support ASP.NET Web Forms as well but the current release (beta version) has dependencies to MVC.  I haven’t tried the Glimpse Web Forms debugging yet, but it is supported.

NuGet:

PM> Install-Package Glimpse

glimpse

 

 

 

 

 

 

 

You can configure Glimpse by navigating to

http://localhost:/Glimpse/config

Below is how you see Glimpse while debugging information.

glimpse2

You can debug : Application settings, routes, session variables, trace data.

If it is an Ajax request, then the server embeds the JSON in the content of the page. And many more…

You can see a nice video and more information here.

So if you haven’t started using this, I suggest you download it, as it will definitely assist your development work!

Simple test helper – MVC Action has decorated with a certain attribute

Below is a useful helper, which allows you to verify whether an Action is decorated with a certain attribute. This is very simple to implement, but you can use something like below.
Test helper:

public static class ActionAttributeTestHelper
{
	public static bool DoesMethodActionContainAttribute&lt;TController, TActionResult, TAttribute&gt;(Expression&lt;Func&lt;TController, TActionResult&gt;&gt; mExpression)
	{
		Expression&lt;Func&lt;TController, TActionResult&gt;&gt; methodExp = mExpression;
		var methodCall = (MethodCallExpression)methodExp.Body;
		var methodInfo = methodCall.Method;
		return methodInfo.GetCustomAttributes(false).Any(a =&gt; a is TAttribute);
	}
}



public class SutController : Controller
{
	[Authorize]
	public ActionResult ActionWithAttributeNoParameter()
	{
	   return View();
	}

	public ActionResult ActionWithNoAttribute()
	{
	   return View();
	}

	[Authorize]
	public ActionResult ActionWithAttributeWithParamter(int i)
	{
	   return View();
	}

	[Authorize]
	[HttpGet]
	[OutputCache]
	public ActionResult ActionWithMultipleAttributes()
	{
	   return View();
	}
}

Unit Tests:

public class SutControllerTest
{
	[TestMethod]
	public void ActionWithAttributeNoParameter_ReturnsTrue()
	{
		// Arrange
		var sut = new SutController();

		//Act
		var doesTheMethodContainAttribute = ActionAttributeTestHelper.DoesMethodActionContainAttribute&lt;SutController, ActionResult, AuthorizeAttribute&gt;((x) =&gt; sut.ActionWithAttributeNoParameter());

		//Assert
		Assert.IsTrue(doesTheMethodContainAttribute);
	}

	[TestMethod]
	public void ActionWithNoAttribute_ReturnsFalse()
	{
		// Arrange
		var sut = new SutController();

		//Act
		var doesTheMethodContainAttribute = ActionAttributeTestHelper.DoesMethodActionContainAttribute&lt;SutController, ActionResult, AuthorizeAttribute&gt;((x) =&gt; sut.ActionWithNoAttribute());

		//Assert
		Assert.IsFalse(doesTheMethodContainAttribute);
	}

	[TestMethod]
	public void ActionWithAttributeWithParamter_ReturnsTrue()
	{
		// Arrange
		int anyNumber = 7;
		var sut = new SutController();

		//Act
		var doesTheMethodContainAttribute = ActionAttributeTestHelper.DoesMethodActionContainAttribute&lt;SutController, ActionResult, AuthorizeAttribute&gt;((x) =&gt; sut.ActionWithAttributeWithParamter(anyNumber));

		//Assert
		Assert.IsTrue(doesTheMethodContainAttribute);
	}

	[TestMethod]
	public void ActionWithMultipleAttributes_ReturnsTrue()
	{
		// Arrange
		var sut = new SutController();

		//Act
		var doesTheMethodContainAuthAttribute = ActionAttributeTestHelper.DoesMethodActionContainAttribute&lt;SutController, ActionResult, AuthorizeAttribute&gt;((x) =&gt; sut.ActionWithMultipleAttributes());

		var doesTheMethodContainHttpGetAttribute = ActionAttributeTestHelper.DoesMethodActionContainAttribute&lt;SutController, ActionResult, HttpGetAttribute&gt;((x) =&gt; sut.ActionWithMultipleAttributes());

		var doesTheMethodContainOutputCacheAttribute = ActionAttributeTestHelper.DoesMethodActionContainAttribute&lt;SutController, ActionResult, OutputCacheAttribute&gt;((x) =&gt; sut.ActionWithMultipleAttributes());

		//Assert
		Assert.IsTrue(doesTheMethodContainAuthAttribute);
		Assert.IsTrue(doesTheMethodContainHttpGetAttribute);
		Assert.IsTrue(doesTheMethodContainOutputCacheAttribute);
	}
}

Struct Layouts Performance Tip

Most developers aware of that Structs needed to be in smaller size (16byte or less) so they can run efficiently as possible. If you are interested in how the Struct size contributes to better performance, please refer to this question. This post is about another less popular tip that may contribute to improve the efficiency of Structs.
Just a bit of back ground on Layouts:

The way you structure your code, for example the order you specify fields within a type, is not necessarily the same way the CLR organize those fields. For performance reasons, CLR can re-arrange those fields of a type any way it chooses. Using StructureLayoutAttribute attribute, you can explicitly tell CLR the way you want to organize your fields. If you don’t specify a StructureLayoutAttribute, the compiler selects the most appropriate layout it thinks best.

For Structs, C# compiler creates the LayoutType.Sequnetial by default. This means the fields should stay in the order defined by the programmer.

(Note: For Reference types C# compiler selects the LayoutType.Auto by default.)
Below is a C# Struct with no explicit layout and the corresponding generated IL.

image 1

The Structs are commonly used when interoperating with unmanaged code. Therefore the fields must stay in the order that programmer define for this to work. But most user defined value types/Structs you create have nothing to do with interoperability with unmanaged code. Therefore if you specify the LayoutKind.Auto, the runtime automatically decide the appropriate layout.

 

image2

If you do a quick benchmark on both layouts you see the LayoutKind.Auto is much faster than the LayoutKind.Sequential.

image3

Result–

(Time in milliseconds)

image4

 

(Config: .NET 4, x86, and Release build)
If you want to look at the sample code is below.

//uses LayoutKind.Sequence by default
   2:    publicstructStructSeq

   privatereadonlyByte mb;
   privatereadonlyInt16 mx;
   publicstringa;
   publicstringb;
   publicstringc;
   publicstringd;
}
>
[StructLayout(LayoutKind.Auto)]
publicstructStructAuto
{
    privatereadonlyByte mb;
    privatereadonlyInt16 mx;
    publicstringa;
    publicstringb;
    publicstringc;
    publicstringd;
}

Program
{
  voidMain()
    {
        StructSeq sq = newStructSeq();
        Stopwatch sw1 = newStopwatch();
        sw1.Start();
        for(inti = 0; i < 8000000; i++)
        {
            ProcessStructSeq(refsq);
        }
        sw1.Stop();
        Console.WriteLine("Struct LayoutKind.Sequence (default) {0}", sw1.Elapsed.TotalMilliseconds);

        StructAuto so = newStructAuto();
        Stopwatch sw2 = newStopwatch();
        sw2.Start();
        for(inti = 0; i < 8000000; i++)
        {
            ProcessStructAuto(refso);
        }
        sw2.Stop();
        Console.WriteLine("Struct LayoutKind.Auto (explicit) {0}", sw2.Elapsed.TotalMilliseconds);

        Console.ReadLine();
    }

    publicstaticvoidProcessStructSeq(refStructSeq structSeq)
    {
        structSeq.a = "1";
        structSeq.b = "2";
        structSeq.c = "3";
        structSeq.d = "4";
    }

    publicstaticvoidProcessStructAuto(refStructAuto structAuto)
    {
        structAuto.a = "1";
        structAuto.b = "2";
        structAuto.c = "3";
        structAuto.d = "4";
    }
}

Dynamic columns via DynamicObject

This might be obvious to some of you, but I thought of writing a small post, since it has a nice example of the usage of  .NET 4. DynamicObject.

Recently I had a requirement where I had to dynamically generate a tabular data (rows/cols) and use that data for Json serialization.

There are few ways of implementing this. The below example uses the .NET 4. DynamicObject to generate custom columns. I found this is quite easier and cleaner to implement than the tradition reflection based approach.

var columnsSet1 = new List<Col>() {new Col("row1Col1"),
new Col("row1Col2"), new Col("row1Col3")};
var columnsSet2 = new List<Col>() {new Col("row2Col1"),
new Col("row2Col2"), new Col("row2Col3")};