Open Bug 1138352 Opened 9 years ago Updated 2 years ago

CanvasRenderingContext2D.clearRect() very slow with clipping

Categories

(Core :: Graphics: Canvas2D, defect)

35 Branch
x86_64
Windows 10
defect

Tracking

()

People

(Reporter: daniel.rentz, Unassigned)

Details

(Keywords: perf, testcase, Whiteboard: [gfx-noted])

User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:35.0) Gecko/20100101 Firefox/35.0
Build ID: 20150122214805

Steps to reproduce:

Use canvas clearRect() method with a single rectangular clipping area.


Actual results:

Clearing rectangles with clipping area is much slower than without clipping.

Test case:
http://jsbin.com/napodinudi

Output Firefox:
fillRect, no clip: 23ms
fillRect, clipped: 21ms
clearRect, no clip: 29ms
clearRect, clipped: 1545ms

Output Chrome:
fillRect, no clip: 25ms
fillRect, clipped: 17ms
clearRect, no clip: 23ms
clearRect, clipped: 22ms


Expected results:

Clearing rectangles should work as fast as without clipping.
Thanks for the report and for the testcase!

I can't reproduce on Mac, and this looks like it might be OS/graphic-driver specific.

Could you copy the data from the Graphics section of about:support <https://support.mozilla.org/en-US/kb/use-troubleshooting-information-page-fix-firefox> here and also look up the graphics driver version?

Also it might be worth re-testing with the most recent pre-release version <https://nightly.mozilla.org/>, first creating a new Firefox profile <https://support.mozilla.org/en-US/kb/profile-manager-create-and-remove-firefox-profiles#w_creating-a-profile>.
Component: Untriaged → Canvas: 2D
Keywords: perf, testcase
Product: Firefox → Core
Using latest release (FF 36.0.4), latest graphics driver. Can still reproduce. Maybe Windows only?

Graphics info:

Direct2D aktiviert	true
DirectWrite aktiviert	true (6.2.9200.16571)
Geräte-ID	0x0fd4
GPU #2 aktiv	false
GPU-beschleunigte Fenster	1/1 Direct3D 11 (OMTC)
Karten-Beschreibung	NVIDIA GeForce GTX 660M
Karten-RAM	2048
Karten-Treiber	nvd3dumx,nvwgf2umx,nvwgf2umx nvd3dum,nvwgf2um,nvwgf2um
Subsys-ID	21151043
Treiber-Datum	3-13-2015
Treiber-Version	9.18.13.4788
Vendor-ID	0x10de
WebGL-Renderer	Google Inc. -- ANGLE (NVIDIA GeForce GTX 660M Direct3D9Ex vs_3_0 ps_3_0)
windowLayerManagerRemote	true
AzureCanvasBackend	direct2d
AzureContentBackend	direct2d
AzureFallbackCanvasBackend	cairo
AzureSkiaAccelerated	0
Results with Nightly 40.0a1:

fillRect, no clip: 13ms
fillRect, clipped: 13ms
clearRect, no clip: 17ms
clearRect, clipped: 695ms
Is this still an issue?
Flags: needinfo?(daniel.rentz)
Well, just try it out. Link to test case has been given in the initial report.
  http://jsbin.com/napodinudi

Results with FF 41.0.1:
fillRect, no clip: 14ms
fillRect, clipped: 13ms
clearRect, no clip: 23ms
clearRect, clipped: 511ms

So, yes, still an issue.
Flags: needinfo?(daniel.rentz)
Whiteboard: [gfx-noted]
It looks like things improved for you between Firefox 35 and 41. I've tested this locally on my Macbook Pro and I confirm the issue but I think I've also found a regression.

Results after 10 testruns:
> Chrome 45 scores 42ms over 10 testruns
> Firefox 24 scores 127ms over 10 testruns [202% worse than Chrome]
> Firefox 40 scores 537ms over 10 testruns [1179% worse than Chrome, 323% worse than Firefox 24]
> Firefox 44 scores 561ms over 10 testruns [1236% worse than Chrome, 342% worse than Firefox 44]

At the very least I'm marking the bug as confirmed. However we probably need to investigate the major perf regression before we can begin to look at competitiveness.
Status: UNCONFIRMED → NEW
Ever confirmed: true
(In reply to Anthony Hughes, QA Mentor (:ashughes) from comment #6)
> > Firefox 44 scores 561ms over 10 testruns [1236% worse than Chrome, 342% worse than Firefox 44]
(Typo: this should read '342% worse than Firefox 24')
Severity: normal → S3

Any progress after 8 years? Still happens for me.

OS: Windows 7 → Windows 10

Looking at the code, I have a suspicion this microbenchmark itself is problematic, and not so much our code. In that fillRect may just be queuing an operation that Direct2D is not actually doing at the time of the request. It's just building a command-list to do it which is close to free, until the graphics pipeline is flushed. Clearing in Direct2D (https://searchfox.org/mozilla-central/source/gfx/2d/DrawTargetD2D1.cpp#402), however, might be having the side-effect of flushing the graphics pipeline and forcing all the preceding renders to actually happen, so then you have to pay for all of that work that has been queued up. At least, that's the going theory for the moment. Someone would have to look into this more deeply to see if it is really something fixable, or merely what I suspect above? Bob, does this sound plausible-ish?

Flags: needinfo?(bobowencode)

I have updated the Bin, each command is now running in its own timeout, separated by 1 second. Same results.
https://output.jsbin.com/vusiyesidu
Would this speak against your suspicion?

improved bin, with changed order function calls (clearRect before fillRect)
https://jsbin.com/pumijupaca/edit?html,js,output

I did a look at this in the profiler, and indeed what is happening is it is causing a pipeline flush. You can reproduce the same performance issue with fillRect by using globalCompositeOperation = 'copy' which is actually what is needed for fillRect to really approximate what is happening with clearRect.

To work around this in the simplest way, we'd need to make the code better at detecting that the path it is clipping against is actually just a suitable rectangle, which would let us bypass the slower path we're using in select simple clip cases. Ideally though we'd want something less awful for dealing with 'copy' in general, though.

Once the canvas code gets into the actually mechanics of how things are processed in Direct2D I have very little experience. Looks like you confirmed your suspicion anyway.

Flags: needinfo?(bobowencode)
You need to log in before you can comment on or make changes to this bug.