Open Bug 781287 Opened 12 years ago Updated 2 years ago

Clearing an Azure canvas on Mac is a lot slower than clearing a non-Azure canvas

Categories

(Core :: Graphics: Canvas2D, defect)

x86
macOS
defect

Tracking

()

People

(Reporter: bzbarsky, Unassigned)

References

()

Details

On http://jsperf.com/canvasclear/9 I see the following times on Mac with Azure canvas:

setting width: 693 ops/sec
full width height clearing: 8,052 ops/sec
partial clearing: 20,107 ops/sec

With non-Azure canvas, I see these numbers:
	
setting width: 125,480 ops/sec
full width height clearing: 1,923,503 ops/sec
partial clearing: 1,923,503 ops/sec

I haven't looked yet whether this is canvas/graphics code itself or binding code, but I will bet on the former while my opt build compiles.
This is likely explained by cairo's tracking of clearness. When you do a clear() on an already cleared surface it turns into a no-op. CoreGraphics doesn't track this and is doing actual work each time.

This is probably WONTFIX.
Hmm.  Would that explain the behavior for cairo when the rect being cleared is not the full surface?
(In reply to Boris Zbarsky (:bz) [In and out Aug 1 - 10, out Aug 11-20] from comment #2)
> Hmm.  Would that explain the behavior for cairo when the rect being cleared
> is not the full surface?

Yes, because the surface starts out as clear.
OK, so I looked into the parts here.

For setting width, there's 10% in mmap/munmap and another 50% under vm_fault.  Then there's the 20% under SetDimensions on the Azure context, which involves clearing and so forth.  Can we not at least fast-path the case when the backing store size didn't change and avoid creating all-new draw targets or something?

It looks like the non-Azure impl did faster here by lazily creating the surface, but still nuking it on every width set.  If I just add a drawing call between the width sets it gets just as slow as the new code.

For comparison, Chrome is about 15x faster than us if I _do_ change the width on each set and about 500x slower if I don't, even with draw calls in there.
For the "full width height clearing" case, if I insert draw calls we're about equally fast with azure and not.  Both are about 10x faster than setting the width, and about 50x slower than Chrome, but pretty comparable to Safari.

A profile there shows that all the clearRect time (which is 89% of the profile; the rest is the fillRect) is spent under CGContextClearRect, most of that in argb32_mark.  :(

For the "partial clearing" case the story is similar; again we match Safari.  Though keep in mind this is Safari on Snow Leopard.  Not sure how Safari on Mountain Lion, say, would do...

In any case, if we're not interested in trying to figure out how Chrome gets its insanely fast times, it sounds like the above bit about width sets is the only thing we can deal with here.
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.