Performance Tuning Tips

Performance Tuning Tips

Performance tuning involves fixing bottlenecks and tweaking code to achieve your desired throughput rate or response time criteria while maintaining scalability. Using new features in ASP.NET, such as caching and new data access methods, can help you realize greater performance gains and scalability. Disabling certain default features, like Session State and ViewState whenever they are not used can have a positive affect on the performance of your Web application too.

Application and Session State

Maintaining state without creating performance and scalability problems in a Web application distributed among multiple Web servers proved to be challenging in the past. There are more options available for ASP.NET Web applications compared to traditional ASP Web applications, but you still must be aware of the performance versus scalability tradeoffs for each option.

Application State

Traditionally application variables were used to store information like connection strings or as a caching mechanism for storing variables and recordsets among multiple users requests. They still exist in ASP.NET but many of the functions previously served in traditional ASP have been replaced with newer more effective methods. Use the Web.config file to store and retrieve database connection strings or use a trusted connection with a SQL server. Utilize the new caching engine discussed below to store frequently accessed data. Application state still has the limitation and cannot be shared across multiple Web servers.

Session State

Session information is data stored in memory of the Web server for each user making a request. In the past, many problems have been associated with enabling and using session state within a Web application. The underlying protocol used in making each request (HTTP) is stateless, so to overcome this in traditional ASP Web applications an HTTP cookie was assigned to the client and would be passed back to the server for subsequent requests within a certain time frame. For a Web application located on multiple machines or a Web farm, the user may be redirected to a different machine between requests and the session cookie would be lost because it could not be passed among multiple machines.

ASP.NET addresses some of the scalability issues previously associated with using session data in Web farms by offering the option to store it out-of-process in a Windows service or to store it in a SQL server. Keep in mind that scalability is gained but there is a performance hit associated with running the session out-of-process. Session state is enabled by default in the Machine.config file and is set to run in-process. Running Session InProc has the same limitations for ASP.NET Web applications as discussed above for traditional Web applications, however it is the fastest most efficient method to use if session state is required. Our recommendation is if you do not absolutely have to use session state, then disable it in the Web.config file or at the page level. You can disable it at the page level by using <%@ Page EnableSessionState = False %>.

Caching in ASP.NET

Caching has been greatly improved with ASP.NET and when used properly can boost application performance significantly. With traditional ASP, caching was implemented by either storing all of your data in session variables, application variables, or by using a custom caching solution. These methods are still available in ASP.NET, but ASP.NET has even more options available to the developer. With the new caching mechanisms the output of entire pages can be cached via a simple directive. Additionally, there is an advanced caching engine and a caching API that can be used to store any arbitrary piece of information that will be reused often.

NOTE
We recommend output caching frequently accessed pages in your ASP.NET Web application whenever possible, but you should always follow up your tuning efforts with testing. Be careful not to go overboard because caching too much data can use valuable memory resources. To ensure that your caching implementation is effective, you can monitor the performance counter ASP.NET Applications\Output Cache Turnover Rate\Total. This counter should remain low or commensurate with the expiration or invalidation rate of the cached pages.

Output Caching

The ASP.NET output cache can use memory on the server to store the output of processed and rendered pages. If output caching is enabled, the output of a page is saved after the first request. Subsequent requests for the same page are then retrieved from the cache, if the output is still available, and returned to the user bypassing all the overhead of parsing, compiling and processing. This greatly improves the response time and reduces utilization of the server s resources.

This feature can easily be enabled for pages by including the OutputCache directive within the page. For example, to save the output of a processed page for a maximum of 60 seconds, using the most basic syntax, you can include the following directive in the page:

 <%@ OutputCache Duration="60" VaryByParam="None"%>

The Duration and VaryByParam attributes are required.

NOTE
It is recommended that pages which are output cached have a Duration of at least 60 seconds, or the turnover rate of the page may hinder rather than benefit performance.

For pages that are short lived but have potentially expensive-to-obtain data, it may be better to utilize the Cache object to cache and update the data as needed (see the section on Cache API below). The VaryByParam attribute allows you to save multiple versions of a page. For example, pages can be designed to produce varying output based on the values of the parameter sent. Specifying a value of None for the VaryByParam attribute saves the output for the page if it is accessed without any parameters. To save versions of the page for all combinations of parameters, you can pass a value of *. You must, however, be aware that caching multiple versions of a page will consume additional memory. To cache output based on a specific querystring parameter or form field within the page, you can specify the name of the parameter. Multiple parameters can be included by separating them with a semicolon. For example, if a page has a form with ProductCategory and Product fields, you can cache the output based on values supplied for these parameter with the following syntax:

