ASP.NET
has taken some dramatic steps forward with caching. Many developers who
first learn about caching see it as a bit of a frill, but nothing could
be further from the truth. Used intelligently, caching can provide a
twofold, threefold, or even tenfold performance improvement by retaining
important data for just a short period of time.
Caching is often used to store
information that's retrieved from a database. This makes sense—after
all, retrieving information from a database takes time. With careful
optimization, you can reduce the time and lessen the burden imposed on
the database to a certain extent, but you can never eliminate it. But
with a system that uses caching, some data requests won't require a
database connection and a query. Instead, they'll retrieve the
information directly from server memory, which is a much faster
proposition.
Of course, storing information
in memory isn't always a good idea. Server memory is a limited resource;
if you try to store too much, some of that information will be paged to
disk, potentially slowing down the entire system. That's why ASP.NET
caching is self-limiting.
When you store information in a cache, you can expect to find it there
on a future request, most of the time. However, the lifetime of that
information is at the discretion of the server. If the cache becomes
full or other applications consume a large amount of memory, data will
be selectively evicted from the cache, ensuring that the application
continues to perform well. It's this self-sufficiency that makes caching
so powerful (and would make it extremely complicated to implement on
your own).
1. When to Use Caching
The secret to getting the most
out of caching is choosing the right time to use it. A good caching
strategy identifies the most frequently used pieces of data that are the
most time-consuming to create and stores them. If you store too much
information, you risk filling up the cache with relatively unimportant
data and forcing out the content you really want to keep.
Here are two caching guidelines to keep you on the right track:
Cache data (or web pages) that are expensive:
In other words,
cache information that's time-consuming to create. The results of a
database query or contents of a file are good examples. Not only does it
take time to open a database connection or a file, but it can also
delay or lock out other users who are trying to do the same thing at the
same time.
Cache data (or web pages) that are used frequently:
There's no point setting
aside memory for information that's never going to be needed again. For
example, you might choose not to cache product detail pages, because
there are hundreds of different products, each with its own page. But it
makes more sense to cache the list of product categories, because that
information will be reused to serve many different requests.
If you keep these two rules
in mind, you can get two benefits from caching at once—you can improve
both performance and scalability.
Performance
is a measure of how quickly a web page works for a single user. Caching
improves performance, because it bypasses bottlenecks like the
database. As a result, web pages are processed and sent back to the
client more quickly.
Scalability
measures how the performance of your web application degrades as more
and more people use it at the same time. Caching improves scalability,
because it allows you to reuse the same information for requests that
happen in quick succession. With caching, more and more people can use
your website, but the number of trips to the database won't change very
much. Therefore, the overall burden on the system will stay relatively
constant, as shown in Figure 1.
Many optimization
techniques enhance scalability at the cost of performance, or vice
versa. Caching is remarkable because it gives you the best of both
worlds.
2. Caching in ASP.NET
ASP.NET really has two types of caching. Your applications can and should use both types, because they complement each other:
Output caching:
This is the simplest type of caching. It stores a copy of the final
rendered HTML page that is sent to the client. The next client that
submits a request for this page doesn't actually run the page. Instead,
the final HTML output is sent automatically. The time that would have
been required to run the page and its code is completely reclaimed.
Data caching:
This is carried out manually in your code. To use data caching, you
store important pieces of information that are time-consuming to
reconstruct (such as a DataSet retrieved from a database) in the cache.
Other pages can check for the existence of this information and use it,
thereby bypassing the steps ordinarily required to retrieve it. Data
caching is conceptually the same as using application state, but it's
much more server-friendly because items will be removed from the cache
automatically when it grows too large and performance could be affected.
Items can also be set to expire automatically.
Also, two specialized types of caching build on these models:
Fragment caching:
This is a specialized type of output caching—instead of caching the
HTML for the whole page, it allows you to cache the HTML for a portion
of it. Fragment caching works by storing the rendered HTML output of a
user control on a page. The next time the page is executed, the same
page events fire (and so your page code will still run), but the code
for the appropriate user control isn't executed.
Data source caching:
This is the caching that's built into the data source controls,
including the SqlDataSource and ObjectDataSource. Technically, data
source caching uses data caching. The difference is that you don't need
to handle the process explicitly. Instead, you simply configure the
appropriate properties, and the data source control manages the caching
storage and retrieval.