nik codes

More HTTP Flushing in ASP.NET MVC

My last post about HTTP flushing in ASP.NET MVC generated quite a bit of buzz and several really good questions. If you haven’t yet, I recommend you read that post before continuing on here. With this post I’ll answer some of the questions that arose about flushing early and offer a few handy tips.

When to Flush?

Steve Souders does a great job of explaining this technique in his book, Even Faster Web Sites, and on his blog, but there still seems to be some confusion about flushing. For example, Khalid Abuhakmeh mentioned that it “seems arbitrary where you would place the flush” and asked:

tweet

While one could certainly flush lots of small chunks of content to the client, and there may be circumstances that call for doing just that, this recommendation is specifically aimed at (1) improving the user’s perceived performance and (2) giving the browser’s parser and network stack a head start to download the assets required to render a page.

Given that, the more content that can be flushed early, before any expensive server side processing (e.g. database queries or service calls), the better. Typically this means flushing just after the </head> tag, or just before the first @RenderSection()/@RenderBody() Razor directive.

Here’s an example of the difference that flushing makes on a waterfall chart displaying network activity:

difference

Notice that in the “Before” image, the two style sheets and one JavaScript file that are referenced in the the <head> section of the page aren’t downloaded until the original HTML file has finished downloading itself. When flushing the <head> section, however, the browser is able to start downloading these secondary resources and rendering any available HTML immediately – providing the user with visual feedback even sooner.

What’s more, if the style sheets contain rules that reference tertiary resources (e.g. background images, sprites or fonts) and the flushed HTML matches one of those rules, the tertiary resources will be downloaded early as well. Ilya Grigorik, a developer advocate that works at Google on the Chrome web performance team, recently wrote an a post about font performance with the tip to optimize the critical rendering path – which flushing directly helps with.

So basically, it’s best to flush as much of the beginning of an HTML response as you can to improve perceived performance and give the browser a head start on downloading not only secondary assets, but often times tertiary ones as well.

How can I See the Improvement?

The effects of flushing early is most easily seen on a waterfall chart. (New to waterfall charts? Check out Tammy Everts’ excellent Waterfalls 101 post.) But how does that correlate to the user’s experience? That’s where Speed Index comes in. Speed Index is currently the best metric we have to measure the perceived performance of a page load. WebPageTest.org measures Speed Index for any given page by doing a series of screen captures of the loading process, analyzing the images over time, and producing the metric.

logo_wpt

compare_progress
Screen captures of a loading page

chart-line-small
Speed Index comparison of two loads

The WebPageTest documentation covers the algorithm for calculating the metric in depth, and offers suggested targets based on the Alexa Top 300K. The lower a site’s Speed Index, the better.

Personally I’ve never seen flushing early increase a page’s Speed Index. In general, I can’t think of a way that it would hurt performance, but you may not need to use the technique if you don’t have anything in the head to download or any server side processing. As always, your mileage may vary and you should test the results on your own site.

What About Compression?

You should still compress your responses, flushing doesn’t change that recommendation! Compression affects the content that is sent to the client (and adds a Content-Encoding: gzip header).

Flushing, on the other hand, affects how the content is sent to the client (and adds a Transfer-Encoding: chunked header.)

headersHTTP Response with Compression and Flushing in Fiddler

The two options are completely compatible with each other. Souders reported some configuration issues with Apache flushing small chunks of content – but, based on my testing,  IIS doesn’t seem to have these problems. Using the default configuration, IIS compresses each chunk of flushed content and sends it to the client immediately.

How do I Debug?

Flushed HTTP responses are really no different that any other HTTP response. That means the in browser F12 development tools and HTTP proxies like Fiddler work as expected.

One caveat worth mentioning though is that Fiddler, by default, buffers text\html responses, which means that when Fiddler is running the benefits of flushing early won’t be observable in the browser. It’s easy enough to fix this though, simply click the “Stream” icon in the Fiddler toolbar, as covered in the Fiddler documentation.

streamIn Stream mode Fiddler immediately releases response chunks to the client

Are There Any Other Considerations?

Since flushing early is done in the name of giving the browser a head start, be sure to provide the browser’s parser everything it needs to efficiently read the HTML document as soon as possible.

Eric Lawrence, ex-product manager for Internet Explorer, has a post detailing the best practices to reduce the amount of work that the parser has to do to understand a web page. Essentially, begin HTML documents like this and the parser will not have to wait or backtrack:

<!DOCTYPE html>
<html>
<head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <base /><!-- Optional -->
     <title>...</title>
     <!-- Everything else -->

What’s the Easiest Way to do This?

I’ve created a simple open source project called PerfMatters.Flush that attempts to make flushing early in ASP.NET MVC as simple as possible. It’s still very alpha-y, but it’s already live on the getGlimpse.com homepage. You can play with the bits now, or wait for my follow up post that details how to use it.

About these ads

Single Post Navigation

6 thoughts on “More HTTP Flushing in ASP.NET MVC

  1. Pingback: Flushing in ASP.NET MVC | nik codes

  2. There is nothing saying that the Razor code has to be compiled after the controller action returns. Because everything is passed into the resulting razor view like a compiled method. Essentially you could wrap your controller code in a lazy function and execute it after you call the first flush for the header.

    Something like this very crude mock up could happen after the first flush.

    @{ Response.Flush() }
    @{ Model = ExecuteAction() }

    Now this goes against everything we have learned about separation of concerns and testability. And heightens the places problems could occur especially if an error occurs in executing the action.

    Alternatively Rosyln might help out here by allowing us to prerecompile the razor view before the model is passed in and then execute and flush anything that comes before the first model call.

    This wouldn’t work in all cases especially for controllers that return more than one result depending on execution path. However the the number of return paths should also be able to be calculated by Roslyn to determine if preflushing can be supported.

    Interested to hear your thoughts on my idea.

  3. nikmd23 on said:

    I originally played around with something like that as well.

    I ended up shying away from it for the same reasons that you mention.

    What I’d really like to see is the ability to put a marker in a layout file (eg @FlushPoint) and be able to use a filter to flush everything up to that point. (Essentially automatically splitting the view in two, which PerfMatters.Flush forces a user to do manually.)

    Concerning Roslyn, I’m not sure that will help much. Razor syntax is “compiled” into C# first by the Razor engine – that’s what I *think* would need to change.

  4. Pingback: Les liens de la semaine – Édition #72 | French Coding

  5. Pingback: PerfMatters.Flush Goes 1.0! | nik codes

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: