Re: NSView -drawRect optimization
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