Designing and Developing High-Performance SharePoint Server 2007 Publishing Sites

Summary: Learn about the Web Content Management features in Microsoft Office SharePoint Server 2007 that enable organizations to deploy Internet-facing publishing sites, and considerations for developers and designers when designing and building high-performance publishing sites. (16 pages)

MVP Icon Andrew Connell, Critical Path Training, LLC (Microsoft MVP)

December 2009

Applies to: Microsoft Office SharePoint Server 2007

Contents

  • Introduction to Creating High-Performance SharePoint Server 2007 Publishing Sites

  • Benchmarking a SharePoint Server Publishing Site

  • Resolving Common Coding Performance Issues

  • Taxonomy: Designing Site Structure and Authorization

  • Improving Page Load Time in Publishing Sites

  • Conclusion

  • Additional Resources

Introduction to Creating High-Performance SharePoint Server 2007 Publishing Sites

Microsoft introduced the capability to create, host, and maintain content-centric Internet-facing sites in Microsoft Office SharePoint Server 2007 with Web Content Management (WCM) and publishing sites. Previous versions of SharePoint, either Windows SharePoint Services 2.0 or Microsoft SharePoint Portal Server 2003, were not designed to be Internet-facing solutions. Internet-facing solutions have some requirements that are different from those that are not Internet-facing. When building Internet-facing sites, developers and designers must handle higher concurrent client requests, consider multiple user agents, and consider multiple connection speeds—among other things that are not usually as critical in internally facing sites.

This article addresses some of the more important aspects developers and designers need to consider when creating Internet-facing Office SharePoint Server 2007 publishing sites. Some of the guidance in this article can be applied to any site based on Windows SharePoint Services 3.0, including publishing sites, while other things are exclusive to Office SharePoint Server 2007 publishing sites. This article also contains information specific to developers, designers, or those who are implementing Internet-facing Office SharePoint Server 2007 publishing sites. It does not address information architecture, server or network topology, or other administrator or IT professional-related topics; the primary audience is those who are actually building publishing sites.

This article uses the sample Office SharePoint Server 2007 publishing site Adventure Works Travel. This sample site is a good subject because it contains a custom branding with many external files references and sample content.

Benchmarking a SharePoint Server Publishing Site

Performance should be considered and good coding practices should be used when creating a publishing site or any Microsoft ASP.NET 2.0 site. However, like all projects, a publishing site should be tested and performance measured throughout the implementation of the project. Before performance-tuning a publishing site, you must set a baseline to measure the actions taken to determine which ones provide the most benefit. One way to establish a benchmark is by load testing, and gathering the results from various performance counters. The SharePoint Monitoring ToolKit for System Center Operations Manager 2007 monitors more than 40 performance counters on SharePoint servers (for more information, see the System Center Operations Manager 2007 Catalog on Microsoft TechNet). This should provide a good list of performance counters to monitor in the performance and load testing during development of the site. This article also calls out specific counters that assist in monitoring specific areas of interest, such as the disk cache known as the BLOB cache.

The TechNet Web site contains a very good and popular article that should help in planning out a site and setting some site benchmarks and limits. You should review this article, Plan for Software Boundaries (Office SharePoint Server), before creating a site.

Page Payload

When a user requests a page from a Web site, this single request immediately turns into many requests. The page requested, for example, https://www.adventure-works.com/default.aspx, contains references to CSS files, external ECMAScript (Jscript, JavaScript) libraries, images, and other possible file types. When the browser receives the generated HTML markup from the initial request, it parses and initiates requests for each of the referenced files in the markup. This means that a simple request for the home page of a site can quickly turn into many more requests. For example, the SharePoint Server Publishing Portal site definition generates more than 20 requests for the various CSS, ECMAScript, and image files referenced in the markup. The combined requests that make up a single page are known as the page's payload, also referred to as the page weight or page size.

Each of these additional requests puts an extra burden on both the server and client that are requesting the file. While it is not feasible to strive for one download per page requested, you should strive for fewer requests between the client and the server to get the highest performing sites. Developers and designers need a way to easily see the number of requests a page generates. One very useful tool to assist in this task is the Fiddler Web Debugging Proxy, an HTTP debugging proxy freeware tool that, among many other actions, logs all HTTP traffic between the client and the network it is connected to. Developers and designers can use Fiddler to inspect not only all requests, but the order of the requests and the size of each request, as shown in Figure 1, from a simple request for the home page of the Publishing Portal site template.

