Open Bug 1304391 Opened 3 years ago Updated 2 years ago

massive delay loading image from javascript

Categories

(Core :: ImageLib, defect, P3)

48 Branch
defect

Tracking

()

People

(Reporter: ossman, Unassigned)

References

Details

(Whiteboard: [gfx-noted])

Attachments

(2 files, 1 obsolete file)

User Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:48.0) Gecko/20100101 Firefox/48.0
Build ID: 20160819105407

Steps to reproduce:

Execute the following:

    var img = new Image();
    img.addEventListener("load", onload);
    img.src = "data: image/jpeg" + Base64.encode(data);



Actual results:

onload fired a whopping 30 ms later.


Expected results:

onload should have fired within 1 ms.

This makes noVNC (a popular web based VNC client) behave like **** on Firefox. For comparison Chrome loads the image without returning from JavaScript, and it does so in under 0.2 ms. I.e. Chrome has a 15000% performance advantage here.

I've tried polling using setTimeout() and requestAnimationFrame(), but it is the same delay.

I'm not sure what to do here?
could you provide a live testcase?
Flags: needinfo?(ossman)
Attached file load.html (obsolete) —
Here's a simple test case. Click the buttons with a performance recording active and examine the results.

Oddly I am seeing two different behaviours from Firefox here. Sometimes it loads the images right away (img.complete set directly), and sometimes I need to wait for the load event. I'm not sure what triggers it. I added a level of indirection via setTimeout(), but it doesn't seem to have much effect.
Flags: needinfo?(ossman)
See Also: → 1304663
Status: UNCONFIRMED → NEW
Component: Untriaged → DOM
Ever confirmed: true
Product: Firefox → Core
Whiteboard: [lang=js]
Edgar might be able to shed some lights here...
Flags: needinfo?(echen)
(In reply to Pierre Ossman from comment #2)
> Created attachment 8793641 [details]
> load.html
> 
> Sometimes it loads the images right away (img.complete set directly),

If we could find image in cache (image has already been requested), then we load image from cache and set img.complete directly.

> and sometimes I need to wait for the load event.

Otherwise, we need to start a request to load image, and we set img.complete after image is loaded completely (happens asynchronously).

In both cases, we fire load event.
Flags: needinfo?(echen)
(In reply to Edgar Chen [:edgar][:echen] from comment #4)
> 
> If we could find image in cache (image has already been requested), then we
> load image from cache and set img.complete directly.
> 

I take it data uri images are also cached then, given that I seen this effect in the attached test? 

It's a bit odd that I sometimes have to wait for a load event though. Can it get evicted from the cache that quickly?

> 
> Otherwise, we need to start a request to load image, and we set img.complete
> after image is loaded completely (happens asynchronously).
> 

Which is annoying, but acceptable. What is not acceptable is the long delay before the event. The image does not take that long to decode so it seems something is being polled rather than firing once there is something to do.
Maybe jdm has thoughts on the delay mentioned in comment 5?
Flags: needinfo?(josh)
Priority: -- → P3
Any ideas?

I played around with the performance test tool in noVNC which tries to run a Websocket data stream recording as fast as possible. In this I added instrumentation for how long it takes for the "load" event to fire. The mean value was as follows:

 Chrome 54 on Fedora 24: ~1.5 ms
 Firefox 49 on Fedora 24: ~4 ms

 Chromium 54 on RHEL 6: ~1.5 ms
 Firefox ESR 45 on RHEL 6: ~12 ms

These differences probably account for the difference in time it takes to perform the entire test, which takes ~2x longer on Fedora, and ~5x longer on RHEL. Bug 1312701 might also affect things though.

Also note that Chrome tends to not require us to wait on the "load" event, so it may be even faster than the numbers here suggest.
Attachment #8793641 - Attachment is obsolete: true
I've been playing with my modified testcase, and the longest set of delays I've observed ranges from 15ms to 27ms as described.
Flags: needinfo?(josh)
Which is to say, in one single run (that loads 10 images), the shortest delay was 15ms, and the longest was 27ms.
(In reply to Pierre Ossman from comment #7)
> 
> These differences probably account for the difference in time it takes to
> perform the entire test, which takes ~2x longer on Fedora, and ~5x longer on
> RHEL. Bug 1312701 might also affect things though.

Clarification: The entire test takes 2x/5x longer for Firefox compared to Chrome. E.g. 14 seconds instead of 7 seconds. :)
Presumably the problem here is that images with data URLs go through our usual async channel setup. That means at least three queued runnables (OnStartRequest, OnDataAvailable, OnStopRequest), and if there's a separate thread for decoding then that requires some more asynchronous operations.
Component: DOM → ImageLib
Attachment #8804319 - Attachment filename: file_1304391.txt → file_1304391.html
Attachment #8804319 - Attachment mime type: text/plain → text/html
Improved test case that ensures we get a print for every image in the async complete case, shows the order in which they complete and the time taken for individual images (not just in aggregate).
Perhaps a bit off topic, but is there a more efficient way of getting an image on to a canvas from Javascript? Converting it to a base64 string and back again seems somewhat wasteful.
Whiteboard: [lang=js]
There is bug 1092837 to remove the async-ness for data and blob uris.
Whiteboard: [gfx-noted]
You need to log in before you can comment on or make changes to this bug.