Tuldok Lambat's Tech Blog

Tuesday, November 29, 2005

Ugly-Printing: Reducing Your Page Content Size

Previously we talked about the idea of compressing the ViewState and the idea of persisting it on the server to reduce the content size of your .aspx page. In addition to those ideas I’ll be discussing with you yet another way of speeding up your .aspx web pages.

Pretty-printing…

The developers of ASP.NET had put lots of effort in formatting the HTML source of our .aspx page and did so pretty well, just right click your browser and select View Source to see what I mean (Figure 1). These were all well and good for those who know how and care to peek under the covers of your web pages but does it really matter to the average user? For all we know, the average user care less if the underlying HTML source is pretty-printed or not. What matters to them, besides your content of course, is the speed at how it delivers its content in front of them.

Free Image Hosting at www.ImageShack.us

Figure 1. Pretty printed HTML source.

The Filter property

The HttpResponse class exposes a Filter property that you could peruse to filter (and modify) the contents of the resulting HTML. This is just what we need to remove the extraneous character (mostly whitespace characters like carriage-returns and tabs) that ASP.NET deliberately put in for pretty-printing, in addition we could also extend our filtering scheme to include removing HTML comment, script comments, spaces between operators (like a + b when a+b will suffice) and etc. for further reduction. You can also try obfuscating your scripts using this scheme. Think of the endless possibilities.

Digression

Staying young and beautiful almost always has a tradeoff. You’ll spend lots of effort and time to maintain one’s beauty, just asks my missus and she’ll tell you. So why stay young and die early in the process (because you worry often that you’re getting older) when you can get old earlier and live longer.

Ugly-printing…

The digression above was just rhetorical but it holds true in computer processing. Agile method proponents always wants to keep everything simple because they acknowledge that most user care less if the system is aesthetically pleasing as long as it work and gets the job done. Most likely such system will be used longer than a system that is aesthetically pleasing yet doesn’t work at all. What I’m really saying is, why pretty-print when we can ugly-print for better user experience.

Using the HttpResponse.Filter and setting up our filter mechanism is not complicated but it’s not trivial either. What we need is a class that derives from the abstract Stream class with the required members implemented (see your MSDN documentation), especially the Write method, where the actual filtering process takes places.

public class UglyPrint : Stream
.
.
public override void Write(byte[] buffer, int offset, int count)
{
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
string inputstring = Encoding.ASCII.GetString(data);

inputstring = Regex.Replace(inputstring, @">[\s\S]*?<", new MatchEvaluator(Evaluate));

data = Encoding.ASCII.GetBytes(inputstring);
strSink.Write(data, 0, inputstring.Length);
}

protected string Evaluate(Match m)
{
string ms = m.ToString();
ms = Regex.Replace(ms, @"\r\n\s*", "");
return ms;
}
.
.
}

Here I made use of the Regular Expression class (Regex) to find the pattern “>[\s\S]*?<”, the pattern basically meant, all white spaces and/or non-white space between the “>” and “<” symbol. If we found such pattern, it will call the Evaluate function and further search the matched string with symbols “\r\n\s*” which meant all carriage-returns followed by zero or more white spaces and replaces them with an empty string.

Now, that we have setup the filtering class. It’s now time to use in our page. Just add the following snippet in the Page_Load event.

this.Response.Filter = new UglyPrint(this.Response.Filter);

or inherit from the ZipPage class (included in the example), like so:

public partial class DynamicNodes_aspx : ZipPage
{
.
.
}

This System.Web.UI.Page derived ZipPage class implements the UglyPrint class and the classes from the ViewState Compression and Persistence blog.

That’s it and you’re done. Run the page and try viewing its source in the browser (Figure 2).

Free Image Hosting at www.ImageShack.us

Figure 2. After ugly-printing the page.

Now, that’s what I call a mess. It’s ugly but it’s faster and because it’s hard to read you are well off from other prying eyes. Also from the snapshot below (Figure 3) you’ll see how much the page was reduced from 17,881 to 16,861. This may seem not much but that’s just because our filtering scheme is simple and did not strip of white spaces inside the scripts. But like I mentioned earlier we could still extend the filtering scheme and make it more robust.

Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us
Figure 3. Shows the size difference before and after ugly-printing the page.

Conclusion

Think of the combine effect of compressing the ViewState or persisting it in the server with this idea of ugly-printing and you’ll get an idea of how much less your .aspx page now weigh. You need not worry how long this overhead takes because it depends on the complication of your filtering scheme but nonetheless a lighter page means a faster delivery.

Note:
Please take note that the above example leaves lot to be done. The filtering logic in the code above is simple and just serves as a proof-of-concept.

Downloads: http://www.megaupload.com/?d=2HHKPJ8J

6 Comments:

  • Nice post bro, i'll try this one of these days

    By Anonymous dehranph, at 9:07 PM  

  • Thanks dehranph. We're planning to actually use this in real-world application. I've already made a prototype that would further squeeze the rendered HTML i.e removed HTML comments, script comments, etc. I'm also planning to use this idea to programmatically move all javascripts at the end of the content so as to make the page render faster (this is just theoretical though) or move it and save it on a .js file so that browsers won't have to download it again and again. But I haven't really thought about it though. But you can try. :)

    By Blogger Tuldok Lambat, at 10:50 PM  

  • very nice post!!
    It works very well, really a good idea!

    I think it could be used also for external js file.. but does it could be applied?

    By Anonymous Anonymous, at 1:51 AM  

  • Nice post, it works but it replace strange symbols instead of à,è,ò,...
    Some solutions?

    By Anonymous Anonymous, at 10:27 PM  

  • Cannot get what you mean by "it replace strange symbols instead of à,è,ò...". Kindly elaborate. Thanks.

    By Blogger Tuldok Lambat, at 9:13 AM  

  • Hey how are you doing? just letting you know that someone from Central America read your blog!

    Regards,
    Charles
    virtual and shared hosting

    By Anonymous virtual and shared hosting, at 9:49 AM  

Post a Comment

<< Home