Intent to Experiment: Stale-While-Revalidate

66 views
Skip to first unread message

Dave Tapuska

unread,
Jul 12, 2018, 2:58:45 PM7/12/18
to blink-dev

Contact emails

dtap...@chromium.org


Spec

Explainer

Design Doc

RFC 5861


Summary

Implement stale-while-revalidate processing in the Cache-Control header. Allow stale resources to be served from the cache while asynchronously revalidated.


Link to “Intent to Implement” blink-dev discussion

As per discussed on the I2I thread we don't send the revalidation requests to the ServiceWorkers (as per normal revalidation requests) and fetch APIs cannot request stale resources at this time.

A TAG review was requested by an individual in the discussion. An issue has since been opened.


Goals for experimentation

The metric Blink.ResourceFetcher.StaleWhileRevalidateDuration represents the time spent revalidating stale resources.  This can be used as a metric that approximates the benefit received in blocking resources.


Metrics collection on origin trial sites about benefits will be calculated. Specifically AMP will conduct an experiment from pages served from the AMP cache.


Experimental timeline

M69-M71


Any risks when the experiment finishes?

No


Ongoing technical constraints

None.


Debuggability

Devtools lists multiple requests when stale-while-revalidate occurs so it is clear to see that one was served from disk (or memory cache) and one from the network.


Will this feature be supported on all five Blink platforms supported by Origin Trials (Windows, Mac, Linux, Chrome OS, and Android)?

Yes


Link to entry on the feature dashboard

https://www.chromestatus.com/feature/5050913014153216


Chris Harrelson

unread,
Jul 12, 2018, 3:55:15 PM7/12/18
to Dave Tapuska, blink-dev
LGTM

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blink-dev+...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/blink-dev/CAHgVhZVGQUueyfv%2BTWcHOK%3DrR2WFSRgbx%3DYEUqNXjO3Pt3h6kg%40mail.gmail.com.

Ben Kelly

unread,
Jul 15, 2018, 7:40:40 PM7/15/18
to blin...@chromium.org
On Thu, Jul 12, 2018, at 2:58 PM, Dave Tapuska wrote:
As per discussed on the I2I thread we don't send the revalidation requests to the ServiceWorkers (as per normal revalidation requests) and fetch APIs cannot request stale resources at this time.

This means that a service worker that does a pass-through fetch handler like `evt.respondWith(fetch(evt.request))` will lose the benefit of the stale-while-revalidate optimization.

Do you think it would be possible to allow stale-while-revalidate to still take place if the `request.destination` matches one of your target subresource types?  (Or even better would be to spec and set a reasonable `request.cache`, even if script can't manually set this value itself.)

Just something to think about in the long term.  Thanks.

Ben

Yoav Weiss

unread,
Jul 16, 2018, 6:04:50 AM7/16/18
to Dave Tapuska, blink-dev
On Thu, Jul 12, 2018 at 8:58 PM Dave Tapuska <dtap...@chromium.org> wrote:

Contact emails

dtap...@chromium.org


Spec

Explainer

Design Doc

RFC 5861


Summary

Implement stale-while-revalidate processing in the Cache-Control header. Allow stale resources to be served from the cache while asynchronously revalidated.


Link to “Intent to Implement” blink-dev discussion

As per discussed on the I2I thread we don't send the revalidation requests to the ServiceWorkers (as per normal revalidation requests) and fetch APIs cannot request stale resources at this time.

Maybe I misunderstood, but my take from the I2I discussion was not that we should skip SwR for `fetch()` calls, but that it will not be directly observable for `fetch()` as the revalidation will happen at a lower layer.

Is there a specific reason why `fetch()` should ignore SwR while other request types shouldn't?

 

A TAG review was requested by an individual in the discussion. An issue has since been opened.


Goals for experimentation

The metric Blink.ResourceFetcher.StaleWhileRevalidateDuration represents the time spent revalidating stale resources.  This can be used as a metric that approximates the benefit received in blocking resources.


Metrics collection on origin trial sites about benefits will be calculated. Specifically AMP will conduct an experiment from pages served from the AMP cache.


Experimental timeline

M69-M71


Any risks when the experiment finishes?

No


Ongoing technical constraints

None.


Debuggability

Devtools lists multiple requests when stale-while-revalidate occurs so it is clear to see that one was served from disk (or memory cache) and one from the network.


Will this feature be supported on all five Blink platforms supported by Origin Trials (Windows, Mac, Linux, Chrome OS, and Android)?

Yes


Link to entry on the feature dashboard

https://www.chromestatus.com/feature/5050913014153216


Dave Tapuska

unread,
Jul 16, 2018, 9:34:01 AM7/16/18
to yo...@yoav.ws, blink-dev
Yes you are correct that that use case would loose that behavior. To ultimately fix this I believe the fetch API needs to be augmented to allow the indication that I am able to accept stale content and some indication that the resource returned was from the cache and was stale. But without that I think that the current proposal is a reasonable state that shouldn't cause incompatibilities it is just possibly suboptimal.

dave.

Ben Kelly

unread,
Jul 16, 2018, 1:27:28 PM7/16/18
to blin...@chromium.org
On Mon, Jul 16, 2018, at 9:33 AM, Dave Tapuska wrote:
Yes you are correct that that use case would loose that behavior. To ultimately fix this I believe the fetch API needs to be augmented to allow the indication that I am able to accept stale content and some indication that the resource returned was from the cache and was stale. But without that I think that the current proposal is a reasonable state that shouldn't cause incompatibilities it is just possibly suboptimal.

I hope that this will be integrated with the fetch spec (with an API or not) before the feature ships in GA.

Also, there are some other examples of features that require coordination with high level browser elements that have been implemented such that they don't break service workers.

For example, you may want to look at how script bytecode caching works.  That feature allows the high level <script> compilation code to stick the resulting bytecode back into the source cache that produced the network response.  This could be the http cache or Cache API.  The connection to the "source cache" is tracked internally through the fetch API Response object so that it works transparently with service workers.  Content script cannot observe the source cache information or the bytecode, but its carried along with the Response object.  (At least this is how firefox works and I've been told that chrome does the same thing.)

Maybe this approach could also be used to internally pass the cache staleness state information through the Response and implement SwR completely in the lower level?

Anyway, sorry to continue picking at this.  We spent a long time trying to spec out how the browser fetches resources so that we could implement service workers.  Just trying to help think of ways to support SwR without breaking service workers.

Thanks.

Ben

Kinuko Yasuda

unread,
Jul 17, 2018, 5:24:25 AM7/17/18
to b...@wanderview.com, blink-dev, Yoav Weiss
On Tue, Jul 17, 2018 at 2:27 AM Ben Kelly <b...@wanderview.com> wrote:
On Mon, Jul 16, 2018, at 9:33 AM, Dave Tapuska wrote:
Yes you are correct that that use case would loose that behavior. To ultimately fix this I believe the fetch API needs to be augmented to allow the indication that I am able to accept stale content and some indication that the resource returned was from the cache and was stale. But without that I think that the current proposal is a reasonable state that shouldn't cause incompatibilities it is just possibly suboptimal.

To clarify, my understanding is that implementation-wise doing this should be possible, and it feels what Yoav said (SwR will not be directly observable for `fetch()` but things should probably just work without skipping SwR) should probably just apply, but for experimenting it's probably good that we skip it for now.

And to Yoav's question reg: any specific reason why `fetch()` should ignore SwR: as far as I understand the current code (while Dave may have more reasons) we currently skip SwR logic for all raw resource types just because raw resource handling tends to be more convoluted and we wanted to play it safe for the initial experiment.  There can be also some corner cases on some type of Fetches (like background fetches, which are handled in the browser process) that won't be covered by the current implementation.
 
I hope that this will be integrated with the fetch spec (with an API or not) before the feature ships in GA.

Also, there are some other examples of features that require coordination with high level browser elements that have been implemented such that they don't break service workers.

For example, you may want to look at how script bytecode caching works.  That feature allows the high level <script> compilation code to stick the resulting bytecode back into the source cache that produced the network response.  This could be the http cache or Cache API.  The connection to the "source cache" is tracked internally through the fetch API Response object so that it works transparently with service workers.  Content script cannot observe the source cache information or the bytecode, but its carried along with the Response object.  (At least this is how firefox works and I've been told that chrome does the same thing.)

Maybe this approach could also be used to internally pass the cache staleness state information through the Response and implement SwR completely in the lower level?

​Chromium works similarly reg: the bytecode caching (while the part's also changing), and yes I believe we should be able to internally pass the info through the Response, while the current impl chose Blink to implement the SwR revalidation logic, which means we do it at a relatively upper layer than lower layer, so it's not like 'we just implement it completely in the lower level'.
 
Anyway, sorry to continue picking at this.  We spent a long time trying to spec out how the browser fetches resources so that we could implement service workers.  Just trying to help think of ways to support SwR without breaking service workers.

Thanks.

Ben

--
You received this message because you are subscribed to the Google Groups "blink-dev" group.

Yoav Weiss

unread,
Jul 17, 2018, 8:42:10 AM7/17/18
to Kinuko Yasuda, b...@wanderview.com, blink-dev
On Tue, Jul 17, 2018 at 11:24 AM Kinuko Yasuda <kin...@chromium.org> wrote:
On Tue, Jul 17, 2018 at 2:27 AM Ben Kelly <b...@wanderview.com> wrote:
On Mon, Jul 16, 2018, at 9:33 AM, Dave Tapuska wrote:
Yes you are correct that that use case would loose that behavior. To ultimately fix this I believe the fetch API needs to be augmented to allow the indication that I am able to accept stale content and some indication that the resource returned was from the cache and was stale. But without that I think that the current proposal is a reasonable state that shouldn't cause incompatibilities it is just possibly suboptimal.

To clarify, my understanding is that implementation-wise doing this should be possible, and it feels what Yoav said (SwR will not be directly observable for `fetch()` but things should probably just work without skipping SwR) should probably just apply, but for experimenting it's probably good that we skip it for now.

And to Yoav's question reg: any specific reason why `fetch()` should ignore SwR: as far as I understand the current code (while Dave may have more reasons) we currently skip SwR logic for all raw resource types just because raw resource handling tends to be more convoluted and we wanted to play it safe for the initial experiment.  There can be also some corner cases on some type of Fetches (like background fetches, which are handled in the browser process) that won't be covered by the current implementation.

Implementation-wise that makes sense. My main concern would be around potential developer confusion if SwR is working for some resource types but not others.
Reply all
Reply to author
Forward
0 new messages