Figure 1. Fiddler user interface for the Publishing Portal site template

Fiddler UI for Publishing Portal site template

Another useful tool that assists in inspecting the page payload is the Visual Round Trip Analyzer. This free tool from Microsoft does many of the same things and provides much of the same detail that Fiddler provides. The Visual Round Trip Analyzer also contains a very good help file documenting how to use the tool and analyze the reports it generates.

Developers and designers determine the payload of a single request. They can identify specific files that can be isolated and optimized by using Fiddler or the Visual Round Trip Analyzer. Using Fiddler to get the total page weight or payload of a SharePoint page is quite easy. Launch both Fiddler and the SharePoint site's page you want to analyze. This example will use the home page of the Adventure Works Travel sample site. To get accurate metrics from Fiddler, the browser's cache and the previous sessions in Fiddler must be purged. To purge the browser's cached files and cookies, click Tools, and then click Clear WinINET Cache. Next, click Tools, and then click WinINET Cookies. Then, to clear the previous sessions in the Fiddler interface, click Edit, click Remove, and then click All Sessions. Now go back to the browser and refresh the page in question. Without clicking on anything in the loaded page, look at the session list in Fiddler (Figure 2).

Figure 2. Fiddler interface after capturing sessions from Adventure Works Travel home page

Fiddler UI after capture sessions

In the Fiddler status bar, notice it shows "1 / 85". This means that there is one session selected but it captured 85 requests. So a single request for the home page actually triggered 85 requests. The Fiddler Web Sessions window contains a list of all the sessions captured. Notice the Body column contains the total bytes of each session request. With a session selected, click the Performance Statistics tab in the right-side window to see more details, such as the status code, how long it took to retrieve the content, header details, and estimates for how long it would take to retrieve the content from different geographic locations and at different connection speeds. Use the CTRL key or SHIFT key to select multiple sessions for a combined file view. For instance, select all the CSS files (6 files) at the top of the Web Sessions window, to see that the combined size of all CSS files is 29,090 bytes.

The section Improving Page Load Time in Publishing Sites addresses some options for optimizing the page payload.

Server and Site Performance

The payload, or weight of a page, is not the only performance concern with respect to Office SharePoint Server 2007 publishing sites. As with any Microsoft ASP.NET 2.0 application, you must also consider that the performance of the server and custom code for the application can affect your publishing site. The following sections address common coding issues, and how to identify and address them.

Resolving Common Coding Performance Issues

Unlike projects where the application is built from the ground up as a pure custom Microsoft ASP.NET 2.0 application, publishing sites are built by extending and customizing Office SharePoint Server 2007. Microsoft invested considerable resources and time into optimizing the performance of Office SharePoint Server. Because of this, developers should strive to minimize the amount of custom code in an implementation, and instead rely on as many built-in SharePoint components as possible. For example, instead of creating a custom approval workflow, use the one provided in SharePoint Server as much as possible; its configuration options provide flexibility.

However, it is not always possible to deploy custom Office SharePoint Server publishing sites without custom code. In these cases, developers should exercise good coding practices to minimize the impact on the memory of the farm's front-end Web servers and the number of round trips to the database server. The following sections discuss some common coding performance issues or bottlenecks, and how mitigate them.

Managing Memory Properly Using IDisposable SharePoint Objects

SharePoint developers who are developing custom publishing sites with any custom code need to have a solid understanding of the disposable pattern in the Microsoft .NET Framework, and why it is relevant to publishing sites. One of the fundamental aspects of the.NET Framework is that it manages the system memory for developers. Applications based on the .NET Framework can create objects as needed without having to address the issue of destroying objects to free system memory. Under specific conditions, either when the system is experiencing memory pressure (low available memory) or when the CPU is idle over a period of time, the .NET Framework garbage collector is triggered. The garbage collector walks through the managed memory creating a list of objects that are no longer in use and that can be destroyed. When it reaches the end of the managed memory, it starts to destroy objects, from largest to smallest, to get the most out of the process, because creating and destroying objects is one of the most expensive operations in the .NET Framework.

