My experiences with .NET
Thursday, March 31, 2005
10 Tips for Writing High-Performance Web Applications
Common Performance Myths
1) C# code is faster than VB code. (False)
2) Codebehind is faster than inline. (False)
3) Components are faster than pages. (Not in .NET)
4) Every functionality that you want to occur between two apps should be implemented as a Web service. (False, Web services should be used to connect disparate systems or to provide remote access to system functionality or behaviors. They should not be used internally to connect two similiar systems. While easy to use, there are much better alternatives. The worst thing you can do is use Web services for communicating between ASP and ASP.NET application running on the same server.)
MSDN
10 Tips for Writing High-Performance Web Applications by Rob Howard *Modified by Evan*
Tip 1 - Return Multiple Resultsets
Review your database code to see if you have request paths that go to the database more than once. Each of those round-trips decreases the number of requests per second your application can serve. By returning multiple resultsets in a single database request, you can cut the total time spent communicating with the database. You'll be making your system more scalable, too, as you'll cut down on the work the database server is doing managing requests. Use stored procedures.
// read the first resultset
reader = command.ExecuteReader();
// read the data from that resultset
while (reader.Read()) {
suppliers = PopulateSuppliersFromDataReader( reader );
}
// read the next resultset
reader.NextResult();
// read the data from that second resultset
while (reader.Read()) {
products = PopulateProductsFromIDataReader( reader );
}
Tip 2 - Paged Data Access
Pagin with the DataGrid requires all of the data to be bound to the grid. For example, your data layer will need to return all of the data and then the DataGrid will filter all the displayed records based on the current page. If 100,000 records are returned when you're paging through the DataGrid, 99,975 records would be discarded on each request (assuming a page size of 25). As the number of records grows, the performance of the application will suffer as more and more data must be sent on each request. Use store procedures. For example:
CREATE PROCEDURE northwind_OrdersPaged
(
@PageIndex int,
@PageSize int
)
AS
BEGIN
DECLARE @PageLowerBound int
DECLARE @PageUpperBound int
DECLARE @RowsToReturn int
-- First set the rowcount
SET @RowsToReturn = @PageSize * (@PageIndex + 1)
SET ROWCOUNT @RowsToReturn
-- Set the page bounds
SET @PageLowerBound = @PageSize * @PageIndex
SET @PageUpperBound = @PageLowerBound + @PageSize + 1
-- Create a temp talbe to store the select results
CREATE TABLE #PageIndex
(
IndexID int IDENTITY (1, 1) NOT NULL,
OrderID int
)
-- Insert into the temp table
INSERT INTO #PageIndex (OrderID)
SELECT
OrderID
FROM
Orders
ORDER BY
OrderID DESC
-- Return total count
SELECT COUNT(OrderID) FROM Orders
-- Return paged results
SELECT
O.*
FROM
Orders O,
#PageIndex PageIndex
WHERE
O.OrderID = PageIndex.OrderID AND
PageIndex.IndexID > @PageLowerBound AND
PageIndex.IndexID < @PageUpperBound
ORDER BY
PageIndex.IndexID
END
Tip 3 - Connection Pooling
To use connection pooling optimally, there are a couple of rules to live by. First, open the connection, do the work, and then close the connection. It's okay to open and close the connection multiple times on each request if you have to rather than keeping the connection open and passing it around through different methods. Second, use the same connection string. If you don't use the same connection string, for example customizing the connection string based on the logged-in user, you won't get the same optimization value provided by connection pooling. And if you use integrated authentication while impersonating a large set of users, your pooling will also be much less effective. The .NET CLR data performance counters can be very useful when attempting to track down any performance issues that are related to connection pooling.
Tip 4 - ASP.NET Cache API
System.Web.dll ( Cache, HttpRuntime.Cache property, the same object is also accessible through Page.Cache and HttpContext.Cache).
Tip 5 - Per-Request Caching
Whereas the Cache API Is designed to cache data for a long period or until some condition is met, per-request caching simply means caching the data for the duration of the request.
For example, in the forums application of Community Server, each server control used on a page requires personalization data to determine which skin to use, the style sheet to use, as well as other personalization data. Some of this data can be cached for a long period of time, but some data, such as the skin to use for the controls, is fetched once on each request and reused multiple times during the execution of the request.
To accomplish per-request caching, use the ASP.NET HttpContext.
Tip 6 - Background Processing
(Example)Indexing e-mail didn't need to happen on each request. Ideally, we wanted to batch this work together and index 25 posts at a time or spend all the e-mails every five minutes. The Timer class, found in the System.Threading namespace, is a wonderfully useful. An ideal situation for background processing.
Tip 7 - Page Output Caching and Proxy Servers
Page output caching by: <%@ Page OutputCache VaryByParams="none" Duration="60" %>
You can effectively generate the output for this page once and reuse it multiple times for up to 60 seconds. VaryByParams just happens to be required. For example, default.aspx?Reports=1 or default.aspx?Report=2 could be output-cached by simply setting VaryByParam="Report".
Tip 8 - Run IIS 6.0 (If only for Kernel Caching)
If you're using IIS 6.0, there is a nice little feature called kernel caching that doesn't require any code changes to ASP.NET. Recommended.
Tip 9 - Use Gzip Compression
I personally don't like this. This will increase CPU utilization (eventhough it can decrease the number of bytes sent by your server).
Tip 10 - Server Control View State
View state is a fancy name for ASP.NET storing some state data in a hidden input field inside the generated page. When the page is posted back to the server, the server can parse, validate, and apply this view state data back to the page's tree of controls. View state is a very powerful capability since it allows state to be persisted with the client and it requires no cookies or server memory to save this state. But there are a number of drawbacks. First of all, it increases the total payload of the page both when served and when requested. There is also an additional overhead incurred when serializing or deserializing view state data that is posted back to the server. Lastly, view state increases the memory allocations on the server. If you don't need this then turn it off by <%@ Page EnableViewState="false" %>
Uploading from .NET
I recently had to rewrote the uploading module that I wrote in Java to work in Servlet to work in .NET environment. I google and found several interesting articles and they all pindown to two things. First, I needed a HTML portion, which required a <input> tag in order for user to select the file.
<input id="myFile" type="file" runat="server">
And then, I had to added following line to save the file to the Web Server.
myFile.PostedFile.SaveAs("DestinationPath")You can find more about this by clicking here.


