Chapter 3

Understanding ASP.NET MVC 4 Performance Optimization Techniques

CONCEPTS

IN THIS CHAPTER

  • How to set a performance baseline
  • Online tools for performance testing and optimization tips
  • All about bundling and minification
  • How to scale a Windows Azure Cloud Service
  • How to improve performance

You can find some very interesting statistics about customer behavior based on a website’s performance and responsiveness on the Internet. This includes the fact that more than 40 percent of website visitors will leave your website if the page takes more than three seconds to render. And that, in most cases, visitors to a website expect the page to render in two seconds or less. Also, 65 percent of shoppers dissatisfied with the performance of a website will never return, and will go someplace else next time. Performance of a website is one of the most important reasons visitors remain loyal (see Figure 3-1).

The normal human being can notice an event that takes approximately 500 ms or one-half a second, and will not notice anything that happens in less time than that. However, according to Amazon.com, an increase in the response of Amazon’s system by as little as 100 ms results in a 1 percent loss in sales. In dollar terms, that’s in the millions. Yahoo! also found that an increase of load time by 400 ms resulted in a 5–9 percent drop in its traffic.

Customers and visitors will not use your site if the performance is poor. It’s that simple. This chapter discusses some ways you can optimize your system for performance, and keep your customers or users happy and returning. Some points discussed in this chapter:

  • The importance of setting a baseline
  • Fiddler, F12 developer tools, and MiniProfiler
  • Online tools for measuring performance and compatibility
  • Bundling and minification
  • Scaling a Windows Azure Cloud Service
  • Fifteen ASP.NET and ORM performance enhancing tips

NOTE This chapter contains key ASP.NET MVC optimization concepts. For a step-by-step guide to implement these concepts, see Chapter 4.

SETTING A PERFORMANCE BASELINE

How do you know if your site has a performance problem? When someone mentions your website performs slowly, how do you determine if it really is? If you do not capture performance metrics, you’ll spend a lot of time in meetings and on the phone explaining that the experienced performance is within the normal range. Without documented trends and metrics, both you and your customer will debate performance based on the perceived response times.


NOTE You must capture performance statistics. You need to know when there is a performance problem and fix it before the user notices it.

A number of tools are available to help you manually measure performance of your system. You can use one or all these tools to capture, store, and report the performance metrics of your system:

  • Fiddler: Commonly used for troubleshooting issues between a client and a server, but also includes very valuable performance statistics.
  • Internet Explorer’s F12 Developer Tools suite: The suite provides a very nice graphical representation of all HTTP requests. You can export the data to Excel for further graphing and analysis.
  • MiniProfiler: A useful tool for tracking performance in your system down to a low level. It is simple to configure, install, and embed into your application. MiniProfiler supports ASP.NET, ORMs, ASP.NET MVC, and database query analysis.

Although you have tools and solutions to gather performance metrics automatically, they do have an impact on performance. Before you implement an automated solution for this, make sure you know how much impact it has on the system.

USING ONLINE TOOLS FOR PERFORMANCE TESTING AND OPTIMIZATION TIPS

A recently published website that provides some useful tips for ASP.NET optimization can be found at http://webdevchecklist.com/asp.net/. The website provides links to tools categorized into topics such as Security, Code Quality, Mobile, Performance, and so on. The checklist has a good set of tasks to ensure your website is ready to go into a live environment.

The Performance category for this site contains a number of actions for optimizing an ASP.NET website for performance, for example:

  • Run in release mode (debug="true")
  • Google PageSpeed score of 90+
  • Yahoo! YSlow score of 85+
  • Optimize HTTP headers
  • Optimize images

In Chapter 4 you use Google PageSpeed to define a list of non-optimal configurations on the sample ASP.NET website. The report that Google PageSpeed generates includes suggestions for enabling browser caching, using compression, scaling images, and implementing bundling and minification. When you implement these suggestions, you’ll see a reduction in the size of the page request and the time required to complete the rendering of the homepage.

