2010-08-22 16 views
13

Poszukuję kodu taktowania o wysokiej rozdzielczości dla telefonu iPhone, aby wykonać pewne działania. Chciałbym napisać kod tak:Zegar o wysokiej rozdzielczości dla iPhone'a?

HighResolutionTimer* myTimer = [[HighResolutionTimer alloc]init]; 
[myTimer start]; 
[self doSomeLengthyOperation]; 
NSLog(@"doSomeLengthyOperation took %f seconds", [myTimer elapsedTime]); 
+1

Dlaczego po prostu nie używać 'getrusage()'? Wszystko, co działa w C, działa w Objective-C. –

+1

Ponieważ istnieje całkiem dobra metoda kakao do robienia tego samego. – lucius

Odpowiedz

26

Sprawdź w mach_absolute_time() w nagłówku mach/mach_time.h.

Nie używaj NSDate. NSdate nie może nawet od czasu do czasu odejść wstecz, gdy ntp robi to samo.

(Urządzenia mogą mieć dryf zegara.Jeśli urządzenie iOS szybko dryfuje przez kilka sekund, to kiedy NTP koryguje ten dryf, zobaczysz, że zegar nagle cofa się o kilka sekund Bardzo źle z powodu używania czasu. które nie zawsze są poprawiane przez NTP, a tym samym nie może iść do tyłu, co jest o wiele lepsze dla terminów.)

+1

'NSDate' zwraca tylko podwójny liczący sekundy od 1 stycznia 2001. Dla stopera stopera, ujemny czas po prostu się nie pojawi, więc nie widzę potrzeby narzucania' mach_absolute_time() 'do twojego kodu - [obie implementowane tutaj] (http://stackoverflow.com/a/12553393/111307). – bobobobo

+3

@bobobobo: Licznik sekund od 1 stycznia 2001 r. Jest czasami korygowany wstecz przez NTP. Może więc być niemonotoniczny na dowolnym urządzeniu, które ma zegarowy kryształ, który czasami dryfuje szybko, oraz połączenie sieciowe, które może skorygować ten dryf. – hotpaw2

+0

Skończyło się na użyciu mach_absolute_time(). Znalazłem małą klasę, która go używa, [tutaj] (http://zpasternack.blogspot.com/2012/07/high-resolution-timing-in-cocoa.html). – zpasternack

5

Zastosowanie NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate] aby uzyskać czas rozpoczęcia, a następnie NSLog (@"Operation took %f seconds.", [NSDate timeIntervalSinceReferenceDate] - startTime); na końcu.

+1

To działa idealnie, dzięki! Nie zdawałem sobie sprawy, że NSDate ma taki poziom precyzji. – zpasternack

16

lepszym rozwiązaniem jest CACurrentMediaTime() który wykorzystuje mach_absolute_time() ale konwertuje go do CFTimeInterval (czyli czas w sekundach, jak podwójne) dla ciebie.

+0

Wymaga ['#import '] (https://stackoverflow.com/q/729094). – Pang

8

Oto moja odpowiedź na zegary zegarowe z wykorzystaniem zarówno mach_absolute_time(), w oparciu o metodę obliczeń shown here, jak i NSDate. W rzeczywistości są one takie same pod względem dokładności.

wersja Mach

double machGetClockS() 
{ 
    static bool init = 0 ; 
    static mach_timebase_info_data_t tbInfo ; 
    static double conversionFactor ; 
    if(!init) 
    { 
    init = 1 ; 
    // get the time base 
    mach_timebase_info(&tbInfo) ; 
    conversionFactor = tbInfo.numer/(1e9*tbInfo.denom) ; // ns->s 
    } 

    return mach_absolute_time() * conversionFactor ; // seconds 
} 

double machGetClockDiffS() 
{ 
    static double lastTime = 0; 

    double currentTime = machGetClockS() ; 

    double diff = currentTime - lastTime ; 

    lastTime = currentTime ; // update for next call 

    return diff ; // that's your answer 
} 

NSTimeInterval wersja

double getClockS() 
{ 
    return [NSDate timeIntervalSinceReferenceDate] ; // NSTimeInterval is always specified in seconds 
} 

double getClockDiffS() 
{ 
    static double lastTime = 0 ; 

    double currentTime = getClockS() ; 

    double diff = currentTime - lastTime ; 

    lastTime = currentTime ; // update for next call 

    return diff ; // that's your answer 
} 

Wyniki:

Uwaga rozdzielczość na obu z nich jest naprawdę dobra.

 

IOS SIMULATOR, running frame rate counts (in milliseconds (*1000.0)) 

MACH_ABS_TIME/NSTimeIntervals 
58.557001/58.552980 
40.558007/40.562987 
52.207822/52.200019 
33.742197/33.742011 
38.498912/38.504004 
48.872679/48.868001 
45.012602/45.011997 
57.858432/57.865977 
25.044615/25.038004 


IPAD HARDWARE SAMPLINGS: 
33.415041/33.416033 
33.240167/33.239007 
33.357542/33.357978 
33.302833/33.302009 
33.506750/33.509016 
33.582250/33.582985 
33.233958/33.232987 
33.239042/33.237994 

* Jeśli spojrzeć na historię edycji tego postu, można zobaczyć niebezpieczeństwa używając float w miejscu o double!

+0

Zapomniałeś dodać init = true; w machGetClockS(). –

+0

@AndrewSmith Świetny punkt! Naprawiony. – bobobobo

+0

Nie jest to dobra próba rozdzielczości czasowej, ponieważ testowałeś bez monitorowania w przeglądarce w poszukiwaniu jakichkolwiek połączeń sieciowych NTP, co czasami może naprawdę zepsuć wyniki NSDate. – hotpaw2

Powiązane problemy