November 14, 2005
One thing I dislike about ASP.NET is that it renders the entire web page in memory before sending one single byte of that page to the browser. Consider an ASP.NET page with an embedded DataGrid that relies on ten complex database queries over 15 seconds. Why can't we serve up part of the page while we're waiting for those DataGrid queries-- so the user has something to look at? A blank page is a disappointing user experience. The strong psychological benefit of progressive rendering is well documented.
What's even more galling is that HTML was originally designed to render progressively as content is received. Internet Explorer is perfectly capable of rendering partial HTML content. Netscape offered progressive rendering as far back as version 1.0:
Netscape is the browser that introduced most all of the remaining major features that define a web browser as we know it. The first version of Netscape appeared in October 1994 under the code name "Mozilla." Netscape 1.0's early beta versions introduced the "progressive rendering" of pages and images, meaning that the page begins to appear and the text can be read even before all of the text and/or images have been completely downloaded. Version 1.1, in March 1995, introduced HTML tables, which are now used in the vast majority of web pages to provide page layout.
See progressive HTML rendering in action via this MSDN sample:
This particular sample is a demonstration of IE's table-layout attribute, which isn't even necessary for Firefox to render the table progressively. But it really doesn't matter which browser you use; the same "show as much as you can as soon as you can" rendering rule should apply to any web page you design.
If the pictured table was rendered as a DataGrid, progressive rendering support is moot. The page model of ASP.NET precludes a single byte of data being sent to the client until the entire page is rendered on the server. There's no opportunity for the browser to start displaying data to the user while the server is still chugging away on the data. The user is stuck staring at a blank web page for the full 15 seconds until the operation completes on the server.
You can still write ASP.NET pages that properly stream data to the browser using Response.Write and Response.Flush. But you can't do it within the normal ASP.NET page lifecycle. Maybe this is a natural consequence of the ASP.NET abstraction layer.
Regardless, it still sucks for users.
Posted by Jeff Atwood
I think part of the problem is the exception handling mechanism- you need to keep the whole page in memory just in case the 14th or 15th database call barfs, and you need to bounce to an error 500 page (which may or may not be nicely wrapped, depending on your web.config setup...)
if you can live without nice 500 errors, you could probably redesign the framework correctly- but most of the commercial sites I've worked for need them handled as cleanly as possible.
I think what sucks for users is rendering a complex datagrid on one page that takes 15 seconds to load in the first place. I would go so far as to say that if you actually *need* to stream data to the user's browser like that, you've got major problems elsewhere.
Jeff: What about @Page Buffer="False"? Doesn't that enable progressive rendering?
I would go so far as to say that if you actually *need* to stream data to the user's browser like that, you've got major problems elsewhere
The same rules apply if the server render time is 3 seconds. Why can't the client start seeing output ONE SECOND into that server render time? Why can't the server render time and client render time overlap?
It's certainly a better user experience.
And even if there is zero overlap, why not design your HTML markup so your pages render progressively? If you're sending down 40 kilobytes of HTML, it should render in some reasonably progressive way on the client at least.
One easy way to test this is to use the IIS 6.0 website bandwidth throttling mechanism. What do your pages look like when served over a 5 kilobyte/sec link? Or a 15 kilobyte/sec link?
Doesn't that enable progressive rendering?
Turning buffering off is a bad idea-- however, you can get the same effect by issuing periodic Response.Flush commands.
Unfortunately, doing this in the middle of the ASP.NET page lifecycle would produce unpredictable results (if it works at all).
Phil is correct. The Buffer attributes allows you to control this.
Streaming partial HTML documents with ASP.NET WebForm pages is just not a good idea. While browser support that there's no way the browser's going to actually have a sensible layout that it can go with.
If you really need progressive rendering you have to revert back to Response style coding where you build your page knowing that it has to render in pieces sequentially.
Other than that I'm with Scott - if it's really that slow use AJAX to pull data into your grid or whatever after the page has been loaded up otherwise...
I develop and support an application that basically shows report data in tabular format. I do have the table layout attribute set to fixed and I do see the content before the whole table is loaded. The customers are still complaining because they cannot scroll through the table ( 650 rows) until the whole table is rendered/loaded. We gave them option of Pagination but they are not willing to click. What can I say...I am just a developer.
I did try doing with Div's although offline ... that is I manually generated a report with same number of rows and did not find any noticable difference in the rendering latency.
Any suggestions / best approaches with HTML table rendering would be appreciated.
I diskike the progressive rendering "feature" of Firefox. Is there a way to disable it using about:config ?
I think part of the problem is that ASP.NET has such poor performance. I've had the opportunity to write a second version of some applications at a new job using Python+Django on a WAMP stack. The original versions were ASP.NET 1.1 on IIS/SQL server. I haven't had to spend any time "optimizing" my HTML rendering because its practically instantaneous.
At its core, HTML is pretty simple, and I think the ASP.NET framework - which tries to map a VB-style event-driven forms model on top of a very different technology - is all backwards.
I know some people love ASP.NET (I used to be one of them). But after working with it for a couple of years, I felt like I was always fighting it and never really happy with the results. I figured there had to be a better way so I started looking around, and for me, I found one.
The core issue that I've run into, related to this, is related to the page event lifecycle of an ASP.NET page. Most processing (data calls, calculations, etc.) occur within the Init, Load, and maybe even PreRender stages of the page, but *all* of the rendering (sending HTML to the output stream) occurs within the Render phase.
One could, potentially, override the Render method and do all calculations, data calls, and rendering within that method, making use of Response.Flush at appropriate times, effectively much like one would in "classic" ASP. (One could even go so far as to write generic HTTP handlers that aren't driven by as much of a lifecycle of events, and literally write your staged rendering and querying code as you would have in ASP.) However, this would seem to lose much of the benefits of the structure of ASP.NET development... and just ain't the prettiest thing to code...
I've had cases where I'd like to be able to render parts of a page to the browser while still working on other parts (that might involve database calls or somesuch), and, due to these issues, found myself in the odd case of saying "This'd be easy in the old ASP, but is actually quite difficult in ASP.NET". :-/
If someone comes up with a good answer to this...
"I think part of the problem is that ASP.NET has such poor performance"
What poor performance? It is a compiled language for Heaven's sake..
I think part of the problem is that ASP.NET has such poor performance
What poor performance? It is a compiled language for Heaven's sake..
Andrei Rinea on July 9, 2007 11:21 AM
Andrei, are you saying that compiled languages and poor performance are mutually exclusive? If so, I'd say that you've got rocks in your brain.
I think it's the side effect of trying to make the ASP.Net pages mimic Winforms more closely. In order to do some event handling processes (mainly .DataChanged) they came up with the pretty boneheaded ViewState; in order for that to be built, it needs to know what data it's stuffing into the ViewState and it can't know that until it's rendered all of its elements.
ASP.Net 2.0 has mechanisms to chunk out the ViewState into maximum sizes (see Dino Esposito's blog at http://weblogs.asp.net/despos/archive/2005/09/28/426137.aspx for a bit on it), not that I can see any direct use for this other than bloating pages even further (is the MTU crippling that many web apps?). That said, since ASP.Net 2.0 can chunk out the ViewState into multiple parts, there's no reason that it shouldn't be able to build out the ViewState chunks as it receives the data that's going into it, letting it render the page progressively. I guess we'll have to wait for ASP.Net 3.0 for that?
Alternatively, they could have designed the system to store ViewState on the session/HTTPState instead of posting down the hidden data that the user needs to post right back in the first place.