You can choose any or all of the other online website analysis tools (such as YSlow and Modern.IE), correct the issues, and implement their suggestions. You might also consider some third-party solutions, such as ANTS Performance Profiler or the Performance Analyzer in Visual Studio. Both of these tools enable you to analyze ASP.NET performance, for example. Figure 3-2 illustrates the results of running Visual Studio Performance Analyzer on the ASP.NET website.

The report identifies the methods in the ASP.NET website that takes the longest to execute. This is useful information and you should use it to find places in your system that are not performing well and, therefore, should be optimized.

UNDERSTANDING BUNDLING AND MINIFICATION

Bundling and minification are features available in ASP.NET 4.5 and are introduced through the System.Web.Optimization namespace. They provide a mechanism for reducing the content size and number of round trips required to completely render a web page. The file types that generally benefit from either bundling or minification are typically JavaScript and CSS files, but are not limited to these types. For example, any file type that has a significant amount of white space or long variable names can benefit from this capability.


NOTE Bundling and minification generally improve only the download speed of the first request. This is because the browser caches static content. Dynamic content is not a good candidate for bundling.

Using the F12 Developer Tool Suite in Internet Explorer, you can see the total number of requests required to render a page, as well as the download speed and file sizes. Figure 3-3 shows three occurrences of text/css that have to a total size of 553 bytes and take 1.26 seconds to download. Likewise, two occurrences of application/javascript file types are requested to render a single page with a total size of 3.15 KB taking approximately 500 ms to download. As shown, each one of the files constitutes a separate GET request, and because there is a limit of six concurrent connections from a browser to the hostname, request number seven must wait until one of the other requests completes. The wait time is represented by the empty sections of the timing bar.

If a web page on your website executes a lot of GET HTTP commands to render a page, you should certainly consider implementing bundling if not for the reason mentioned in the previous paragraph, then for the following reason: Requests traveling over a network should be compacted as much as possible. There is an overhead for network packet frames in the form of serialization, for example for each packet. Therefore, if you can reduce the number of frames, you can realize an additional performance gain. Figure 3-4 illustrates a chatty request (top figure) versus a chunky request (bottom figure). A chatty request is one which has a large number of frequent small packets, while a chunky request has a small number of large packets.

In summary, you can implement bundling with few lines of code, as discussed in Chapter 4. This reduces the number of GET requests that the client makes to the server by merging similar file types together into a single file. This also reduces any delay caused by connection limits and network packet framing.


NOTE Excessive bundling can increase latency and data loss, so test your solution thoroughly before going live with it.

The code shown in Listing 3-1 defines how to bundle a group of JavaScript files together. The requirements are to first create an instance of the Bundle class, which is part of the System.Web.Optimization namespace. You then identify the files and their relative path and add them to the Bundles object.

LISTING 3-1: Bundling JavaScript Files

void Application_Start(object sender, EventArgs e)
{
  Bundle JSBundle = new Bundle("~/JSBundle");
  JSBundle.Include("~/syntax/scripts/shCore.js");
  JSBundle.Include("~/syntax/scripts/shBrushCSharp.js");
  BundleTable.Bundles.Add(JSBundle);
}

Four constructors for the Bundle class are available:

  • Bundle(string virtualPath)
  • Bundle(string virtualPath, params IBundleTransform[] transforms)
  • Bundle(string virtualPath, string cdnPath)
  • Bundle(string virtualPath, string cdnPath, params IBundleTransform[] transforms)

If you review Figure 3-3, you’ll notice the size of each individual file and the combined size per file type. Likewise, take note of the params IBundleTransform[]) transforms parameter of the Bundle class. Passing a class that implements the IBundleTransform interface results in the included files being minified. Therefore, implementing minification is as simple as passing an additional parameter to the Bundle class. Listing 3-2 is an example of the minification of the JavaScript files.

LISTING 3-2: Minifying JavaScript Files

void Application_Start(object sender, EventArgs e)
{
  Bundle JSBundle = new Bundle("~/JSBundle", new JsMinify());
  JSBundle.Include("~/syntax/scripts/shCore.js");
  JSBundle.Include("~/syntax/scripts/shBrushCSharp.js");
  BundleTable.Bundles.Add(JSBundle);
}

