General Observations: Testing Databinding Options
What to choose when you need to display rows of data from some data source:
In previous posts I have discussed programming design patterns that are impacted by performance testing. Frankly, I still stand behind those opinions that I have shared. However, not very often does one actually describe the benefits and the trade-offs that should be considered. So, let us take the most common scenario a developer has to deal with - displaying rows of data from some data source.
The Fastest Method: HtmlWriter
Why? It is fast because you render out the HTML directly to the page bypassing alot of extraneous page events.
Pros:
- In n-tier implementations, it can be used in the BLL (Business Layer) providing a seperation of UI and logic.
- Code safe to the degree of UI Designers can not muck with the output.
- Portable - it is easier to create a custom control that can be used in varying situations and follows strict business rules but also fixed UI presentation.
- It is the fastest method of spitting out rows of formatted data.
Cons:
- Difficult to write and maintain as one has to declare all the HTML markup in code-behind using StringBuilders etc...
- May not play well with Microsoft's Ajax in all situations, depending on the markup that is generated.
- Less control of the actual UI in terms of using Themes.
- Difficult to troubleshoot.
Example of HTMLTEXTWRITER used in a Tab Control...
override protected void RenderContents(HtmlTextWriter writer) {
// Dont't render for downlevel browsers
if (! _isUplevel)
return;
// Display the tabs
for (int i = 0;i < _tabs.Count; i++) {
Tab objTab = (Tab) _tabs[i];
writer.AddAttribute(
HtmlTextWriterAttribute.Href, String.Format("BLOCKED SCRIPTshowPanel('{0}')", objTab.PanelID));
writer.RenderBeginTag(
HtmlTextWriterTag.A );
writer.Write( objTab.Text );
writer.RenderEndTag();
if (i < (_tabs.Count - 1))
writer.Write(
" | " );
}
}
Inline Script: 2nd Fastest (In Most Cases)
Why? It is rendered with the page - on the page. It is almost as fast as the HtmlTextWriter method in most cases, depending upon the complexity of the data and code layers that the data has to be fetched from.
Pros:
- Quick and easy from the IDE to create pages that repeat data.
- Can use actual controls in the presentation.
- Incredibly fast.
Cons:
- No code seperation. Does not seperate the UI layer from the BLL layer. And in most cases, even the DAL will be all integrated into the page.
- Clunky and unmanagable code. UI Designers can take it upon themselves to change the logic and therefore introduce new issues.
- May be more difficult to troubleshoot issues.
- Can not be effectively re-used across the application(s).
Custom Repeator Controls:
If designed properly a Custom Repeator Control can be within 5-10% of the Inline Script programming style in terms of all out performance.
Pros:
- Allows even further code seperation.
- Allows for use of the HtmlTextWriter where appropiate.
- Provides re-usablity across the application(s).
- The controls can be updated and replaced with minimal impact to the code / pages it is referenced from or embedded upon.
- Greater re-use in terms of UI, as multiple ascx files can inherit the control code and thus provide the ability to change formatting and presenation of the data from code-behind in the applications logic.
- Supports custom paging easier than the two above listed entries.
Cons:
- Controlling the proper hierachy of those controls that are being added.
- More actual code and maginally larger memory footprint in some cases.
- Can be more difficult to troubleshoot especially in Ajax enviroments.
Custom Repeator Controls are what most developers whom subscribe to n-tier design practices and want performance - use for displaying data from any data source. It offers the best flexibility in design versus performance.
GridView and the Repeator Control - Least fast.
Why? These are controls that are ladened with features to make the controls as drag and drop friendly in the IDE as well as present the most flexibility in terms of binding to numerous types of data sources. As a result - the performance of the GridView and Repeator (non custom - it is marginally faster than the gridview in some situations) is upwards of 20% or more slower than Custom Repeator Controls or the Inline Script.
Pros:
- Even a Caveman can use it...Super simple for novice programmers to hook up to data and display it.
- Tons of tutorials on ASP.Net in how to flex all of the options.
- Minimal design work needed as it handles most of it.
- All of the events can be handled and overridden in code behind so it can be used in custom controls and can play well in n-tier designs with abstraction from the various layers.
Cons:
- Performance. The larger the recordsets are - the least performant it will be. For example pulling back 100 records and displaying them takes approximately 30% longer to do than a Custom Repeator Control displaying the set of records.
- Paging feature does not work well when not binding directly to a SQL DataSource. However, most people implement custom paging which also works around this particular Microsoft Ajax issue.
- It is not CSS friendly unless you implement the CSS Adapter.
- It can be fairly complicated code-wise to maniplate the data for display in a n-tier design.
The GridView is by far better than the Asp.Net 1.1's DataGrid. And merely, because of the huge impact performance wise - I personally only use it in areas of my web applications where there would be nominal impact. For instance in a administration section - only a handful of people would ever use it it so the impact is low on the servers. For mocking up quick and dirty designs before implementing a Custom Repeator Control - is another good use.
Summary:
For each problem a developer must tackle there is the good, the bad and outright ugly solution. Not everyone is writing applications that 'have to scale' right now. Different developers have different goals for why they are developing. However, understanding all of the options - and the general caveats each programming option provides is beneficial for the long term - no matter who, why, or what you are developing solution for. And while performance does not necessarily mean the application can scale horizontally - it does usually mean that the server can scale vertically.
Best suggestion of all - is test - test - test. And when testing these various options do so under 3 different scenarios such as:
1. Pull back 10 records and display them.
2. Pull back 100 records and display them.
3. Pull back 1000 records and display them.
I further recommend testing these scenarios using a datasource that is cached during the duration of the testing to remove database induced bottlenecks. And do use a actual stress tool to simulate 100's of users accessing the page and do not rely on the 'micro' loop and timer test method. You'll get much more disparency and seperation of the results in testing the options in a 'live and similiar' enviroment that is similiar to how the code will be used in a production enviroment.....
There are alot of varying opinions and the likes and these are my general observations based on results from my own lab tests. Naturally, results can be influenced merely based on other optimizations of code structure or lack of them. So, actual mileage will vary...as will opinions on the matter.