Skip to content
This repository has been archived by the owner on Apr 21, 2023. It is now read-only.

Design Doc: Flush Head Early

Jeff Kaufman edited this page Jan 6, 2017 · 1 revision

Flush Head Early

Megha Mohabey, 2012-02-29

Objective

Improve the time to first byte and time to render by flushing the head section of the html document early. The head section has various processing information like scripts, styles etc and flushing it early will allow the browser to fetch and parse the head elements early.

Non Goals

  • Stuffing subresources of the document in the head section so that the browser preloads those. The Flush Subresources Early rewriter aims to do that.

  • Determining the static and dynamic parts of the page and flushing accordingly. Above the fold (Blink) rewriters already address that but require some configuration.

User Configuration

The exact UI of this rewriter can be decided later. However, this rewriter is aimed to be auto ON. Also, this rewriter will be disabled if Above the fold rewriter is enabled or any other rewriter is enabled which can get negatively impacted.

Basic Approach

  1. When an html request comes, lookup the property cache keyed by url.
    1. If the optimized head is cached and stable then flush it immediately without waiting for a response from the origin server.
      1. If the origin server responds before receiving a response from property cache, then do not use the response from property cache.
    2. Else cache the optimized head in property cache keyed by url from the response generated for this request.
  2. From the optimized response generated for the request, check whether the property cache entry matches with the response. 3. If it is a match do nothing. 4. Else 2. send a js to reload. 3. update the property cache with new value.

Design Alternatives

There are various ways in which we can handle head section mismatch

Send the head section again

Con:

  • Browser will end up requesting and executing similar content/resources twice.
  • May cause some pages to break.
  • Double execution of java scripts.

Send the diff between the two heads again.

Pro:

  • Reduces the amount of redundant information which is requested and executed twice by the browser.

Con:

  • May cause some pages to break.
  • Elements which are order sensitive need to be sent again.

Send a small js to reload/redirect

  1. Set a cookie to disable flush_head_early_rewriter and reload. Or send a redirect with flush_head_early_rewriter disabled in query parameter.

  2. When the pss server receives this request, it will unset the cookie and not apply the rewriter for this request

Pro:

  • we don't serve broken pages

Con:

  • Extra RTT for the html page.

Combined approach

3. If the script nodes have changed then do reload.
4. else
    1. delete all the elements in the old head except the script nodes and the nodes added by the scripts.
    2. send the new head after removing the script nodes.

Pro:

  • Double applying of javascript can be dangerous and this avoids that case.

Con:

  • If the scripts are modifying some of the head elements then this may still result in broken pages.

Conclusion

Instrument the speed gains and stability of the rewriter before implementing. Use "reload/redirect" option for handling head section mismatch.

Open Issues

(and requirements from property cache)

  1. Headers also need to be flushed early which might have cookies.
    1. Handle this similar to Blink.
  2. How to preview this filter as this may not show any gains till the property cache has fully warmed up/ become stable.
  3. Also property cache "stability" metric has to be sufficiently robust to detect outlier changes.
  4. If the head section varies with every request, it may cause very high writes for cache. The property cache will need to have a feature to declare a key as uncacheable for some time if say last n cases were not a match.

Below are some implementation details for my reference.

Detailed Design

(need to expand this)

  • Add a cohort in property cache for FlushHeadEarly.
  • When a request comes
    • Check if there is an existing entry for this url in property cache.
      • If its there and if it is stable then flush section
      • remember that head flush is made for this request.
  • FlushHeadEarlyRewriter
    • It will be a post render filter and extend HtmlWriterFilter.
    • If the cached head was already flushed for this request, it will inhibit flushing till its sees and keep all the storing the bytes seen in a string.
    • When its sees then it will check if it is a match with the entry in property cache.
      • If match then nothing to flush. Subsequent bytes are flushed correctly.
      • Else,
        • if the response headers do not have any VARY other than Accept-Encoding add this entry to the property cache.
Clone this wiki locally