<%@ OutputCache Duration="10" VaryByParam="ProductCategory;Product"%>

Besides the two required attributes that are supported by the OutputCache directive, there are three additional attributes all of which are optional; these are Location, VaryByCustom, and VaryByHeader. The Location attribute controls where the data will be cached (for example, the server or client). VaryByHeader can cache based on specific headers sent with the request, and VarybyCustom can be used to cache based on browser type when specified with a value of Browser or can be used to implement custom logic when supplied with any other value.

Fragment Caching

Fragment caching is similar to output caching in the sense that the directive is the same. This level of caching is used to cache portions of a page that are implemented as user controls and is also referred to as partial page caching or user controls caching. Fragment caching should be considered whenever there is a lot of information to cache and caching at the page level is prohibitive in terms of server memory and cache utilization. Again, as with output caching, fragment caching is best used to cache output that does not vary tremendously or for output that is resource intensive.

The Output directive to implement fragment caching has to be included as part of the file implementing the control. The Duration and VaryByParam attributes are required and are exactly the same as in output caching. Additionally, there is the VaryByControl attribute, which is specific to fragment caching and can be included only in the user control file.

 <%@ OutputCache Duration="60" VaryByParam="None"%>

Caching API

The caching API lets you save any piece of information in server memory that you want to reuse. For example, let us say that you need to display the product categories on a page in addition to other information. Rather than retrieving this information from the database with every request to the page, you can save the categories via the caching API. The most basic syntax to cache something is:

Cache("mydata"}() = "some data"

You can store entire data sets besides just strings and numeric data. Retrieving the cached data is just as simple:

X = Cache("mydata")

Other useful methods to be aware of are the Remove method, used to remove an item from the cache and the Insert method to add items to the cache. The syntax for the Remove method is:

(Cache.Remove("mydata"))

The Insert method is an overloaded method of the Cache object and has several versions. For example, the following version of the Insert method can be used to add an item to the cache with no external dependency and with an absolute expiration time of 120 minutes from the first time the page is cached:

Cache.Insert("mydata", mydata, nothing, _ DateTime.Now.AddMinutes(120), TimeSpan.Zero)

The last parameter in the previous example is known as the sliding window and can be used to set an expiration for a cached item relative to the time the item was first placed in or last retrieved from the cache The sliding value parameter can be thought of as the maximum length of time between successive calls that need to elapse before a cached item is removed from the cache. For example, to place an item in the cache for a maximum of 10 minutes between successive retrievals, you can use the following syntax of the Cache object s Insert method:

Cache.Insert("mydata", mydata, nothing, DateTime.MaxValue, _ TimeSpan.FromMinutes(10))

Disabling ViewState

ViewState saves the properties from one page (usually from a form) to the next by saving and encoding the data for each server control to a hidden form field rendered to the browser. The size and contents of the ViewState data can be determined by using the Trace directive at the page or application level as discussed in the previous section, Profiling a .NET Web Application. If many server controls are used, the size of the ViewState data can become quite large and hinder performance of your Web application. As a best practice it is advisable to disable ViewState unless you absolutely need to use it. You can disable ViewState by setting the property EnableViewState= false at the page or control level.

ADO.NET Tips

Most Web applications are built with a back-end database management system. Connecting to this data tier and manipulating the data is critical to application performance, among other factors such as the amount of data being transferred and the database design. This is where an understanding of the object model of ADO.NET becomes important. Using the correct object and right method can make a difference to application performance, especially under load. This section will highlight some of the recommended practices for retrieving and affecting data at the data source but is by no means exhaustive. The references listed at the beginning of the chapter are suggested for more detailed information on ADO.NET.

The .NET Framework ships with two .NET data providers: The OLE DB .NET Data Provider and the SQL Server .NET Data Provider. The OLE DB .NET Data Provider can be used to connect to any data source for which there exists an OLE DB Provider, for example Microsoft SQL Server or an Oracle database, but is primarily intended for non-SQL Server databases. For applications that use Microsoft SQL Server versions 7.0 or higher, the SQL Server .NET Data Provider is the better choice. This provider has been optimized specifically for SQL Server and implements some SQL Server specific functionality.

NOTE
Use the SQL Server .NET Data Provider with SQL Server versions 7.0 and higher.

SqlConnection Object

The first step in communicating with the data tier is to establish a connection with the database server. The SQL Server .NET Data Provider gives us the SqlConnection object for this purpose. Creating a connection is fairly straight forward; the following VB.NET sample code demonstrates opening a connection to the SQL server on the local machine and connecting to the Pubs database:

Dim strCnStr As String = "Data Source =.;" _ & "Integrated Security=SSPI;" _ & "Initial Catalog = Pubs" Dim objCn as New SqlConnection(strCnStr) _ objCn.Open()

By default, this data provider takes advantage of connection pooling. This helps reduce the overhead of establishing a connection each time it is requested because all of the work is done up-front when the first connection is established. It is important, to understand when this feature is taken advantage of. For a pooled connection to be utilized, the connection strings of all new connections has to match that of the existing pooled connections exactly. Even an extra space in the string will cause the .NET runtime environment to create a separate pool. In fact, the .NET runtime creates a separate connection pool for every distinct connection string. This implies that connections utilizing different usernames and password will fail to take advantage of pooled connections.

NOTE
It is recommended that applications either use integrated security whenever possible or implement a common application username/password that is shared by all users in order to improve the efficiency of the connection pooling usage.

The other factor that determines whether a pooled connection is utilized is the transaction context. A second connection will use a pooled connection as long as the transaction context is the same as the initial connection or does not have one at all.

Controlling the size of the connection pool is affected by specifying the min and max properties. This is important if you need to control the amount of memory utilized at the Web tier. If all pooled connections are active, any extra connection request will be blocked until one is relinquished or the connection time out has expired (the default is 15 seconds). The following code demonstrates setting these properties as part of the connection string:

Dim strCnStr As String = "Data Source =.;" _ & "Integrated Security=SSPI;" _ & "Initial Catalog = Pubs;" _ & "Min Pool Size=10;" _ & "Max Pool Size =100"

Another property that can have an effect on performance is the packet size. For applications that transfer large blob or image fields, increasing the packet size can be beneficial. In cases where the amount of data transferred is small, a smaller value for the packet size may be more efficient. The following code demonstrates setting this property as part of the connection string:

Dim strCnStr As String = "Data Source =.;" _ & "Integrated Security=SSPI;" _ & "Initial Catalog = Pubs;" _ & "Packet Size=32768"

SqlCommand Object

A common scenario for Web applications is the retrieval/modification of data from the data source. The SQL Server .NET provider implements the SqlCommand/DataReader and the DataAdapter /DataSet classes that allow the user to retrieve/modify the data. We only briefly discuss the SqlCommand/DataReader in this book; information on the SqlDataAdapter/DataSet classes can be obtained from other sources that deal specifically with ADO.NET.

The SqlCommand/DataReader is connection oriented and provides certain methods that can be leveraged to improve application performance. These methods include the ExecuteNonQuery, ExecuteScalar and ExecuteReader. Additionally the SqlCommand class implements the ExecuteXmlReader method for data returned in XML format. A description of these four methods along with an example (VB.NET Console application) for each follows. The examples make a connection to the NorthWind database, which by default is installed with Microsoft SQL Server.

ExecuteNonQuery Method

This method is typically used with Insert, Update, and Delete operations. The only piece of information that is most useful in these cases, and that is returned to the client, is the number of rows that are affected. This method will also work with stored procedures that contain output/return parameters, which can be returned to the client. The following Visual Basic .NET code demonstrates this method by calling a stored procedure that returns a count of the number of customers in the Customer table in the NorthWind database as a return value:

Imports System Imports System.Data Imports System.Data.SqlClient Module ExecuteNonQuery Sub Main() Dim strConnString As String = "Data Source=.;" _ & "Initial Catalog=Northwind;" _ & "Integrated Security=SSPI" Dim strSQL As String = "GetNumberOfCustomers" Dim sqlConn As New SqlConnection(strConnString) Dim sqlComd As New SqlCommand(strSQL, sqlConn) sqlComd.CommandType = CommandType.StoredProcedure sqlComd.Parameters.Add(New _ SqlParameter("@i", SqlDbType.Int)) sqlComd.Parameters(0).Direction = _ ParameterDirection.ReturnValue sqlConn.Open() sqlComd.ExecuteNonQuery() sqlConn.Close() Console.WriteLine("Number of customers = {0}", _ CType(sqlComd.Parameters(0).Value, Integer)) End Sub End Module

ExecuteScalar Method

This method should be used whenever you need to retrieve a single value from the data tier, for example, if you need a count of customers or the customer ID of a single customer. To demonstrate this method, the following Visual Basic .NET code retrieves the count of customers from the Customers table in the NorthWind database:

Imports System Imports System.Data Imports System.Data.SqlClient Module ExecuteScalar Sub Main() Dim strConnString As String = "Data Source=.;" _ & "Initial Catalog=Northwind;" _ & "Integrated Security=SSPI" Dim strSQL As String = "select count(*) from customers" Dim sqlConn As New SqlConnection(strConnString) Dim sqlComd As New SqlCommand(strSQL, sqlConn) sqlConn.Open() Dim o As Object= sqlComd.ExecuteScalar() sqlConn.Close() Console.WriteLine("Number of customers = {0}", _ CType(o, Integer)) End Sub End Module

ExecuteReader Method

Any time you need to return a single data row or multiple data rows containing a lot of columns, you should use this method. This method is useful for a one-time pass of the returned data only. To demonstrate this method, the following Visual Basic .NET code retrieves the customer ID, contact names, and phone number of customers in the Customers table in the NorthWind database.

Imports System Imports System.Data Imports System.Data.SqlClient Imports Microsoft.VisualBasic Module ExecuteReader Sub Main() Dim strConnString As String = "Data Source=.;" _ & "Initial Catalog=Northwind;" _ & "Integrated Security=SSPI" Dim strSQL As String = _ "select customerid,contactname,phone from customers" Dim sqlConn As New SqlConnection(strConnString) Dim sqlComd As New SqlCommand(strSQL, sqlConn) sqlConn.Open() Dim sqlDR As SqlDataReader = _ sqlComd.ExecuteReader(CommandBehavior.CloseConnection) Do While sqlDR.Read() Console.WriteLine(sqlDR("customerid").ToString() _ & ControlChars.Tab _ & sqlDR.GetSqlString(1).ToString() _ & ControlChars.Tab _ & sqlDR.GetSqlString(2).ToString()) Loop sqlDR.Close() End Sub End Module 

In cases where you are sure only one row is returned to the client, you can call this method by supplying the SingleRow value of the Command Behavior enumeration as a parameter. The syntax with this optional parameter is:

Dim sqlDR As SqlDataReader = _ sqlComd.ExecuteReader(CommandBehavior.SingleRow);

Data values in each row can be referenced either by name or ordinal position as illustrated in the example shown above. In general using the ordinal position of a data item achieves slightly better performance. Additionally, if you know the data types being returned, a further gain can be achieved by using the SQL Server .NET Providers type-specific methods to return data values. There are several such methods, such as GetSqlString and GetInt32.

TIP
Try to use the type-specific methods of the SQL Server .NET Provider whenever possible.

ExecuteXMLReader Method

This method is useful when data is returned from SQL Server in XML format. For example, to return the data in XML format, the SQL statement can be modified to instruct SQL Server to return the data in XML format. The example that follows demonstrates using this method:

Imports System Imports System.Data Imports System.Data.SqlClient Imports System.Xml Module ExecuteXmlReader Sub Main() Dim strConnString As String = "Data Source=.;" _ & "Initial Catalog=Northwind;" _ & "Integrated Security=SSPI" Dim strSQL As String = "SELECT customerid," _ & "contactname," _ & "phone " _ & "From customers " _ & "FOR XML AUTO" Dim sqlConn As New SqlConnection(strConnString) Dim sqlComd As New SqlCommand(strSQL, sqlConn) sqlConn.Open() Dim xmlR As XmlReader = sqlComd.ExecuteXmlReader() Do While xmlR.Read() Console.WriteLine(xmlR.ReadOuterXml()) Loop xmlR.Close() sqlConn.Close() End Sub End Module



Performance Testing Microsoft  .NET Web Applications
Performance Testing Microsoft .NET Web Applications
ISBN: 596157134
EAN: N/A
Year: 2002
Pages: 67

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net