This process works great for objects that are 100 percent managed objects, but some managed objects are simply wrappers to larger unmanaged objects. For example, objects that open a handle to a file or database connection are actually small managed wrappers to much larger unmanaged objects. The challenge this imposes is that the .NET garbage collector can see only the managed memory footprint, not the full managed and unmanaged memory footprint. This means that the garbage collector does not have an accurate number when it generates an inventory of candidates for destruction. Therefore some objects can potentially hang around, consuming large blocks of unmanaged memory and negatively affecting the performance of the server. Excessive memory consumption on a server can yield OutOfMemory exceptions, frequent application pool recycles, and even application crashes.

To address this, Microsoft created the System.IDisposable interface. This interface has a single method, Dispose, which developers implement to release the unmanaged portion of memory consumed by the unmanaged objects it is using. When developers use an object that implements the IDisposable interface, they are supposed to call Dispose as soon as the object is no longer needed. If this guidance is followed, the garbage collector has an accurate representation of the amount of memory consumed by the system and the biggest objects that can be released. For more information about how the .NET Framework manages system memory, the garbage collector, and the disposable pattern, see Chapter 5 - Improving Managed Code Performance by the Microsoft patterns & practices group.

Why do SharePoint developers need to be especially aware of the disposable pattern? SharePoint contains a handful of managed objects that are small wrappers to much larger unmanaged objects. This includes some of the most commonly used objects in custom code, such as SPSite, SPWeb, and PublishingWeb. To assist you with the challenges of memory management and to provide guidance on when to dispose SharePoint objects (including which objects to dispose), see Best Practices: Using Disposable Windows SharePoint Services Objects. In addition, you can use the SharePoint Dispose Checker Tool (SPDisposeCheck), available from the MSDN Code Gallery, to scan custom code to help identify issues related to disposing SharePoint objects.

Using SPContext.Current for Site Collections and Sites

Almost all custom components written by developers need to know the current SharePoint site or site collection for one reason or another. One way to retrieve the current site collection is by creating a new site collection using the following syntax.

SPSite currentSiteCollection = new SPSite(Request.Current.Url.ToString());

The problem with this approach, however, is that it creates an unnecessary object in memory (SPSite) and also triggers a round trip to the database.

For every request for a page on a SharePoint site, SharePoint creates an instance of the current site collection and site that it uses in processing the page request. These two objects are made available to developers by using the following syntax.

// Current site collection
SPSite currentSiteCollection = SPContext.Current.Site;
// Current site
SPWeb currentSite = SPContext.Current.Web;

By reusing these two objects, developers avoid a round trip to the database and the creation of more objects that must be disposed.

Iterating Over SharePoint Collections and Common Coding Issues

Developers who are creating custom components for Office SharePoint Server 2007 publishing sites, or any Windows SharePoint Services 3.0–based SharePoint site, should have a solid understanding of how the SharePoint API works for common scenarios. For example, the developer should know that creating an instance of an SPList object triggers a round trip to the database. Therefore, getting the title and description of a list by using the following code yields two round trips to the database.

string listTitle = SPContext.Current.Web.Lists[0].Title;
string listDesc = SPContext.Current.Web.Lists[0].Description;

Instead, developers should get a local copy of the SPList object and access the properties on the local object. This technique is twice as fast as the previous one because it goes to the database only one time.

SPList list = SPContext.Current.Web.Lists[0];
string listTitle = list.Title;
string listDesc = list.Description;

To understand the common techniques developers will encounter in their custom code, see Best Practices: Common Coding Issues When Using the SharePoint Object Model.

Working with Large Lists and Various Data Access Options

At some point, many, if not most, custom SharePoint components built by developers will need to access data in a SharePoint list. Thankfully, the SharePoint API is quite flexible in that it provides developers many different options for querying data in SharePoint lists. The trick is to know which technique to use at the right time because some are much faster—or slower—than others.

In addition to simple data access, lists that contain large amounts of data require consideration on how to present and query their contents. To review a detailed case study of the various data access methods and how to work with lists that contain more than 100,000 items when the server is under and not under a heavy load, see White Paper - Working with Large Lists in Office SharePoint Server 2007 (TechNet).

One data access technique that is available only on servers with Office SharePoint Server 2007 installed is using the PortalSiteMapProvider object. (This object is not available in Windows SharePoint Services 3.0 installations because it is installed with Office SharePoint Server 2007). This is the same object that the Content Query Web Part and publishing site navigation providers use. This object has a built-in caching mechanism and is optimized for querying for data across multiple lists and sites within the same site collection. The TechNet white paper mentioned earlier includes the PortalSiteMapProvider in the case study and comparisons with other data access options. In addition, the Microsoft Enterprise Content Management (ECM) Team Blog post Increased Performance for MOSS Apps Using the PortalSiteMapProvider describes working with the PortalSiteMapProvider object.

ASP.NET AJAX-Enabled and Asynchronous Web Parts

Inevitably when creating page layouts, developers and designers must address whether they should use field controls or Web Parts to provide editable content regions on the page. You should take great care when making this decision. For guidance, see Understanding Field Controls and Web Parts in SharePoint Server 2007 Publishing Sites for a comparison of field controls and Web Parts, and information about which to use in specific scenarios. One important point to understand is that field controls should be used to display and manage content, whereas Web Parts should be used to provide functionality on the page.

When creating Web Parts that provide some sort of functionality, the need may arise to have the Web Part trigger a postback to perform some server processing. This causes the entire page to be regenerated when only the Web Part needs to be re-executed. This is a classic scenario to ASP.NET AJAX instead of issuing a postback for the entire page. Optimizing Custom Web Parts for the WAN (TechNet) contains a section on creating AJAX-enabled Web Parts. AJAX-enabled Web Parts avoid a full page postback that will inevitably improve the SharePoint front-end Web server's performance and load, and it will also likely reduce the number of database round trips and facilitate a better experience for the site's end users or content authors.

There are other times when the Web Part needs to perform some sort of long-running operation, such as query a database, issue a request to a Web service, or perform a long-running calculation. In traditional ASP.NET 2.0 applications, developers usually know everything that will be put on the page. However, in the case of Web Parts, developers may not know where the Web Part they are building will be used in the site or whether there will be multiple instances of the same Web Part on the same page. Long-running operations can block the processing and load time of the page. Consider a scenario in which a Web Part issues a Web service request that takes two seconds. The entire processing of the page is blocked during this wait for the Web service request. This means that the page will never be faster than the total of two seconds plus the time it takes for the rest of the page to execute. Even worse, consider if there are three of these Web Parts on the same page; the page will never be faster than six seconds because of a single Web Part!

For long-running operations, developers should consider implementing asynchronous programming techniques in custom Web Parts. This removes the blocking aspect of the long-running operation. For example, in the previous example, regardless of how many Web Parts are on the page, the page will potentially execute within two seconds. This is because the Web Parts are not blocking each other or the rest of the page.

Unfortunately, making a Web Part asynchronous is not as easy as a typical ASP.NET 2.0 application. The @Page directive in ASP.NET 2.0 applications has an async attribute that can be set to true to make the entire page execute asynchronously. However, in SharePoint, the Web Part cannot make this change and an alternate technique must be used: creating asynchronous tasks. This involves using the PageAsyncTask object. This object enables developers to register an asynchronous task, or multiple asynchronous tasks, with the page. The ASP.NET 2.0 page life cycle will stop at the OnPreRender phase if there are any outstanding asynchronous tasks that have either not completed or timed out. After all asynchronous tasks are completed or timed out, the processing of the page continues.

Taxonomy: Designing Site Structure and Authorization

When designing the site structure of a new publishing site, exercise extra care if the site has both secure (HTTPS) and anonymous (HTTP) resources. When a secure resource is requested, the user must validate the credentials to determine who the user is, then the ASP.NET 2.0 role provider checks the SharePoint groups the user has been added to, to determine whether they have access to the resource requested. If there are three images on the secured page, the role provider will enumerate through the SharePoint groups four times: once for the page itself and once for each image. Images usually pose the greatest problem in this area. Because of this extra processing, developers and designers should strive to minimize the number of images on the page. One technique to consider is stacking or clustering images, which is addressed in the section Clustering Images: Minimize the Number of Images on a Page.

