The ASPSmith's Blog

Some rants about ASP.NET by Steven Smith

April 2003 - Posts

Caching and Callbacks

I gave my second presentation to a user group for INETA this evening (well, last evening - it's late).  I spoke to about 70 members of the Philadelphia .NET user group, Philly .NET, about ASP.NET Performance Tips and Tricks and the Caching support in ASP.NET.  While I was discussing callbacks and the CacheItemRemovedCallback delegate that can be specified when an object is inserted into the cache, one of the users asked me a question that I wasn't sure of the answer to.  In my example, I was doing something like this:

//create an instance of the callback delegate

CacheItemRemovedCallback callBack =

new CacheItemRemovedCallback(onRemove);

 

Cache.Insert(cacheKey,System.DateTime.Now.ToString(),null,

System.DateTime.Now.AddSeconds(5),

System.Web.Caching.Cache.NoSlidingExpiration,

System.Web.Caching.CacheItemPriority.Default,

callBack);

...

private void onRemove(string key,

object val,

CacheItemRemovedReason reason)

{

//create an instance of the callback delegate

CacheItemRemovedCallback callBack =

new CacheItemRemovedCallback(onRemove);

Cache.Insert(key,val.ToString() + suffix,null,System.DateTime.Now.AddSeconds(5),Cache.NoSlidingExpiration,

System.Web.Caching.CacheItemPriority.Default, callBack);

}

The question then was, since I wasn't using a static method for my callback, would the .NET runtime keep an instance of this page around in memory so that it was available for this instance method I was calling.  I thought that that couldn't be right, since it seemed like it would potentially be quite a bit of overhead to keep around, since there was no telling how big and complex my page instance might be.  The right answer, I said, was to use a static method for the callback in this case, since it did not depend on the state of the page.  However, I didn't have a good answer to the question.

So after modifying my example slightly to depend on some stateful instance data in the page, I found that yes, indeed, the caching API does keep a copy of the page instance available so that it can call the instance method I specified as the callback.  This is good to know, since that could have implications on scalability as well as potentially cause some strange behavior if theinstance data of the page were somehow to cause the callback to behave differently in different situations, unintentionally.

Thanks for the good question!

Test Driven Development Article
Eric Gunnerson at Microsoft has published an article on Unit Testing and Test Driven Development (he calls it Test First Development).  It does a good job of introdcuing the concept of TDD and showing how to use NUnit to perform unit testing of a class before and during its construction.  Another good resource I've found for TDD is the TDD Yahoo Group.  I'm hoping to write a few articles on the use of NUnit for data access component testing as soon as I'm finished with the redesign of ASPAlliance.com's article management system (which was to have been done last week).
Windows Server 2003 Notes

I set up Win2K3 Server on a box at home a few days ago and here are some of the things I've learned.  The first thing I'd like to point out is that there is a pretty good Unofficial FAQ maintained by Windows XP MVP Larry Samuels.

The machine I installed on is a Dell Dimension 4100, P3-1GHz with 512MB ram.  It has a DVD player that was flaking out under XP Pro for some reason (no sound during movies, otherwise fine).  I was at the brink of requesting a new DVD player from Dell, but I managed to get it to work after the Win2k3 install.  Here's what I had to do:

  1. Enable graphics acceleration.  This is under an Advanced button in the Display properties box.  You can get to it either from Control Panel or by right-clicking on the desktop.
  2. Enable the Windows Audio service.  Gotta have this for sound.  This is in the Sounds section of the Control panel.
  3. Install a DVD decoder.  You can buy one from MS if need be for like $20.  For some reason Win2k3 doesn't come with one despite its huge price tag and WinXP does (and you can get WinXP for like $49).  In my case, I was in luck -- I installed the Dell Intervideo WinDVD software that came with the machine and it worked fine under Win2k3.
  4. Games: To get most games to work, follow these same steps, but then enable DirectX, which is disabled by default.  Go to a command prompt or the Start-Run prompt and type "dxdiag".  Click OK.  Click on the Display tab, then click on the Enable button for DirectDraw and Direct3d.

Once this was done, I was able to watch DVDs using either WinDVD or WMP on the machine, which is good news because my wife wants to be able to use it to entertain Ilyana while she's working on her computer.  I was also able to get Ghost Recon to work as a test to see if the OS would support games.  The PC has an old GeForce2 card that seemed to work just fine without any need to download drivers.

The next thing I did was try and install Exchange.  The end goal is to be able to share my schedule with my family, something that Outlook Express and Outlook do not support without a Server product (insane overkill for a family's needs).  I got IIS set up and played with ASP.NET 1.1 a bit, and once I'd finally gotten all of its prerequisites installed, I tried to install Exchange 2000 only to learn that it was not supported.  So I'm now downloading the Exchange 2003 Beta 2 and I'll probably install that tomorrow.

 

When is it OK to use a DataReader

I just responded to a discussion on this topic on the ASP.NET Forums...

There is a good article on the actual performance characteristics of DataReaders vs. DataSets on MSDN here.  In it, you will find that DataSets are not always slower than DataReaders, especially when there is any significant latency between the web server and the database server or when there are a limited number of connections available.  Still, a DataReader is generally going to be the fastest way and almost always the least resource intensive (memory) way to pull some data from the database.  However, that speed is not the only basis on which you should make your decision on whether or not to use it.

In addition to raw performance, another important consideration is what I call dummy-proofing.  If you pass an open DataReader back from a Data Access Layer in an N-Tier application so that someone else can use it on a web form, you are asking for trouble.  You're depending on that individual to know how to properly clean up the DataReader and to remember to do so, and it is completely out of your hands whether or not they do so.  If they do not, it can have severe consequences on the application's performance.  You're basically handing them a loaded gun with the safety off and hoping they know which end the bullet comes out of.

When I teach or present on this topic, I offer some guidelines that I've come up with that help one to determine whether to use a DataReader or another data container (like a DataTable or a strongly typed custom class).  Here are the conditions that must exist in order for you to use a DataReader:
1) You do NOT need to cache the data.
2) You do NOT need to serialize the data via web services or remoting.
3) You are NOT delegating responsbility for cleaning up the Reader beyond code that you immediately control, either a function or a class.  Passing between application layers is definitely ill-advised.
4) You do not want to use the updating capabilities of the DataAdapter to do batch updates.


 

More Posts