I have a method which runs incredibly slow testing in device (iPhone3G) comparing to simulator.
While the simulator can handle around 100 executions of the method in 1 second the device can only run 4 times thought the method in a second.
What can make it so sloooow?
CODE: Note: The method calculates a human friendly string from a two dates (start date and end date of an event).
-(void)calculateDiaDeInicioYFinTexto
{
NSLog(@"inicio");
NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init];
NSMutableString *auxString = [NSMutableString string];
NSLocale *currLocale = [NSLocale currentLocale];
NSString *stringFormatDay = [NSDateFormatter dateFormatFromTemplate:@"d"
options:0
locale:currLocale];
NSString *stringFormatDayMonth = [NSDateFormatter dateFormatFromTemplate:@"dMMMM"
options:0
locale:currLocale];
NSString *stringFormatDayMonthYear = [NSDateFormatter dateFormatFromTemplate:@"dMMMMYYYY"
options:0
locale:currLocale];
NSDateFormatter *formatterDay = [[NSDateFormatter alloc] init];
[formatterDay setDateFormat:stringFormatDay];
[formatterDay setLocale:currLocale];
NSDateFormatter *formatterDayMonth = [[NSDateFormatter alloc] init];
[formatterDayMonth setDateFormat:stringFormatDayMonth];
[formatterDayMonth setLocale:currLocale];
NSDateFormatter *formatterDayMonthYear = [[NSDateFormatter alloc] init];
[formatterDayMonthYear setDateFormat:stringFormatDayMonthYear];
[formatterDayMonthYear setLocale:currLocale];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponentsNow = [calendar components:(NSYearCalendarUnit |
NSMonthCalendarUnit |
NSDayCalendarUnit)
fromDate:[NSDate date]];
NSDateComponents *dateComponentsInicio = [calendar components:(NSYearCalendarUnit |
NSMonthCalendarUnit |
NSDayCalendarUnit)
fromDate:self.diaDeInicio];
NSDate *diaDeInicioTimeless = [calendar dateFromComponents:dateComponentsInicio];
NSDateComponents *dateComponentsFin = [calendar components:(NSYearCalendarUnit |
NSMonthCalendarUnit |
NSDayCalendarUnit)
fromDate:self.diaDeFin];
NSDate *diaDeFinTimeless = [calendar dateFromComponents:dateComponentsFin];
if ( [diaDeInicioTimeless isEqualToDate:diaDeFinTimeless] ) {
// dates are the same
if ( dateComponentsInicio.year == dateComponentsNow.year ) {
// date is in the current year
[auxString appendFormat:@"%@", [formatterDayMonth stringFromDate:self.diaDeInicio]];
} else {
// date is in another year
[auxString appendFormat:@"%@", [formatterDayMonthYear stringFromDate:self.diaDeInicio]];
}
} else {
// dates are different
if ( dateComponentsInicio.year == dateComponentsFin.year ) {
// years are the same
if ( dateComponentsInicio.month == dateComponentsFin.month ) {
// Months are the same
if ( dateComponentsInicio.year == dateComponentsNow.year ) {
// date is in the current year
[auxString appendFormat:@"%@ - %@",
[formatterDay stringFromDate:self.diaDeInicio],
[formatterDayMonth stringFromDate:self.diaDeFin]];
} else {
// date is in another year
[auxString appendFormat:@"%@ - %@",
[formatterDay stringFromDate:self.diaDeInicio],
[formatterDayMonthYear stringFromDate:self.diaDeFin]];
}
} else {
// Months are different
if ( dateComponentsInicio.year == dateComponentsNow.year ) {
// date is in the current year
[auxString appendFormat:@"%@ - %@",
[formatterDayMonth stringFromDate:self.diaDeInicio],
[formatterDayMonth stringFromDate:self.diaDeFin]];
} else {
// date is in another year
[auxString appendFormat:@"%@ - %@",
[formatterDayMonth stringFromDate:self.diaDeInicio],
[formatterDayMonthYear stringFromDate:self.diaDeFin]];
}
}
} else {
// Years are different
[auxString appendFormat:@"%@ - %@",
[formatterDayMonthYear stringFromDate:self.diaDeInicio],
[formatterDayMonthYear stringFromDate:self.diaDeFin]];
}
}
self.diaDeInicioYFinTexto = auxString;
[formatterDay release];
[formatterDayMonth release];
[formatterDayMonthYear release];
[localPool release];
NSLog(@"Fin");
}
iOS Devices are considerably less powerful than the computer that you are running the simulator on. The iOS simulator does not emulate the ARM proccessor and so it runs it at full speed.
In addition, the reason that this particular method is so slow is because of the creation of the NSDateFormatter
and NSCalendar
objects. Those are fairly expensive to create and should be cached in an instance variable/property if you want to use them multiple times.
You should cache this variable, it's very slow. Call this method once.
NSCalendar *calendar = [NSCalendar currentCalendar];
Avoid using NSDateFormatter in loop.
I fixed it by converting date to string using stringWithFormat and then breaking the components by using componentsSeparatedByString.
NSString *stringDate = [NSString stringWithFormat:@"%@",mydate];
NSArray *stringArray = [stringDate componentsSeparatedByString: @" "];
NSArray *timeArray = [stringArray[1] componentsSeparatedByString: @":"];
By doing this, I was able to execute my loop in less than a sec from couple of seconds.
Hope this will help.
Instantiating NSDateFormatter and NSCalendar are not non-trivial operations. Creating an NSDateFormatter can take up to 250ms on an iPhone 4s, on my testing. Avoid re-creating of these objects, keeping them either as class ivars or static objects if possible. Re-use whenever you can.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With