• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: NSView -drawRect optimization
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSView -drawRect optimization


  • Subject: Re: NSView -drawRect optimization
  • From: Erik Buck <email@hidden>
  • Date: Tue, 12 Feb 2008 18:51:12 -0500

Your method of determining where drawing time is being spent is probably effective, but it's way too much work. Just use Shark or Sampler along with Quartz Debug. Apple provides some of the best profiling tools anywhere and they're free.

You are drawing way too much each time you draw. You only need to draw graphics that fall within the rect passed to -drawRect:, and you can narrow it down even farther using - (void)getRectsBeingDrawn: (const NSRect **)rects count:(NSInteger *)count. Not drawing things that don't need to be drawn is the biggest optimization you will get. Why don't OrderStep instances draw themselves ? If you are worried about adding drawing code to a "Model" object, add the drawing code in a category of OrderStep and maintain the category implementation in the "View" subsystem. For example:


@implementation OrderStep (ScheduleDrawing)

- (void)drawInRect:(NSRect)aRect ofTimelineView:(id)someView
{
NSTimeInterval timeIntervalToStart = [[self startTime] timeIntervalSinceDate:now] - [[[someView window] delegate] timeOfflineBetweenNowAndDate:(NSCalendarDate *)[self startTime]];
NSTimeInterval timeIntervalToEnd = [[self endTime] timeIntervalSinceDate:now] - timeOfflineBetweenNowAndDate;


NSRect OSRect = [someView rectForStartTimeInterval: timeIntervalToStart endTimeInterval: [[[someView window] delegate] timeOfflineBetweenNowAndDate:(NSCalendarDate *)[self endTime]]];

       if(NSIntersectsRect(OSRect, aRect)
       {
             // do all the drawing with NSBezierPath etc.
       }
}

@end


inside the timeline view:

-drawRect:(NSRect)rect
{
     NSRect		*dirtyRects;
     NSInteger		countOfDirtyRects;

[self getRectsBeingDrawn: &dirtyRects count:&countOfDirtyRects];
NSInteger i;
for(i = countOfDirtyRects - 1; i >= 0; i--)
{
int OSIndex;
for (OSIndex = 0; OSIndex < [[currentWorkCenter orderSteps] count]; OSIndex ++)
{
OrderStep * currentOS = [[currentWorkCenter orderSteps] objectAtIndex:OSIndex];


[currentOS drawInRect: *(dirtyRects[i]) ofTimelineView:self];
}
}
}



Then, be very careful to call -setNeedsDisplayInRect: with the smallest possible rectangles instead of calling -setNeedsDisplay or just -display.


Finally, you are recalculating a lot of state information every time you draw. As a guideline, the only code called from -drawRect: should be drawing code. It should be possible to calculate the position of each order step once and re-use the value as needed. Translate the coordinate system of the timeline view to indicate changing time instead of recalculating all of the order step rectangles. In other words, the rectangles are constant but the view's coordinate system changes.

You may find introductory graphics text books useful. Many people recommend "Computer Graphics: Principles and Practice in C (2nd Edition)" by James D. Foley, Andries van Dam, Steven K. Feiner, John F. Hughes

In the name of avoiding drawing, you can use Core Animation Layer Backed Views or even use OpenGL directly and potentially see 100x speed-up over basic Quartz. CoreAnimation will cache the view drawing in a GL texture so that in most cases your -drawRect: will be called exactly once and the bitmap will be reused after that. Caching the drawing in a texture will eliminate calls to draw the P-number etc. so they will end up taking zero time. To use Layer Backed Views, each of your Order Steps should be represented by a separate subview of the timeline view.

I will be surprised if you can't make you drawing 100x faster, and 1000x faster is within the realm of possibility.

There is a lengthy chapter on graphics optimization in "Cocoa Programming" http://www.cocoaprogramming.net/ You can download the examples including a Tetris game without buying the book. The optimization examples are in Appendix B: Optimizing and Finding Memory Leaks.






_______________________________________________

Cocoa-dev mailing list (email@hidden)

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:
This email sent to email@hidden


  • Follow-Ups:
    • Re: NSView -drawRect optimization
      • From: Paul Bruneau <email@hidden>
  • Prev by Date: Re: Repetitive Appending of Strings
  • Next by Date: Re: Repetitive Appending of Strings
  • Previous by thread: Re: NSView -drawRect optimization
  • Next by thread: Re: NSView -drawRect optimization
  • Index(es):
    • Date
    • Thread