Closed Bug 1014058 Opened 10 years ago Closed 10 years ago

script[async] downloads are blocked on CSSOM

Categories

(Core :: Networking: HTTP, defect)

x86
macOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla34

People

(Reporter: igrigorik, Assigned: mcmanus)

Details

(Keywords: perf)

Attachments

(1 file)

User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36

Steps to reproduce:

Example page: http://jsbin.com/qefefiyi/7/quiet

For additional context: https://www.igvita.com/2014/05/20/script-injected-async-scripts-considered-harmful/


Actual results:

A CSS file at the top (2 second RTT), and two <script async> scripts at the bottom. The scripts are "discovered" by the parser, but the download is deferred until CSS is available.. Why?

WPT trace on nightly: http://www.webpagetest.org/result/140521_0X_548e3fdcce144c6b0e2c080bb6544943/


Expected results:

Chrome [1], IE [2], Safari [3] all download the files immediately. I expected FF to do the same. 

[1] http://www.webpagetest.org/result/140521_Z1_2641991126afb2eddbc7be3d9c9b6bc9/
[2] http://www.webpagetest.org/result/140521_11_0edb77ba1d0c8cde8851d2f18a5ebf79/
[3] http://www.webpagetest.org/result/140521_EW_4e8bc7183f256dfd7d35711f95494718/
Component: Untriaged → HTML: Parser
Product: Firefox → Core
I wonder if this could be negatively impacting our b2g app launch times.  We have some significant CSS in those apps and a large number of <script async> resources.  Granted, all the resources are on local disk, so maybe its not completely relevant there.
Keywords: perf
bz, henri, why can't we execute these scripts before css?
> but the download is deferred until CSS is available.. Why?

We certainly call AsyncOpen() on the channel before the CSS is done loading.  What happens on the necko level after that, I don't know, but it's not returning us the data until after the CSS loads.  Once we get the data, we run it, and would even if the CSS were loading, as far as I can tell based on code inspection.
Component: HTML: Parser → Networking: HTTP
Flags: needinfo?(mcmanus)
we intentionally hold back async stuff in the necko scheduler that can interfere with the downloading of sync js/css from the head because in prior benchmarks that was the stuff that really killed us on time to first paint. you can make it parallel - but that doesn't invent bandwidth.

in general - it can wait because its async, but the css can't wait. You give up the benefit of parallelism using latent bandwidth, but you gain assurance that you aren't over-parallelizing and squeezing out bandwidth that is needed to get first paint. The bandwidth is finite - its a trade meant to help with responseiveness.

that's specifically an http/1 algorithm.. so wrt comment 1 it would only apply to b2g if b2g was doing these things over http to localhost using http/1 (I don't know if it is or not), and given its localhost it should not really add up to anything.

http/2 tosses this little hack away because it can do parallelism with priority.
Flags: needinfo?(mcmanus)
@mcmanus: given that all other browsers avoid the extra delay, this is unfortunate. Do you have any benchmarks showing the first-paint results?

I understand your reasoning, but I'm not convinced that "because its async it can wait". A good counter-example is analytics and other measurement beacons: many big sites today place a blocking script right in their head to ensure that they get their analytics beacons dispatched as early as possible -- analytics is not a "nice to have" but a "must have", even at the cost of delaying the first paint. When I ask them to defer these beacons, they report large loss in recorded analytics (north of 30%). As a result, we're stuck at an impasse (and slow first paints). 

script[async] is a simple way to solve this problem... and works everywhere but FF. I'm glad to hear that this is not an issue on http/2, but I'd love to see consistent behavior for http/1 as well.
Attachment #8464242 - Flags: review?(bzbarsky)
Assignee: nobody → mcmanus
Status: UNCONFIRMED → ASSIGNED
Ever confirmed: true
(In reply to Patrick McManus [:mcmanus] from comment #8)
> Created attachment 8464242 [details] [diff] [review]
> async scripts should run unblocked

forgot to add this comment when I uploaded the patch.

The current policy says that sync js/css in the head blocks pretty much everything else - including async js. And we've got test cases showing that to be a win when it blocks the images that generally follow.

But this bug suggests that async js could benefit from being loaded in parallel. The tests cases I've looked at don't argue with that one way or the other. (the key in them is the images).

So the change here is that async js can load fully in parallel along with anything else. They don't quite have the status of sync-head js in that they won't cause images to wait for them.
Comment on attachment 8464242 [details] [diff] [review]
async scripts should run unblocked

r=me
Attachment #8464242 - Flags: review?(bzbarsky) → review+
https://hg.mozilla.org/mozilla-central/rev/e264e7a813e5
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla34
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: