Redgate logo for print use

ANTS Performance ProfilerANTS Performance Profiler

Back to all resources

Article

How to improve the performance of ASP.NET applications


Consider front-end performance issues as well as back-end performance issues

David Berry | @DavidCBerry13 | www.buildingbettersoftware.blogspot.com

Many applications written today are web applications, so it is important to consider front-end performance issues as well as back-end performance issues. While the processing of a web page on the web server may only take a few hundred milliseconds, for example, it can take several seconds for the browser to load and render the page to the user.

Tools like Google PageSpeed Insights and Yahoo YSlow can analyze your pages for adherence to known front-end performance best practices. You not only get an overall score for your page, but a prioritized list of issues so you know exactly what items need to be addressed. Given how easy these tools are to use, every web developer should install them in their browser and analyze their pages on a regular basis.

Flush HTML responses early

Nik Molnar | @nikmd23 | www.nikcodes.com

By flushing HTML responses, the browser gets a jump start on downloading critical resources. It's also pretty easy to do in ASP.NET MVC with the CourtesyFlush NuGet package.

Consolidate your images with sprites

Jonathan Danylko | @jdanylko | www.danylkoweb.com

If you have a standard collection of images with the same height and width (like social icons), use a sprite generator to consolidate the images into one file, and then use CSS to position the separate images on your website. Instead of multiple browser requests, you then make one request for the consolidated image, and the CSS positions the images for you.

Efficiently Streaming Large HTTP Responses With HttpClient

Tugberk Ugurlu, Redgate | @tourismgeek | www.tugberkugurlu.com

HttpClient in .NET has a default behavior of buffering the response body when you make the call through GetAsync, PostAsync, PutAsync, etc. This is generally okay if you are dealing with small sized response bodies. However, if you wanted to download a large image and write it to a disk, you might end up consuming too much memory unnecessarily.

The following code, for example, will use up lots of memory if the response body is large:

static async Task HttpGetForLargeFileInWrongWay()
{
	using (HttpClient client = new HttpClient())
	{
		const string url = "https://github.com/tugberkugurlu/ASPNETWebAPISamples/archive/master.zip";
		using (HttpResponseMessage response = await client.GetAsync(url))
		using (Stream streamToReadFrom = await response. Content.ReadAsStreamAsync())
		{
			string fileToWriteTo = Path.GetTempFileName();
			using (Stream streamToWriteTo = File. Open(fileToWriteTo, FileMode.Create))
			{
				await streamToReadFrom.CopyToAsync(streamToWriteTo);
			}
			response.Content = null;
		}
	}
}
							

By calling GetAsync method directly, every single byte is loaded into memory.

A far better method is to only read the headers of the response and then get a handle for the network stream as below:

static async Task HttpGetForLargeFileInRightWay()
{
	using (HttpClient client = new HttpClient())
	{
		const string url = "https://github.com/tugberkugurlu/ASPNETWebAPISamples/archive/master.zip";
		using (HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption. ResponseHeadersRead))
		using (Stream streamToReadFrom = await response. Content.ReadAsStreamAsync())
		{
			string fileToWriteTo = Path.GetTempFileName();
			using (Stream streamToWriteTo = File. Open(fileToWriteTo, FileMode.Create))
			{
				await streamToReadFrom. CopyToAsync(streamToWriteTo);
			}
		}
	}
}
							

The HttpCompletionOption.ResponseHeadersRead enumeration value reads the headers and returns the control back rather than buffering the response. The CopyToAsync method then streams the content rather than downloading it all to memory.

For more information, see http://www.tugberkugurlu.com/archive/efficiently-streaming-large-http-responses-with-httpclient

Move to ASP.NET MVC

Jonathan Danylko | @jdanylko | www.danylkoweb.com

With the new release of Visual Studio 2015 and ASP.NET 5.0, there is no better time to move to ASP.NET MVC. With WebForm's ViewState taking up a hefty amount of space on the return trip to the browser (and possibly a mobile device), it could take a long time to render the content to the page. Particularly when web pages are now becoming larger and larger.

ASP.NET MVC makes your HTML more granular, returns a smaller HTML footprint to the browser, and provides a better separation of concerns for your development.

Use ASP.NET generic handlers instead of WebForms or MVC

Jeff Osia | www.linkedin.com/in/jeffosia

In ASP.NET applications, generic handlers, WebForms, and MVC all implement the IHttpHandler interface. The generic handler is normally the most lightweight option.

For more information, see: https://msdn.microsoft.com/en-us/ library/bb398986.aspx

Cache your static content by directory

Jonathan Danylko | @jdanylko | www.danylkoweb.com

If you have a directory of content like JavaScript, images, and CSS, place a web.config in that content directory to cache your static content.

For example, if you had a directory called 'Content' with an images, styles, and scripts directory underneath it, you would place a web.config (similar to below) in just the content directory.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="1.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
							

You can include this web.config in any static directory to gain maximum caching web performance.

Keep an eye on your server-side code

Nik Molnar | @nikmd23 | www.nikcodes.com

Practice good performance hygiene by keeping an eye on your server-side code with a tool like Glimpse. Glimpse inspects web requests as they happen, providing insights and tooling that reduce debugging time and empower every developer to improve their web applications.

Send as little as possible to the web browser

Ben Emmett | Redgate

Web page load time is often limited by network latency, which can range in the hundreds of milliseconds, especially for mobile devices. The more files are transferred and the larger those files, the more round trips will be needed, so the greater the impact the latency will have. As a developer, there's rarely much you can do to reduce the latency, but you can cut down the number of times the round trip cost is incurred.

HTTP compression should always be turned on, and makes a particularly big impact for easily compressible content like html.

Minification and bundling of JavaScript & CSS files can be automatically handled by ASP.NET from v4.5 onwards. Just make sure you set BundleTable.EnableOptimizations = true;

If you're including libraries like jQuery, serve it up from Google or Microsoft's free CDNs. Google's datacenters are probably better than yours, and it's very likely a user will already have a cached copy of the same library from having visited other websites using the same CDN, entirely eliminating their browser's need to re-download it. It also reduces your own server's load and bandwidth.

Clear out the cruft! A new ASP.NET project includes many libraries, not all of which are necessarily used, and if something's being unnecessarily sent to the client, it's incurring performance cost for no good reason. It can also be astonishing how many libraries get added to a project over time, but not removed when they stop being required. An occasional spring clean helps keep this in check.

How to improve the performance of ASP.NET applications