Another site organizational technique to consider is grouping secured and anonymous resources. The reason for this concerns caching, because page output cache profiles can be applied on a site-by-site basis. Each profile can be optimally configured for each scenario, but if a site contains a mix of anonymous and secured resources, it will be difficult to fine-tune the output cache profile. See the section Improving Page Load Time in Publishing Sites for more information on publishing sites and caching options.

Improving Page Load Time in Publishing Sites

In addition to some of the techniques mentioned previously that address writing custom code for publishing sites, another angle developers can take to improve the performance is reducing the load time of pages. When a request is initiated by a user for a page, there are two components:

  • How long it takes for the server to process the request and respond with the page's markup of the requested page

  • How long it takes for the browser to receive the markup and associated files—such as images, CSS, ECMAScript (JScript, JavaScript)—to render the page

The first component is entirely a server component. The section Resolving Common Coding Performance Issues addressed the custom code aspect for the server. In addition to the custom code, Office SharePoint Server 2007 publishing sites have extra caching capabilities built in that can be configured to dramatically improve performance. For more information, see the following section, Implement, Configure, and Tune Caching.

The second component concerns the goal of limiting the total amount of data the browser needs to download to render the page. As previously mentioned, the size of the markup, reference files such as images, ECMAScript libraries, CSS, and other controls such as Flash or Microsoft Silverlight applications all combine to make up the page payload (also known as page weight). In addition, the number of requests on a page can also negatively affect the speed of how the page is rendered. The section Minimize the Page Payload addresses some techniques that can be employed to not only limit the size of the page's payload but also limit the number of files needed to render the page.

Implement, Configure, and Tune Caching

Office SharePoint Server 2007 publishing sites include the capability for three kinds of caching—page output, object, and BLOB—which are designed to do two things:

  • Minimize the number of instances that the ASP.NET 2.0 page life cycle is kicked off by page requests on the SharePoint front-end Web servers

  • Minimize the number of database round trips between the SharePoint front-end Web server and database servers

Page output and object caching are inherited directly from ASP.NET 2.0. The third kind, BLOB caching, is exclusive to Office SharePoint Server 2007. All three types of caching are addressed in the Microsoft Office SharePoint Server 2007 SDK in Custom Caching Overview.

Note

Be aware that most caching is not enabled on Office SharePoint Server 2007 publishing sites by default; most kinds of caching must be manually enabled.

Page Output Caching

Page output caching is provided by ASP.NET 2.0. This type of caching takes the generated HTML markup and inserts it into memory. The next time the page is requested, the server determines whether a previous request for the same page matches the specified criteria. If it does, it bypasses the ASP.NET 2.0 page life cycle and just returns the cached HTML markup. For more information about configuring the page output cache, see Output Caching and Cache Profiles.

When configuring the page output cache for an anonymous site, speed should take precedence over the most updated content. The most important thing for anonymous Internet-facing sites is speed; the time between the request, response, and rendering should be as fast as possible. Therefore it is acceptable if a page is a few seconds or minutes stale to provide the fastest experience possible.

However, when configuring caching for secured publishing sites such as intranet sites or extranet sites, the most updated content and uniqueness of the page must take precedence over speed. Intranet sites and extranet sites tend to have more relevant information updating on a more frequent basis. Sometimes older versions of the content are no longer applicable and users should see only the most updated content. In this case, a profile can be configured to check whether the page requested has changed from the time a cached version was saved. If so, it invalidates the cache and regenerates the page. In other cases, one user requesting a page may have permissions to see more or different content than another user. Therefore, the uniqueness of the request, or more specifically the user's permissions, should take precedence over speed.

Object Caching

Object caching, also provided by ASP.NET 2.0, is leveraged in publishing sites. This type of caching is enabled by default. It caches items like field control contents and other commonly requested objects. For more information about the object cache and how to configure it, see Object Caching in the Microsoft Office SharePoint Server 2007 SDK.

The configuration of the output cache for each site collection enables administrators to set how much memory the object cache can use. Use the ASP.NET 2.0 performance counter Cache Hit Ratio to determine whether more memory should be allocated to the object cache. If the hit ratio is below 90 percent, which means less than 90 percent of the time objects are not found in cache and the server has to go to the database to retrieve the content, consider increasing the amount of memory allocated to the object cache.

