2012-02-29 6 views
8

Mam metodę, która działa niesamowicie wolno testowanie w urządzeniu (iPhone3G) w porównaniu do symulatora.iOS: Metoda 25 razy wolniejsze testowanie na urządzeniu w porównaniu z symulatorem

Podczas gdy symulator może obsłużyć około 100 wykonań tej metody w ciągu 1 sekundy, urządzenie może uruchomić tylko 4 razy przemyślaną metodę w ciągu sekundy.

Co może sprawić, że będzie tak sloooow?

KOD: Uwaga: Metoda oblicza przyjazny dla człowieka ciąg z dwóch dat (data rozpoczęcia i data zakończenia wydarzenia).

-(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

Urządzenie jest DUŻO wolniejsze niż symulator ... stąd nazwa symulator, a nie emulator. Czy jest to zauważalny problem z wydajnością? Czy uruchomiłeś profil czasowy (z urządzeniem)? –

Odpowiedz

16

Urządzenia iOS są znacznie mniej wydajne niż komputer, na którym działa symulator. Symulator iOS nie emuluje procesora ARM, więc uruchamia go z pełną prędkością.

Ponadto powód, dla którego ta szczególna metoda jest tak powolna, jest spowodowany tworzeniem obiektów NSDateFormatter i NSCalendar. Są one dość kosztowne w tworzeniu i powinny być buforowane w zmiennej/właściwości instancji, jeśli chcesz ich używać wiele razy.

+0

Zapisałem to w pamięci i otrzymałem 50 przebiegów metody w ciągu sekundy (12 razy szybciej) i tylko połowę czasu w porównaniu z symulatorem. Będę musiał to sprawdzić w moich pętlach od teraz. –

1

To normalne symulator jest kompilowany dla procesorów Intel, podczas testowania na symulatorze aplikacja jest budować dla INTEL i wykorzystuje wszystkie zasilania komputera CPU. Więc jest o wiele szybciej.

Możesz użyć instrumentu, aby zobaczyć, która część spowalnia wykonanie.

13

Powinieneś buforować tę zmienną, jest bardzo powolna. Wywołaj tę metodę raz.

NSCalendar *calendar = [NSCalendar currentCalendar]; 
+0

Jeśli spełnione są następujące warunki: http://mikeabdullah.net/NSCalendar_currentCalendar.html, nie musimy buforować '[NSCalendar currentCalendar]' dłużej uruchamiając ios 7 i nowsze. –

0

Unikaj używania pętli NSDateFormatter.

Naprawiłem to, konwertując datę na ciąg znaków za pomocą stringWithFormat, a następnie łamiąc składniki za pomocą componentsSeparatedByString.

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

W ten sposób udało mi się wykonać pętlę w czasie krótszym niż sekundę od kilku sekund.

Mam nadzieję, że to pomoże.

0

Tworzenie instancji NSDateFormatter i NSCalendar to nie nietrywialne operacje. Utworzenie NSDateFormatter może zająć do 250 ms na iPhone'ach 4s podczas moich testów. Unikaj ponownego tworzenia tych obiektów, zachowując je jako klasy lub obiekty statyczne, jeśli to możliwe. Wykorzystaj ponownie, kiedy tylko możesz.