Notice the addition of the new JsMinify(), which is a default class found within the System.Web.Optimization namespace and which implements the IBundleTransform interface as required. When the minified CSS and JavaScript bundles are referenced from the requested pages, the requests are fewer and the response times faster, as shown in Figure 3-5.

This is a nice feature that is easy to implement, and for which gains in performance are quickly realized.

SCALING A WINDOWS AZURE CLOUD SERVICE

Before the cloud and virtual machines, scaling a system took a lot of time. Scaling meant that you needed to order a new server, to install the operating system and to connect to the network, to install the application onto it, and, if all went well, to add the server to the web farm and start directing traffic to it. This process could take weeks if not months from start to finish. Metrics and processes were required to forecast and anticipate growth and usage of the system well in advance so that you could scale out the current environment.

The creation of virtual machines changed that a lot. Tools, such as VMware and Hyper-V, speed things up considerably. To scale, you can take a snapshot of an existing virtual machine and use that snapshot to build another virtual instance of your system. It still takes time to get it added to the network and to load user traffic onto it, but nothing like it was before virtual machines.

Windows Azure scaling has taken it to the next level. While monitoring your system, if you notice that the CPU or memory usage increases, you can click the Scale link of the Cloud Service or Web Site and increase the number of instances, as shown in Figure 3-6.

In this case, the number of virtual machines running the http://mvc-4.cloudapp.net Web Role is increased to four. After you set and save the scaling of the Web Role, four virtual machines are created, the website is published to the virtual machines, and traffic begins flowing to the new instances when they are needed. During the deployment of the virtual machines, you can track the status by clicking the Instances link and then the environment you want to scale out (for example, either Production or Staging). Figure 3-7 illustrates the transition status.

With three clicks, the website scales from one server to four. No manual configuration is required — it is all done for you automatically. When scaling Windows Azure Web Sites, you also need to take the Web Site Mode into account, as shown in Figure 3-8.

The different website modes:

  • Free: The constraints placed on this mode change, but the name of the mode says it all. Depending on your subscription, a number of websites with a bandwidth and storage limit are provided at no cost.
  • Shared: As with Free mode, Shared mode is deployed into a multi-tenant environment. The main advantage is that there is no bandwidth limit.
  • Reserved: Runs on an isolated small, medium or large virtual machine. There is no limit on the number of websites, CPU usage or memory.

When you click the “?” in the Web Site Mode section, the following information is rendered:

In the Free and Shared modes, all websites run in a multi-tenant environment and have quotas for usage of CPU, memory, and network resources. You can decide which sites you want to run in Free mode and which sites you want to run in Shared mode. Shared mode employs less stringent resource usage quotas than Free mode. The maximum number of sites you can run in Free mode may vary with your plan. When you choose Reserved mode, all your web sites run in Reserved mode on dedicated virtual machines that correspond to standard Windows Azure compute resources.

This means that when your website is in Free or Shared mode, your site runs on a server with other websites. This is the common web hosting approach and is what the product Antares delivers to web-hosting companies. When you run your website in Reserved mode, it runs on a dedicated virtual machine similar to how a Web Role works.

Scaling is no longer a difficult nor costly endeavor. For example, you can scale out the website or Web Role when you are running a marketing campaign and then scale back when the traffic reduces. This scaling back technique is complicated to perform in older scaling models because after you pay for the hardware build it and direct traffic to it, it generally stays, as do the maintenance/fixed costs. Scaling back is a new concept that Windows Azure has made available. Because of this, the costs of unnecessary extra capacity can be significantly reduced.

FIFTEEN PERFORMANCE ENHANCING TIPS

Using online tools, bundling, minification, and scaling can all help your application perform faster and better under load. However, these tools and techniques may not resolve all the performance problems you may encounter in an ASP.NET website. With that in mind, you can implement the following 15 tips into your ASP.NET website to improve performance results:

