Steve Smith's Blog
My recent DotNetRocks interview with Carl Franklin and Mark Dunn is live now. The three of us discuss our experiences as small business owners. I also did a show with Craig over at Polymorphic Podcast last week that should be live next week on caching and performance with ASP.NET. I did a similar caching show last year on dnrTV that runs through some nice demos and has sample code with it, but the show with Craig for PP adds a few more things (though without the screencast and demo code - audio only). I appreciate all feedback and hope you enjoy the shows!
DotNetRocks Talk on Business and Entrepreneurship
A couple of weeks ago I did a DotNetRocks show with Carl Franklin and Mark Dunn in which we discussed our collective experiences with running our own businesses. We had a good time and shared some of our lessons learned. In some ways it was similar to the discussions Julie Lerman and I have proctored a couple of times as Birds of a Feather talks at TechEd shows. Toward the end of the show, I recommended a book that I think any would-be entrepreneur should read, which is:
This book does a great job of explaining the difference between being really good at and passionate about a particular craft or skill (e.g. writing software) and running a business centered around performing that task (e.g. running a software or consulting company). As I write this, I'm thinking it's probably about time I re-read this book, as I'm quite certain I haven't fully grasped all of its lessons. Key takeaway: if you're excited about the former but not the latter, think hard (or find a partner) before going into business for yourself.
The DNR show is set to air on August 14th, so look for it then.
Anybody who's talked to me about web programming in the last 5 years or so knows that I'm a big fan of caching. However, in most of my presentations on ASP.NET caching, I don't get into the client side of things. Mainly this is because ASP.NET is a server-side technology and there's plenty of cool stuff to talk about on the server with regard to caching, and I truly think that's where the biggest performance wins are to be had (i.e. reducing expensive calls to databases and web services).
That said, a lot of bandwidth can be saved and the perceived performance of individual pages can be greatly improved with some client side caching. What I mean by client side is within the user's browser, or at the very least, at some proxy server nearer to the user than your web server. The way web servers and browsers determine whether or not to cache a particular request is by inspecting what headers are sent with it. The two most important headers (for caching) are Expires and Cache-Control.
Cache-Control determines whether or not the content should be cached at all. If it is set to private, then intermediate servers like proxy servers will not cache the content because it is (supposedly) meant for a particular user only. For instance, you wouldn't want to send user Alice her bank account details and then have user Bob make a request to your bank web site through the same proxy server for the same page and have him get back Alice's account details. However, some things you're perfectly happy to let proxy servers cache, such as perhaps your 25kb logo that's on every page of your web application. By making its Cache-Control header public, proxy servers may choose to keep a local copy of that file rather than re-fetching it from your web server with each request, saving on both bandwidth and latency. Further, browsers may cache the file as well. In practice, this varies with the browser and it usually helps if you also set the Expires header.
The Expires header should be set to a date, and as long as that date has not passed, proxy servers and browsers may decide to cache the contents of the request locally. Sometimes requests will be made for the content if it has been modified (using the If-Modified-Since header) in which case the server may choose to respond with a Not Modified 304. This still incurs round trips to the server, but the response only has headers, no body, so it uses minimal bandwidth. This allows browsers and proxy servers to periodically check to see if a resource has expired without having to refetch it in its entirety.
A useful tool for checking the cacheability of various URLs on your sites is http://ircache.net/cgi-bin/cacheability.py. This tool will let you see the headers that your resources return and will give you a graphical indication of the cacheability of the resource (green means cacheable; red means not so much). As a best practice, I recommend making all images immutable* and setting their Cache-Control to public and Expires to a far future date, such as "Sun, 17 Jan 2038 19:00:00 GMT". If the image needs updated, it should have a new URL and all references to it should be updated. This will ensure images are cached as effectively as possible and ensures that updates to images take effect immediately without waiting for various proxy servers to update their caches.
*Here I'm using immutable to mean that, once uploaded to a particular URL, the contents of the image never change. Obviously this only applies to static images, and not to dynamic charts, etc.
I've also recently been using Amazon S3 more and more, and have found that Bucket Explorer is a nice tool to use with that service. Here's a nice tutorial on how to set headers of resources within S3 using Bucket Explorer. Using S3 to host images is also nice because every bucket is a different subdomain (e.g. bucket.s3.amazonaws.com) and so with a couple of different buckets for images, css, javascript one can easily have 3 or 4 different domains involved in the loading of resources for a given page (with all static files coming from S3). Since browsers typically only open 2 requests to a given domain at a time, this means you'll be able to utilize 8 simultaneous requests for content (best case) which can enable your page to load 4x faster than if it had all of its resources on a single domain (and only 2 simultaneous requests).
More Resources
Using S3 as a CDN (Content Delivery Network) Part 2
Microsoft has released SQL Server 2008 officially, according to this press release. The software is currently available to MSDN and TechNet subscribers:
SQL Server 2008 is now available to MSDN and TechNet subscribers and will be available for evaluation download on Aug. 7, 2008. SQL Server 2008 Express and SQL Server Compact editions are available for free download today at http://www.microsoft.com/sqlserver. As previously announced, pricing for SQL Server will not increase with SQL Server 2008. More information is available at http://www.microsoft.com/presspass/presskits/sqlserver.
Read the full press release for more details, or hop out to MSDN and begin downloading now before everyone else does! Oh, and check out the new UI for the MSDN subscription center, too - the filter is awesome!
DevExpress is one of several companies I work with via Lake Quincy Media, and it seems like a very fun place to work. Recently they launched a video site to help showcase their products, and earlier this week they made a video showing the reaction of some of their employees to the 5.4 scale earthquake in LA earlier this week. Check it out, and then check out some of their other videos as well.
Incidentally, Mark Miller (Miller in the video - the bald one...) also has his own blog and spoke at this year's TechEd. He's the brains behind CodeRush and Refactor and is a good guy to keep tabs on if you're interested in optimizing your coding experience (though he's not much of a blogger). He also participates in the show Mondays with some very funny stuff.
There are no single developer projects
Oren wrote today, There is no such thing as a single developer project. At first this sounds like an obviously false statement, but read on:
There are always at least two people in any software project:
- The developer who wrote the code.
- The developer who read the code.
They are never the same person, even if just by temporal dissonance.
This is a very clever thing to point out, and worth remembering when you're tempted to take shortcuts using the excuse "I'm the only one working on this code so I can wing it." Who you are today is not who you were yesterday, nor will you be the same person tomorrow. Write your code with the knowledge that someone else is going to have to maintain it, even if that someone else is you with a bit more experience (and probably a bit of lost knowledge about the details of what you're working on right at this moment).
Batch JavaScript Libraries for Increased Performance
I've been meaning to set up batched loading of the JavaScript libraries used by Lake Quincy Media's administration application for some time, and finally had a chance this past weekend. The site uses a variety of third-party tools such as DevExpress, ComponentArt, AJAX Control Toolkit, Overlib, PeterBlum, Dundas Charts, and probably a couple of others I'm forgetting at the moment. As a result, the site's initial load tended to be pretty sluggish. JavaScript libraries are loaded and executed serially by the browser, resulting in a pretty significant bottleneck to page load time, as shown here:
Once loaded the first time, most of these scripts are cached in the client, so performance doesn't remain dreadful (and usually the individual files don't take as long as they are above). However, you can see how this has a seriously detrimental effect on the site's perceived performance, and this has nothing to do with any kind of server or database processing time (which is typically the first place folks go looking for performance issues within ASP.NET applications).
While researching this problem I found a couple of helpful links:
- Combine Multiple JavaScript and CSS Files and Remove Overhead
- Client-side caching for script methods access in ASP.NET AJAX
More importantly, though, I discovered that the AJAX Control Toolkit project added a new ScriptManager object over a year ago that I'd overlooked. David Anson blogged about the new ToolkitScriptManager class last June, explaining its script combining features. Replacing my ScriptManager with this one resulted in an immediate and significant reduction in the number of ScriptResource.axd calls required. The ToolkitScriptManager inherits from ScriptManager, so you simply need to replace <asp:ScriptManager /> with <ajaxToolkit:ToolkitScriptManager /> assuming your prefix for the AJAX Control Toolkit is ajaxToolkit.
It's a good idea to use a separate domain for static files like images, CSS, and common scripts, because browsers typically will open 2 concurrent connections per domain to retrieve such things. However, in the case of scripts like these, the browser only loads them one at a time, and further since they're dynamic (at least, the *.axd ones), there's no simple way to use a separate domain anyway.
After switching to ToolkitScriptManager, I still had a bunch of dynamic script calls, which I determined were being loaded by ComponentArt controls. I figured they probably had a similar batch load mechanism, and they did not disappoint. Milos wrote about Optimizing Web.UI Client Script Deployment, which has the necessary steps. It requires setting up a handler and adding a key to <appSettings /> (something which I think is a bad idea for components to use), but otherwise it was quite painless.
Finally, I determined that the Overlib scripts we're using were only needed by one custom control we'd created for displaying Help dialogs, but the scripts were being included in the Master page. Many pages show the help dialogs, but many do not, and there were 4 separate scripts being loaded. I could have written my own handler or updated the custom control to automatically emit the required script references, but since I was going for the simplest thing that worked I opted to wrap the 4 <script /> tags in an ASP.NET Panel control and set its visibility to a property on the common base page. I then set this property to true from my Help control's Page property, after casting it to our base page class using the as keyword to ensure type safety.
The end result is shown here:
The scripts are still loaded serially, but there are far fewer of them, so the overall page load time is dramatically reduced. In this case I had to look at three different approaches for three different sets of scripts that I was using. However, it's possible to use an HttpModule to look at all of the resources on the page and batch them up into fewer requests. The links I listed above show some of this, but if you want an off-the-shelf solution, check out the Runtime Page Optimizer from ActionThis, which will do this and more. The product is still in beta, but it offers 9 different page load optimizations that take script, css, and even images and batch them up on the server and request them as fewer, larger chunks on the client. I've tested it and it's not quite 100% ready to go for my needs, but that's mainly because of some conflicts with the many different third-party tools I'm using. On simpler pages, it just works, so check it out if you want a simple solution to batching up scripts and other files to improve performance of your web application.
Avoid appSettings Usage in Controls or Shared Libraries
Since .NET 1.0, there has been a built-in appSettings section in configuration files. Many developers use this space to store application settings, such as the name of the site or (before <connectionStrings />) database connection information. However, many third party tools also make use of this collection, which is a bad practice. Third party tools should use their own configuration section, which is incredibly easy to do today (and wasn't all that hard in past versions), in my opinion. I'm curious to know why more companies don't do this, however, as the only thing I can see is that it's laziness or just "the way we've always done it" that's the reason.
Personally, I avoid using appSettings even for my own application configuration settings. Why? Because it really is too stinking easy to create your own custom configuration section, and this provides a much more readable and strongly typed way to access the values your application needs. AppSettings might be ok for a quick spike of a site where you're not doing anything "the right way" out of some desire for expediency, but otherwise it should be avoided. There are two reasons why I feel this way.
Global Scope and Naming Collisions
AppSettings is basically a global variable collection. There is nothing to prevent two separate control vendors from using the same key for their appSettings variable names. In practice this doesn't happen very often because vendors are smart enough to use long names (for the most part) that include their company and/or product name in them. However, this could easily be avoided (due to its being unnecessary) if a company- or product-specific configuration section were used instead.
Organization and Clarity
The second and arguably more applicable reason to avoid overusing appSettings for shared components is organization and clarity. There is zero discoverability of configuration options available within appSettings. The only way to figure out what is available to configure is the documentation. Further, once several different vendors' settings are intermingled in appSettings (along with a variety of actual site-specific settings), it can be quite a mess and quite long. This can result in errors when changes are made to the configuration settings.
Favor Custom Configuration Sections for Controls and Shared Code
Default configuration options should be distributed with the control in a self-contained section, making it easy for users to see the default values. Updates to the configuration file can then be as simple as cut-and-paste since the section is self-contained - there is less risk of the user screwing up the configuration instructions because they're trying to edit an already crowded and disorganized appSettings section in the configuration file.
VS Tip - Incremental Search in Visual Studio
If you're looking to navigate through the current file in Visual Studio, the typical approach is ctrl-F, which is the shortcut for Find and brings up a dialog like the one at right to locate instance of a string. Bertrand just let me know about another shortcut, ctrl-I, which does Incremental Search. The nice thing about this is that it's faster (there is a measurable delay before ctrl-F loads) and doesn't pop up a window that gets in the way of seeing your code. After pressing ctrl-i, as you type the cursor will move to the next string that matches what you've typed. Finding additional instances of the string is simply a matter of hitting F3.
Travel Gadget - Power Splitter
Something I always keep in my laptop bag is a Liberator power splitter. All this does is split one power outlet into two, with a little bit of extension cord thrown in for added convenience. You can find a wide variety of such things here.
Always Enough Power For You
So, what's the big deal about having one of these? Well, you could throw a whole power strip in your bag, but that's more bulk and weight. If you don't mind that, then go for it. Assuming you don't want to carry that, though, the benefit of a Y-splitter is that if you walk into a room (or conference session, where power outlets are always in short supply at geek conferences) you can simply unplug somebody's laptop (ask first), and then plug in the Y-splitter and plug them back in. Similarly, at the airport, if you're lucky enough to find a power outlet but it's in use by some folks charging their cell phones and iPods or using their laptops, you can unplug them (ask first...) and then plug yourself in along with them to your Y-splitter.
This has allowed me to get access to power outlets on many occasions, and is well worth the < $5 cost of the Y-splitter.

The E-Myth Revisited: Why Most Small Businesses Don't Work and What to Do About It