Kyle
Kyle

Reputation: 1595

Benchmark UIView drawRect: method

I am writing an iPhone application in Objective-C that utilizes some custom drawing in views and I would like to benchmark various revisions of my code to see what really helps. I was planing on doing this by setting up a new application, adding my custom drawing code to the drawRect: method of the view, then, in a for loop in the view controller, sending [UIView setNeedsDisplay] some large number of times and timing how long it takes to complete. However the setNeedsDisplay calls seem to be cached so even though I call it 1000 times in a for loop, the drawRect: method gets called only once. Also, I tried calling drawRect: directly but I need a graphics context to do some drawing in and when I don't use setNeedsDisplay: UIGraphicsGetCurrentContext() doesn't give me a context.

Any suggestions?

Thanks,

Kyle

Upvotes: 6

Views: 3005

Answers (4)

nielsbot
nielsbot

Reputation: 16022

If you're looking for something that can give slightly more in-depth analysis, I have a set of macros you can use for time profiling here: https://gist.github.com/952456

Upvotes: 0

Don't forget you can also use the CoreImage performance tool and get framerates if your drawRect is used often.

You could also use some of the performance tools to see how long is spent in that method.

Upvotes: 0

rpetrich
rpetrich

Reputation: 32316

You can benchmark a view by doing the following:

- (NSTimeInterval)timeTakenToDrawView:(UIView *)view count:(NSInteger)count
{
    CGRect bounds = [view bounds];
    NSDate *startDate = [NSDate date];
    UIGraphicsBeginImageContext(bounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    NSInteger i = 0;
    for (i = 0; i < count; i++) {
        CGContextSaveGState(context);
        [view drawRect:bounds];
        CGContextRestoreGState(context);
    }
    UIGraphicsEndImageContext();
    return [[NSDate date] timeIntervalSinceDate:startDate];
}

(Haven't tried it, but it should work)

Upvotes: 5

Steven Canfield
Steven Canfield

Reputation: 7332

Inside of your NSView's .m. Obviously you might want to hook this up to a UI or something.

- (void)awakeFromNib {
    // Have to wait for the window to be onscreen, graphics context ready, etc
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerFired:) userInfo:NULL repeats:NO];
}


- (void)timerFired:(NSTimer *)aTimer {
    [self lockFocus];

    NSDate* then = [NSDate date];

    int callIdx = 0;
    for( callIdx = 0; callIdx < 1000; callIdx++ ) {
        [self drawRect:[self bounds]];
    }
    NSDate* now = [NSDate date];

    [self unlockFocus];

    NSLog(@"Took %f seconds", [now timeIntervalSinceDate:then]);
}

- (void)drawRect:(NSRect)rect {
    [[NSColor redColor] set];
    NSRectFill(rect);
}

Upvotes: 0

Related Questions