This post is second part of my previous post where we discussed six tips to improve the performance of ASP.NET applications. In this post, we are going to discuss six more tips that could be another round a booster for your application performance. The link of previous post is below.
12 tips to increase the performance of ASP.NET application drastically – Part 1
6 Make your page asynchronous
IIS uses CLR thread pool to get a thread that processes a request that comes to the application. Say, if there are currently twenty threads available in pool, it means only twenty request can be served in parallel and if request processing takes some time then it could turn into disaster if hundred odd request are bombarded in few milliseconds. In this case, some of the requests may take very long time and for some may return 404 status code. For any request, the significant part of time is gone when the request goes out of current scope like going to database and fetching or reading/writing file, calling the web services etc. During that period, current thread keeps waiting till the response is returned. So if we make the page asynchronous and time consuming calls is handled asynchronously, then we can increase the throughput considerably. To process a page asynchronously, add async directive in page as
Also now writing asynchronous code became so easy with the introduction of async and await keyword. We can write asynchronous methods and can use it with the help of RegisterAsyncTask method of the page.
7 Application Pool Suspension - This feature got introduced with Windows Server 2012 R2 and .NET 4.5.1. IIS provides a setting Idle Time out for application pools which is by default set as 20 minutes. It means that if there is no request for 20 minutes, worker process (w3wp.exe) will stop to save the server resources. But it has a side effect, as the worker process currently stopped, the next request becomes victim because while serving it, worker process is required to restart and initialized. Worker process restart is an expensive and time taking process as it includes lots of tasks like process start, initialize configurations, initialize asp.net, load the binaries etc in memory.
This feature allows us suspend the process instead of stopping it. After suspension, it releases most of CPU and memory which becomes available for other sites hosted on same server. But it is maintained in a state if a request comes, it will become active quickly and start serving the request. It is similar to suspension in windows apps where we have concepts of active and suspended apps. It helps in two folds, first it allows us to server more optimally by adding more application and even the request which comes after timeout, also served quickly without much difference with active ones. We can configure in any app pool as
Select application pool -> advanced settings
8 Remove methods from Glabal.asax – Global.asax provides us some application level methods where some gets fired once on first request while others fired in each request. Most of the time, we have empty methods in this files, which forces asp.net execute those methods even if there is no code inside. On each request, ASP.NET looks if there is any method available in Global.asax, and if yes, then it loads and execute it accordingly. So as a first thing, we should remove empty methods and even if we can remove some methods from there by putting the code at some other place in page lifecycle, then it will be also helpful.
9 Don’t use SqlDataSource – Avoid using SqlDataSource as data source for data controls like GridView. In case of GridView, if paging is enabled, on page number click, it fetches all the records from the database and then apply the paging by own. Same is true for sorting as well. Instead use model binding introduced in ASP.NET 4.5, where we can use IQueryable queries and use select method etc to return the list of items. IQueryable behind the scene optimize and create the SQL queries smartly that fetches only the required data from the database like only ten records instead of all the records or sort the data at database level. That makes the paging and sorting very efficient. Similarly we can use QueryableDataSource or ObjectDataSource as well.
10 Use HTTP Keep Alive - It is another hidden gem which resides in response header and helps in improving the performance of our web applications significantly. This response header keeps the client and server connection open for specific duration and it is utilized by multiple requests. In case the connection is open, the time for creating a new connection gets saved which enables the server to send the response very quick. By default it is enabled it and connection is opened for 120 second. If it is disabled, it behaves as HTTP 1.0 where only one request per connection is allowed. We can configure it on IIS as
Go to IIS -> Select the desired website-> Open HTTP Response Headers -> Click on Set Common Headers from action tab at right
It is by default enabled (refer the encircled area). Verify it to check whether your application is leveraging this feature or not.
Note – For IIS 7.5 and above, this header tag is removed from the response header and by default it is enabled as discussed but there is another header tag in opposite case. If it is disabled then in response header there is new header is available as Connection: close. It means connection is closed after the request.
11 Remove ETag - Let’s have a look on one HTTP response header
Here we can see that there one element as ETag (Refer Red encircled). Let’s try to understand the way it is used. Whether any response is served by the client cache or not, depends on two items: One is Cache-Control and Expires attribute, and another ETag. ETag is a hash code that is created on the web server for each content and in case of content of the file changes, hash changes which invalidates the cache. In Web Farm scenario, hash created on different server will be different even if the content is same because hash also depends on server as well. So the request won’t be served from the cache even if the content is same if request goes to another web server. So it is better if we remove this tag itself to get the better use of client cache if application is hosted in web farm.
12 This tip is a set of few very important configuration changes, which can make a significant impact on the performance of your application.
a. We discussed earlier that IIS uses CLR thread pool to serve the request. Let’s take an example, if our application receives just even 100 requests simultaneously and this number of threads are not available in thread pool, then some of them has to wait. CLR starts creating new threads to assign each request. Creating new threads is pretty heavy process and in earlier versions of .net, the rate of creating threads was two seconds per thread while in latest version, it is around 0.5 second. Considering 0.5 sec per thread, creating eighty threads will take forty second so we can understand that the response time would vary at least 1-40 second. You can imagine the situation if number of request goes 500 or 1000.
There is one setting in machine.config which is by default as
Which we can change as
maxWorkerThreads = "200" />
As we have set the minWorkerThread count as 100, it will reduce the time spent on creating each thread and IIS will be ready to take the requests quickly. Please note the above settings are on per core CPU basis.
b. There is another important settings available in applicationHost.config (can be set at application pool level) as maxConcurrentRequestsPerCPU (available in IIS 7+) which is in latest versions is 5000, can be tweaked based on requirement. As the name suggests, it sets the limits the number of concurrent request can be processed by the application.
c. maxConnection is another very important configuration. It limits the number of connection can be created to some other system. The default value was 2 in earlier versions of .NET. It comes into the picture when web server makes a call to other machine in network like database/wcf services etc. It means at a point of time only two connections can be made, even if you have high end servers with good connectivity. It can be changed at machine level or application level as
Here we have changed it to one hundred. Based on requirement, we can increase or decrease but it is advised keep it moderate number else it could be a overkill. Apart from that we can provide more specific details like IP address or domain information to limit it to specific server(s) in network.
Conclusion – In this series, we discussed following twelve tips, most of them we can easily apply without any code change that can enhance the performance of your web application drastically. These are
1 Kernel mode Cache
2 Pipeline mode
3 Remove unused modules
5 Don’t write in wwwroot
6 Remove unused view engines and language
7 Make your page asynchronous
8 Application Pool Suspension
9 Remove methods from Glabal.asax
10 Don’t use SqlDataSource
11 Use HTTP Keep Alive
12 Remove ETag
I tried to discuss the tips which are normally ignored but they have huge performance enhancement potential and can be applied quickly as well. Some common tricks likes Bundling and Minification, IIS compression, ViewState, client caching are very important but well known they did not include in the series.