2012-02-29 10 views
8

Ho un metodo che esegue test incredibilmente lenti nel dispositivo (iPhone3G) confrontandolo con il simulatore.iOS: test 25 volte più lento sul dispositivo rispetto al simulatore

Mentre il simulatore può gestire circa 100 esecuzioni del metodo in 1 secondo, il dispositivo può eseguire solo 4 volte il metodo in un secondo.

Cosa può rendere così sloooow?

CODICE: Nota: il metodo calcola una stringa human friendly da due date (data di inizio e data di fine di un evento).

-(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"); 
} 
+1

Il dispositivo è MOLTO più lento del simulatore ... quindi il nome simulatore e non emulatore. È un problema di prestazioni notevole? Hai eseguito Time Profiler (con il dispositivo)? –

risposta

16

I dispositivi iOS sono notevolmente meno potenti del computer sul quale si sta eseguendo il simulatore. Il simulatore iOS non emula il Processore ARM e quindi lo esegue alla massima velocità.

Inoltre, il motivo per cui questo particolare metodo è così lento è dovuto alla creazione degli oggetti NSDateFormatter e NSCalendar. Questi sono abbastanza costosi da creare e dovrebbero essere memorizzati nella cache in una variabile di istanza/proprietà se si desidera utilizzarli più volte.

+0

L'ho memorizzato nella cache e ottengo 50 run del metodo in un secondo (12 volte più veloce) e solo la metà del tempo rispetto al simulatore. D'ora in poi dovrò controllare questo nei miei anelli. –

1

E 'normale il simulatore è compilato per processori Intel, quando si esegue il test sul simulatore vostra applicazione viene costruire per INTEL e sta usando tutta la potenza della CPU del computer. Quindi è molto più veloce.

È possibile utilizzare lo strumento per vedere quale parte sta rallentando l'esecuzione.

13

Si dovrebbe memorizzare nella cache questa variabile, è molto lento. Chiama questo metodo una volta.

NSCalendar *calendar = [NSCalendar currentCalendar]; 
+0

Se il seguente è vero: http://mikeabdullah.net/NSCalendar_currentCalendar.html, non è necessario memorizzare nella cache '[NSCalendar currentCalendar]' più a partire da iOS 7 in su. –

0

Evitare l'uso di NSDateFormatter in loop.

L'ho risolto convertendo la data in stringa utilizzando stringWithFormat e quindi interrompendo i componenti utilizzando componentSeparatedByString.

NSString *stringDate = [NSString stringWithFormat:@"%@",mydate]; 
NSArray *stringArray = [stringDate componentsSeparatedByString: @" "]; 
NSArray *timeArray = [stringArray[1] componentsSeparatedByString: @":"]; 

In questo modo, sono riuscito a eseguire il ciclo in meno di un secondo da un paio di secondi.

Spero che questo possa essere d'aiuto.

0

Instantiating NSDateFormatter e NSCalendar non sono operazioni non banali. La creazione di un NSDateFormatter può richiedere fino a 250 ms su un iPhone 4s, durante i miei test. Evita di ricreare questi oggetti, mantenendoli come ivari di classe o oggetti statici se possibile. Riutilizzare quando puoi.

Problemi correlati