BLOB Caching

BLOB caching, also known as disk-based caching, is an exclusive type of caching provided by Office SharePoint Server 2007. BLOB caching stores larger static files that usually reside in the site's content database on the individual SharePoint front-end Web servers for future requests, eliminating the round trip to the database. For more information about BLOB caching, see Disk-Based Caching for Binary Large Objects.

The max-age attribute is not listed in the <blobCache /> node in the web.config file (where BLOB cache is enabled and configured). This attribute tells browsers how long they can cache the items locally instead of issuing a new request for the files. Make sure this attribute is used, even though it is not included in the <blobCache /> node by default.

Minimize the Page Payload

The section Benchmarking a SharePoint Server Publishing Site explained how to measure the page payload using tools like Fiddler or the Microsoft Visual Round Trip Analyzer. Minimizing the page payload reduces the amount of data sent from the server to the requestor, which improves the page load and render times. In addition to minimizing the payload, developers can also improve the page load time and limit the traffic between the client and server by limiting the number of files referenced in the page's generated markup. This includes images, ECMAScript (JScript, JavaScript) libraries, CSS files, or any other type of referenced file. The following sections address different methods and techniques that can be used to limit the page payload and improve the page load time.

Disabling the ASP.NET 2.0 View State

By default, Windows SharePoint Services 3.0 leaves the ASP.NET 2.0 view state enabled. The view state is a hidden field on ASP.NET 2.0 pages that is used to persist values and settings across postbacks. Many built-in controls use the view state to manage the state of the control between postbacks. The disadvantage to using the view state is it can grow to be quite large on some pages with many controls that have the view state enabled.

A common technique ASP.NET 2.0 developers use is to disable the ASP.NET 2.0 view state, as addressed in "Improving .NET Application Performance and Scalability" Chapter 6 — Improving ASP.NET Performance by the Microsoft patterns & practices group. While disabling the view state in publishing sites can work, it is strongly recommended that you test every page in the site thoroughly in both display mode and authoring mode. SharePoint includes many controls on the page that might require that the view state is enabled.

Clustering Images: Minimize the Number of Images on a Page

Taxonomy: Designing Site Structure and Authorization includes a recommendation that limiting the number of requests for each page, specifically images, would have a positive effect on the page load time. Many sites use multiple images in the implementation of a site's branding. Developers and designers can use a technique that can dramatically reduce the number of images on a page. This technique, known as clustering or stitching, combines multiple images into a single image file. You can then use CSS to clip parts of the image, giving users the impression that multiple images are being used. This will reduce the number of images referenced in the markup of a page and the number of requests from the client to the server. Implementing clustered images is not a trivial task; it can be quite tedious to set up and maintain, but the page load time improvements can be worth the extra effort.

The following example demonstrates how to implement clustered images. It is easiest to cluster images that have the same or similar dimensions. Take two images that are provided with Windows SharePoint Services 3.0: error.gif (Figure 3) and noresult.gif (Figure 4).

Figure 3. Windows SharePoint Services 3.0 image error.gif

Windows SharePoint Services 3.0 image error.gif

Figure 4. Windows SharePoint Services 3.0 image noresult.gif

Windows SharePoint Services 3.0 image noresult.gif

The first step is to combine these two images into one image, placing them side by side, as shown in Figure 5.

Figure 5. Clustered image clusteredImages.gif

Clustered image clusteredImages.gif

Next, create the CSS necessary to clip the images in standard HTML <IMG /> tags. The following CSS assumes the images error and noresult will be nested within a <DIV> tag named imageCluster.

<style>
  .imageCluster{
    height:50px; width:50px;
    position:relative;
  }
  .imageCluster img{
    position:absolute;
  }
  #error{
    clip:rect(0,49,49,0);
  }
  #noresult{
    clip:rect(0,99,49,50);
    left:-50px;
  }
</style>

The following HTML contains two <IMG /> tags that reference the same image file, but are tagged using different CSS identifiers to display different parts of the same file. The browser is smart enough to request the file once, but cache it for future requests. Therefore, although there are two image references in the HTML, the image is downloaded only once.

<div class="imageCluster">
  <img id="error" src="clusteredImages.gif" width="100" height="50" />
