Improving Web Site Performance Through Stress Testing
by Dev Noronha
Introduction
I cannot stress (excuse the pun) how important this exercise really is!!
Since the advent of web applications development, with never ending client
requirements and project deadlines due yesterday, Stress Testing (not to
be confused with Functional Testing) was often overlooked. Stress Tests
tell you the number of concurrent users your application can handle before
performance starts to degrade. Lets get into the 'Why' before I tell you
about the 'How'.
The 'Why'
Web applications have the additional overhead of having to maintain state
because the server just spits out HTML after processing your ASP page. The
web server is quite dumb that way because it doesn't remember a thing
about each client session. The programmer needs to create and maintain
several digital 'Post-It's' for the web server to remember what the client
state was. These details, called session objects, are stored at the server
FOR EACH client during her stay at your site. Hence, performance degrades
with every additional user hitting your Web server and making processing
slower for all users.
One should also Test the capacity of components used on the site.
Components 'block' calls (add to the IIS ASP Request queue). This means
that if a component is able to service 20 calls to it per minute but is
called 100 times per minute then it becomes the 'dead weight' of your
application and spoils the good work of the rest of the system.
Darn those Christmas Shoppers!!
Studies show that the average Web user does not wait for more than 10-15
secs for the page to load before leaving for a rival site (and there are a
lot of them!!). With click-happy, impatient web customers one can't take
chances. On a fateful day in December 1998, an overloaded server of a
popular e-commerce site caused an outage of 4 hours. The Cost: $400,000!!
If only the web master had read my article!! Even more damaging is the
perception of the company by the customer; the users do not care why the
outage happened, they just surmise that the service is bad. One could just
rollout the app and pray, but a prudent web master would find out the max
load (concurrent users) her application and server can handle.
The 'How'
Now that I've convinced you about the gravity of Stress Testing, let's get
into the tools you need. You could use Microsoft's Application Center Test
which comes bundled with Visual Studio .NET. The concept is simple really.
You can record a typical user session on your web site (ACT captures the
browser session as you glide from page to page), tell the program how many
simultaneous users it needs to simulate, the duration of the test (7-8
hours gives you clearer results), the parameters it needs to capture
(Processor Utilization, Memory Usage etc.) and run it. A real time graph
gives you the 'worms' of the parameters you chose to monitor as the test
progresses and ACT pounds away at you site. Creating a test and running it
is super simple. Before you open IE and go to your favorite search engine
for articles on ACT, check out the 'Help' section in ACT. It is extremely
well written and easy to understand.
You could tinker with your code, run the test several times, and check the
results to see which coding practices improve performance. This not only
improves the quality of your site, all future projects will be optimal
from day 1 because best practices become second nature to the coder.
Tips to improve your site performance
In any Web Based System, the well being of 3 elements affect the overall
performance of the application: Web Server, Database, ASP pages.
Obviously, sufficient bandwidth and hardware is assumed to be thrown at
the application. But a common misconception is that additional hardware
and bandwidth is the panacea whenever performance starts to degrade. Badly
designed applications sitting on even super high-end machines can bring
the server down on its knees at the slightest load. Memory leaks by COM
objects are the bane of many a web site.
I thought I might as well throw in some tips I picked up during my Web
development experience on how to improve performance of ASP pages by code,
database and IIS optimization
-
Open Recordsets just before accessing them and close them ASAP.
-
Regulate Queueing and Number of Processor Threads in IIS . Say the
Request Queue is set to 100 . This means that 100 clients will get the
hourglass on their screen while while the ASP engine churns out their
request. The 101'st client onwards will get a 'Server Too Busy' message.
The problem with having a high Request Queue value is that even if the
client closes the window, her request is still in the queue and when it is
finally taken care of, it has nowhere to go. As I mentioned earlier, most
clients don't hang around for too long. So it's quite possible that a
large chunk of the requests at the bottom of the queue get processed for
nothing. So you need to think carefully before setting this property.
-
Session variables limit scalability. They require server resources and
also bind a client to a specific machine because they cannot be shared
across machines in a server farm. It is better to use Hidden Fields,
Querystrings, Cookies or Files and Database to maintain state as much as
possible.
-
Use .HTM files when possible as they never block and get maximum caching
benefits. ASP files are generally blocked. So if the file contains pure
HTML (Interface files), give it an .htm extension.
-
Minimize the use of Server.CreateObject in your Asps whenever possible.
Try and use as few Record set objects as possible.
-
SQL Server should be on a separate machine from IIS / MTS. The two
machines should have excellent connectivity, network should not be a
limiting factor. As far as possible avoid external dependencies (resources
not present on the Web Server).
-
Index the tables with large amounts of data, which are queried
frequently. Though indexing adds additional load, it provides a
performance boost in certain situations.
-
Use as many Stored procedures as possible. These are compiled (hence the
performance boost) SQL statements stored in SQL Server. Plus these accept
parameters and can be programmed. Frequently used queries or large SQL
statements are good candidates.
-
Data manipulation from Recordsets should be done at the query level
itself. Do not perform sorting, ordering etc. in the script.
-
If you're accessing a database, are you pooling your connections?
Pooling creates and maintains a store of connections to a database. As
applications open connections to a data store and subsequently release
them, a pool of open connections is built with complete authentication
information and connection properties. Then, if available, connection
requests to the same data store (with the same user authentication and
connection properties) are satisfied from the pool rather than by making
the connection on demand. They are released by the pooling mechanism when
they time out. When pooling is enabled, the database connection request is
satisfied from the pool rather than by reconnecting, reauthenticating and
returning (again) a validated connection to the application all of which
takes in a lot of resources.
-
ASP generally automatically closes and frees up all object
instantiations, still it is always a good idea to explicitly close and
free up object references yourself. If you're using connection pooling,
the faster you close and free your ADO objects once you're done with it,
the sooner it dumps the connection back into the pool than if you wait
until the page terminates and let the terminating page implicitly close
and free the ADO object.
-
Use Get string for populating tables from record set results from
database queries. This is a rarely used feature, which provides a
performance boost.
-
Wherever ASP objects are used it is better to store session or
querystring objects in a variable at the start of the page and
subsequently use the variable. The Engine needs to read the value of from
the Querystring collection each time which increases overhead.
StrName = Request.QueryString("name")
response. Write strName 'Better than response.Write
Request.QueryString("name")
Conclusion
Now that I've made you sufficiently worried about your applications, I
must hasten to tell you that this is only the tip of the iceberg. Best
coding practices don't come easy. It comes with a passion for
self-improvment.