1. Check the efficiency of ORM-generated SQL queries, and the number of times they execute per transaction. Use a SQL Profiler to confirm both prior to going live with the solution.
2. Turn on the compression of dynamic and static content that IIS supports. Compressing the content results in smaller files, which, in turn, increases the speed of download.
3. Don’t log too much in your production environment. You want your production systems to run as fast and as optimally as possible. Logging requires hardware resources that the application can use for doing its work. Although logging is necessary for troubleshooting, maintainability, and stability tracking, you’ll want to log the minimum amount of information required and turn off your environment when it is not absolutely needed.
4. Perform validations on the client prior to posting it to the server. ASP.NET provides client-side validation controls. You can implement them and avoid an unnecessary round trip to the server. For example, consider the <asp:RequiredFieldValidator />. If you validate only on the server side, a post may fail and return an error message to the user. The user can then correct and then re-post.
5. Use the using{} statement wherever possible and reduce memory leaks. An example of a using{} statement follows:
                 using (SqlCommand command = 
                            new SqlCommand(sql,
                            ConnectionManager.GetConnection()))
                 {
                    command.CommandType = CommandType.Text;
                    count = (int)command.ExecuteScalar();
                 }
As soon as the code execution exits the using{} statement, the command object is marked for deletion and garbage collected the next time it runs.
6. Set the CacheControlMaxAge attribute to a high number. By setting this value to a higher number (for example, one year), on files that do not change (for example, HTML or image files on your website), you can ensure that requests are not retrieved unnecessarily. Only when the CacheControlMaxAge is exceeded will the file download again.
7. Don’t run your website in debug mode. The web.config file for your website contains an attribute called debug located in the <system.web><compilation debug="true"> tags. When in production, set this value to false to avoid unneeded overhead when you compile your ASP.NET temporary files.
8. Although lazy loading is a good ORM technique, if you know the data will be retrieved later, select it, if possible, with a single database hit. A feature called Futures in NHibernate enables you to bundle multiple database queries together. This means you can execute two or more queries and minimize the number of round trips to the database.
9. Always write the database query for the specific context. Don’t reuse the query if it selects data that is not needed. The more data you select, the longer the query takes to complete. In addition, the larger the amount of selected data stored in the result set, the longer it takes to travel back to the client and server across the network.
10. Remove unused HTTP modules. You can remove modules, such as Profile, RoleManager, Session, and UrlAuthorizaion, from the globalModules section if they are not used in your website. Even if they are not used, they consume memory.
11. Use Asynchronous programming techniques. One of the newer capabilities of ASP.NET is that long running code segments in a transaction can run on a separate thread. This enables code not dependent on the outcome of the long-running code segment to continue. After the long-running code segment completes, the threads merge back together.
12. In MVC, use the OutputCache, which serves the request from memory instead of disk. Accessing data in memory is much faster than accessing it on the hard drive. You should take every opportunity to store common result sets or reference data in memory.
13. Implement paging at the database level, not on the client. Paging means that you display a subset of the data in a GridView; then the user clicks a Next button to view the next page of data. The point is not to download thousands of rows of data and store them on the client for the user to page through them. It is likely the user will look at only the first few pages anyway. Therefore, implement the paging on the database side and select only the amount of data required per page.
14. Hardware, hardware, hardware, and more hardware. You can resolve many problems by increasing the capacity of the hardware. Because the price of hardware components is on the decline, you have no good reason not to have too much power.
15. Disable VIEWSTATE if it is not needed. By default, VIEWSTATE is enabled. You can disable it at the page level so that it is turned off for all controls or on a control-by-control basis. VIEWSTATE can get big, which increases the size of the file and impacts the download speed.

USEFUL LINKS

The following links can further help you optimize your system:

SUMMARY

In this chapter, you learned the importance of performance in a website. Customers and visitors expect a website to be responsive and fast. If it does not meet their expectation, they will not return.

A number of tools can aid you in setting a baseline so that you can compare that baseline with performance measurements you take during a slow period. In addition, you can use tools such as ANTS and Visual Studio to gain deeper insight into which methods perform the slowest and, therefore, need more analysis and improvement.

You can implement features such as bundling, minification, and scaling to increase the performance and stability of your website in a short time. These features have a large positive impact on the website.

The next chapter has detailed exercises for implementing many of the concepts discussed in this chapter.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset