On 28/03/2012, at 6:36 PM, Kenneth Baxter wrote:

> I am trying out some different ideas for animating portions of a view, but am 
> having problems with performance. 
> 
> Essentially I have an animation running using a CABasicAnimation, and when it 
> calls back to my view, it invalidates the rect where the object was drawn, 
> and the new place where it is going to be drawn. Then in my drawRect code, I 
> ask each of my objects that overlap the dirty rect to redraw itself.
> 
> For testing purposes, I have a view that is 5,000 x 5,000 and have 100 of my 
> objects which are placed randomly and size 200 x 400.
> 
> For each object, I save the graphics state, transform my coordinates, clip to 
> the bounds of the object, draw it, and then restore the graphics state.
> 
> At the moment, on my test machine (which is admittedly not the latest and 
> greatest, but it probably representative of our typical customer), I have 
> tried the following scenarios:
> 
> Draw each object individually (admittedly it's just a simple oval in rect 
> which is filled and stroked): 12fps
> Generate an NSImage of the object once and cache it, then just drawInRect...: 
> 8fps
> Cache a CIImage and draw that: 8fps
> Cache a CGLayer and draw that: 8fps
> 
> This sure does seem to be awfully slow. Instruments tell that the time is all 
> being spent in drawing the object, no matter how I do the drawing.
> 
> Is there some better way to get decent drawing performance from drawing into 
> an NSView?

200 x 400 is quite a big area to fill, whether by using stroke/fill or blitting 
an image. Multiply by 100 and you are doing a lot of work pushing pixels 
(equivalent to blitting 8 million pixels!). Though I'm surprised that the 
NSImage method is slower than fill/stroke, in most cases I would expect that to 
be faster, so there might be an inefficiency there somewhere.

The only way to get faster drawing is to avoid doing any drawing you don't need 
to - it's always worth it. So for example if your objects overlap (they surely 
do) then avoid drawing anything except the topmost object which finally sets 
the pixels you see. Also, using the rect parameter to -drawRect can end up 
doing more drawing than necessary because it's actually the union of any 
disjoint or non-rectangular dirty regions. You could use 
-getRectsBeingDrawn:count: or -needsToDrawRect: instead to ensure you really 
keep the set of drawn objects to a minimum.

The next step, once you have the minimal set of objects to draw, is only to 
draw the pixels that have changed. Depending on your animation, it might not be 
many - for example, if a solid object moves, only its leading and trailing 
edges have actually changed, though of course for anything non-trivial that 
might not help at all. If you really need to animate this many objects this 
large, you are going to have to get clever to reduce the pixels involved. I 
expect using CABasicAnimation and invalidating most of the view is not smart 
enough - you'll need to track each object and how it has moved so that you 
invalidate strictly what area changed. Combined with -needsToDrawRect: you 
should see a big gain in performance.

You might also get some improvement using CALayer to draw the layer content 
rather than a view. This ultimately uses OpenGL to blit the pixels as a 
texture, though capturing the image in the first place is just as slow if you 
must redraw it every time. However, to just move a static graphic around, 
CALayer will cache the image and not need to ever redraw it, so you'll see a 
massive speedup for that case. You could use a CALayer for each object, and 
just animate their x,y positions. The speed boost will be huge.

--Graham

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to