</div>
Second image: NORESULT
<div class="imageCluster">
  <img id="noresult" src="clusteredImages.gif" width="100" height="50" />
</div>

This HTML would render in the browser as shown in Figure 6.

Figure 6. Rendering of clustered images

Rendering of clustered images

Address Large ECMAScript Files

One of the biggest challenges to limiting the page payload of Windows SharePoint Services 3.0–based sites, including publishing sites, is the size of the ECMAScript libraries required to implement most SharePoint sites. The file that is usually the topic of debate is core.js. Take the built-in Publishing Portal site template's home page; the payload of the home page is 204 KB, but core.js accounts for 54 KB or 26 percent of the entire page's payload. This ECMAScript library is responsible primarily for the Site Actions menu.

Microsoft does not support removing the core.js reference. However, one technique you can employ is referred to as "lazy loading" of the core.js library. Lazy loading of this file essentially moves it to the end of the request stack. Although this does not reduce the size of the page payload, it changes when the browser requests the file. By the time core.js is requested, the page has loaded and users can see the rendered page. However, the large ECMAScript library is downloaded in the background.

Figure 7 shows the Fiddler output from the built-in Publishing Portal site template's home page.

Figure 7. Fiddler output from the Publishing Portal home page

Publishing Portal site template's home page output

The article How to Create a Detached Page That Downloads the Core.js File But That Does Not Reference the Core.js File on a SharePoint Server 2007 Site (KB 933823, Microsoft Support) walks developers through how to detach core.js from a page and move it to the end of the page's request stack. After implementing the steps in the article, Figure 8 shows the results of implementing the lazy loading of core.js.

Figure 8. Results of implementing lazy loading of core.js

Results of implementing lazy loading of core.js

Another technique for addressing external ECMAScript libraries is to compress them before use on a site. Most ECMAScript libraries are written to be read by humans, but unnecessary characters such as line breaks, comments, block delimiters, and spaces take up extra space that browsers do not need to execute the libraries. This process of compressing the libraries is commonly referred to as minification and it applies to ECMAScript libraries and to CSS files. For more information about minification, and for resources that will compress these libraries, see Minification (programming).

Important

Microsoft does not support altering the ECMAScript libraries that are provided in Windows SharePoint Services 3.0 or Office SharePoint Server 2007.

Implement and Tune IIS Static and Dynamic Compression

Another technique for reducing the page payload is compressing the files that are requested before sending them to the user. Internet Information Services (IIS) offers two types of compression: static and dynamic. Static compression addresses static files such as HTM, HTML, TEXT, and CSS. Dynamic compression addresses ASP.NET 2.0 files such as ASPX, ASCX, ASMX, and ASHX. Office SharePoint Server 2007 automatically enables IIS static and dynamic compression for new publishing sites. This has a significant impact on the payload of a site. For example, although core.js represents 54 KB of a page's payload, the file is actually 257 KB in size on the server. When the file is requested, IIS uses dynamic compression to compresses the file before streaming it down in response to the request.

IIS compression is a very useful turn-key solution to limiting the page payload. Both types of compression are configurable and can be customized based on the site. One of the customization points for static and dynamic compression in IIS is the level of compression. The default compression levels for IIS 6.0 (in Windows Server 2003) and IIS 7.0 (in Windows Server 2008) are a bit different, as shown in Table 1.

Table 1. Default static and dynamic compression levels in IIS 6.0 and IIS 7.0

IIS Compression Level

IIS 6.0

IIS 7.0

Default Static Compression Level

10

7

Default Dynamic Compression Level

0

0

Although the compression levels are configurable, it is something that should be done with significant testing. The higher the compression level, the smaller the files will get but it will also negatively impact the CPUs on the server, as it is a CPU-intensive process. Levels should not be set above 9. However, consider starting at the highest compression level and testing the servers under load. The SharePoint front-end Web server should be configured to run at the highest static and dynamic compression levels that the server can handle.

Modifying the default compression levels in IIS can dramatically improve the payload of a site. For example, the page payload for the Adventure Works Travel site's home page is roughly 786 KB when deployed on Windows Server 2008, including the Silverlight photo gallery application, branding, and high-resolution imagery. The ASPX and ECMAScript files, those subject to dynamic compression, account for 194 KB of the page payload. After setting the dynamic compression levels to 9, the ASPX and ECMAScript files account for 153 KB, a savings of 21.1 percent with no changes to the code base of the site.

Changing the Dynamic Compression Level

Changing the configured static and dynamic compression levels in IIS 6.0 is slightly different from IIS 7.0 because of the new architecture. IIS 6.0 changes are applied by using Visual Basic Scripting Edition (VBScript), whereas IIS 7.0 changes are applied by using a command-line tool or manually configuring an XML file.

To set the dynamic compression to 9 in IIS 6.0, execute the following commands at the command line.

CSCRIPT.EXE ADSUTIL.VBS SET W3Svc/Filters/Compression/DEFLATE/HcDynamicCompressionLevel "9"

CSCRIPT.EXE ADSUTIL.VBS SET W3Svc/Filters/Compression/GZIP/HcDynamicCompressionLevel "9"

To set the dynamic compression to 9 in IIS 7.0, open the application configuration file located at c:\windows\system32\inetsrv\config\applicationHost.config and add the following node as a child to the <httpCompression> node.

<scheme dynamicCompressionLevel="9" />

Adding File Types to IIS 6.0 Static and Dynamic Compression

IIS 6.0 does not include the correct file types for either static or dynamic compression needed for ASP.NET 2.0 or Windows SharePoint Services 3.0–based sites. To add the necessary files for IIS 6.0 static compression, execute the following commands at the command line.

CSCRIPT.EXE ADSUTIL.VBS SET W3Svc/Filters/Compression/DEFLATE/HcFileExtensions "htm" "html" "txt" "css" "js"

CSCRIPT.EXE ADSUTIL.VBS SET W3Svc/Filters/Compression/GZIP/HcFileExtensions "htm" "html" "txt" "css" "js"

To add the necessary files for IIS 6.0 dynamic compression, execute the following commands at the command line.

CSCRIPT.EXE ADSUTIL.VBS SET W3Svc/Filters/Compression/DEFLATE/HcScriptFileExtensions "asp" "exe" "axd" "aspx"

CSCRIPT.EXE ADSUTIL.VBS SET W3Svc/Filters/Compression/GZIP/HcScriptFileExtensions "asp" "exe" "axd" "aspx"

Note

These steps are not necessary for IIS 7.0 static or dynamic compression because it is MIME type–based instead of file name extension–based.

IIS 7.0-Specific Compression Settings

IIS 7.0 has two capabilities that IIS 6.0 does not offer. One is the ability to automatically enable and disable the dynamic compression based on the CPU utilization. IIS 7.0 measures the site at specified intervals of the CPU. If it exceeds the configured threshold, it will disable dynamic compression to keep it from stressing the server even more. To set the range in which the server will enable IIS 7.0 dynamic compression, execute the following commands at the command line to set the threshold between 20–75 percent CPU utilization.

APPCMD.EXE set config –section:httpCompression /dynamicCompressionDisableCpuUsage:75

APPCMD.EXE set config –section:httpCompression /dynamicCompressionEnableCpuUsage:20

The other capability that IIS 7.0 has over IIS 6.0 is the ability to configure the .NET Framework to enable insertion of items into the page output cache after they are compressed. This is a significant advantage that IIS 7.0 has over IIS 6.0. IIS 6.0 compresses markup when it is pulled from the cache, whereas IIS 7.0 compresses it on the way in. This dramatically reduces the impact on the CPU on Windows Server 2008 installations. To set this value, execute the following command at the command line.

APPCMD.EXE set config –section:urlCompression /dynamicCompressionBeforeCache:true

Conclusion

Office SharePoint Server 2007 publishing sites enable organizations to deploy content-centric Web sites via Web Content Management. Internet-facing publishing sites are different from traditional SharePoint collaboration sites in that they typically experience higher traffic. This traffic usually consists of anonymous, unauthenticated users.

These types of sites can be optimized in various ways to implement the best experience for users of the site. This article addresses areas such as server configuration optimizations, techniques to reduce the page load and rendering time for clients, and techniques to reduce the load on the SharePoint farm.

Additional Resources

For more information, see the following resources: