Open Bug 631632 Opened 11 years ago Updated 7 years ago

Performance of putImageData() greatly degraded since FF 3.6


(Core :: Canvas: 2D, defect)

Windows 7
Not set




(Reporter: phrogz, Unassigned)


(Depends on 1 open bug, )



(3 files)

User-Agent:       Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b10) Gecko/20100101 Firefox/4.0b10
Build Identifier: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b10) Gecko/20100101 Firefox/4.0b10

As seen on the test URL, Firefox 3.6 was able to put 83k pixels per second (on my machine) when using putImageData() for a single pixel, and 64k fillRect() per second. In FF 4.0b10 the fillRect() rate has nearly doubled (yay!) but the putImageData() performance is now 80x slower.

Reproducible: Always

Steps to Reproduce:
1. Visit
2. Press "Run tests" button
3. Observe the test results shown under the "Compare results of other browsers" section at the bottom of the page.
Actual Results:  
The performance of the "1x1 image data" test is roughly two orders of magnitude worse than the performance of the "fillRect" test.

Expected Results:  
The performance of the "1x1 image data" test should be comparable to--or slightly better then--the performance of fillRect. It should be no slower than the results of running the same test on the same machine for a build of Firefox v3.6

Note that the results at the bottom of the page are averaged across all browsers and machines that have been tested; look at the result in the "Run tests" column for the same machine to compare between different browsers.
What do the numbers look like if you disable hardware acceleration?  The two operations you're describing interact _very_ differently with the GPU.

For what it's worth, on a Mac (so canvas is not GPU-accelerated), I see both operations double in speed from 3.6 to current 4.0 betas.
Note that this test is doing 1x1 putImages; basically, it's testing overhead of doing that operation, and is generally uninteresting otherwise.  The overhead absolutely increased for D2D on Windows, but a more interesting test would be > 1x1, maybe 400x400 or similar.  But maybe the "get/putImageData" test is doing that?  Not sure.

Also, see bug 625267 and bug 631640.
Vlad, the test is testing a way to color an individual canvas pixel.  I have no idea why one would want to do such a thing, but apparently people do...

If turning off D2D improves this, then this is probably dependent on bug 625267.  But note that on Linux getImageData is slow as hell (for the obvious reasons), but the 1x1 put is actually fast.  So I wonder whether we can make the put at least faster on Windows too.

What the get/put test does is for each pixel it gets the whole 800x300 imagedata, changes that one pixel, then puts it.  We can do that about 200 times per second on the reporter's machine, apparently.  Just putting a single pixel we can do 1500 times or so.  In other words, the overhead is about 15% of even the 800x300 putImageData call.
If I uncheck the "Use Hardware Acceleration when Available" option in the Advanced section of Options I get 102k for fillRect and 145k for 1x1 on my machine. When I enable it, quit and restart Firefox and run the tests again I get 106k for fillRect and 1.7k for 1x1. It definitely seems to be related to the hardware acceleration.
Yeah, that seems pretty unfortunate.  Bas, any ideas?  Are we ending up reading stuff from the GPU for a putImageData call?  Or is any SOURCE operation just really slow?
Depends on: 625267
Ever confirmed: true
I updated the give cpp source,
so now, when a small piece of canvas is supposed to be drawn, the called putImageData function does not process the whole canvas anymore, and then just draws the requested part because that was making it slow.
I will upload a small file which shows the speed gain for a drawing of a 100x100 rectangle which is around 50 faster than without .
Attachment #8579341 - Flags: review+
Christos, would you mind attaching a diff instead of the entire file?

Also, you probably want to request review on the diff, not mark it review+.
This file shows like I said before the time needed (and the eventual speed gain) to draw the rectangle (100x100) on the given canvas (1600x800).
For given size, it needs around 1 second, with the updated source it is around 20-30ms for the same drawing.
One other thing.  That testcase has nothing to do with this bug as originally filed, since it's specifically about a case in which the dirty rect is smaller than the entire imagedata, while this bug was filed on a 1x1 imagedata.

Please spin off the small-dirty-rect case to a separate bug?
Flags: needinfo?(christos.alewa)
(In reply to Not doing reviews right now from comment #7)
> Christos, would you mind attaching a diff instead of the entire file?
> Also, you probably want to request review on the diff, not mark it review+.

Ok sorry, i will fix that right away..
Flags: needinfo?(christos.alewa)
Attachment #8579341 - Flags: review+
Attached file These are the changes
Comment on attachment 8579356 [details]
These are the changes

Sorry..but how do i mark it as to be reviewed?
Attachment #8579356 - Attachment description: changes.txt → These are the changes
You set the review flag to "?" and put in the name of a module owner or peer for this code in the textbox (the textbox should offer some suggestions).

But again, you want to do this in a new bug, not this one.
Though it seemed to me that it's relevant (at least, more relevant than to other, existing bugs)
to this bug i will probably file a new one, then.
You need to log in before you can comment on or make changes to this bug.