Friday, November 12, 2010

Using Time Profiler to Tune Performance

There are two parts of software development on the iPhone we still don't feel comfortable with: gdb and Instruments. We know they are powerful tools but we just can't seem to understand what they are telling us most of the time. Perhaps understanding those two areas of development is a good goal for the next quarter. If we knew those tools we would be able to write better software, faster.

Here is an example of Instruments in action tonight. We
are trying to speed up an application that just seems sluggish. Especially on our older test devices. Our philosophy is to always test on the oldest devices we have. If it runs well on those, it will fly on newer hardware.

We ran the app with just the Time Profiler so we could identify where the app spends its time. Some of the things were obvious to us. However, here was one that wasn't obvious and turns out was a simple fix on our part with a high return.

This particular application streams audio using a set of co
de written by Sound Cloud to interface with their site. We noticed, however that the NSDateFormatter was taking a great deal of time:
4.9% of the time had been spent regenerating a date formatter object. With a little digging we found this set of code:

NSDate *position = [NSDate dateWithTimeIntervalSinceReferenceDate

:stream.playPosition / 1000.0];

NSDate *songEnd = [NSDate dateWithTimeIntervalSinceReferenceDate:[currentArticle.duration intValue] / 1000.0];

NSDateFormatter *formatter = [[NSDateFormatter alloc] init] ;

[formatter setDateFormat:@"mm:ss.S"];

playPositionLabel.text = [NSString stringWithFormat:@"%@ / %@", [formatter st

ringFromDate: position], [formatter stringFromDate:songEnd]];

scrubberSlider.maximumValue = (float)[currentArticle.duration intValue];

scrubberSlider.value = (float)stream.playPosition;

We were alloc/initting an NSDateFormatter every 2/10's of a second, then using it to display some numbers and then throwing it away. It seemed harmless enough but clearly the whole alloc/init was more overhead that we realized. So, we simply moved the variable out and declared it in the header file as a regular variable

NSDateFormatter *formatter;

and then just set it up in the viewDidLoad method

formatter = [[NSDateFormatter alloc] init] ;

[formatter setDateFormat:@"mm:ss.S"];

Now it should be alloc/initted just once and then used each time. Sure enough we ran again and now we had to actually search for the references to the NSDateFormatter since they were so far down the list.


No comments:

Post a Comment