2010-08-22 19 views
13

Sto cercando il codice di temporizzazione ad alta risoluzione per iPhone, al fine di fare alcuni tempi di esecuzione. Mi piacerebbe scrivere codice come questo:Timer ad alta risoluzione per iPhone?

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

Perché non usare semplicemente 'getrusage()'? Qualunque cosa funzioni in C funzionerà in Objective-C. –

+1

Perché esiste un metodo Cocoa perfettamente valido per fare la stessa cosa. – lucius

risposta

26

Cerca in mach_absolute_time() nell'intestazione mach/mach_time.h.

Non utilizzare NSDate. NSDate non è nemmeno garantito di non tornare indietro di tanto in tanto, quando ntp fa il suo dovere.

(Dispositivi può avere l'orologio deriva. Se il dispositivo iOS scivola veloce pochi secondi, poi quando NTP corregge questa deriva, si vedrà l'orologio improvvisamente andare all'indietro pochi secondi. Molto male per temporizzazione uso. Mach_time utilizza un contatore questo non mai ottenere corretti da NTP, quindi non può tornare indietro, quindi è molto meglio per temporizzazione.)

+1

'NSDate' restituisce solo un double che conta i secondi dal 1 gennaio 2001. Per il cronometro, un tempo negativo non si verificherà, quindi non vedo il bisogno di sovraccaricare il' mach_absolute_time() 'nel codice - [entrambi implementati qui] (http://stackoverflow.com/a/12553393/111307). – bobobobo

+3

@bobobobo: il numero di secondi del dispositivo dal primo gennaio 2001 viene occasionalmente corretto all'indietro da NTP. Quindi può essere non monotona su un dato dispositivo che ha un cristallo di orologio che a volte si muove velocemente, più una connessione di rete che può correggere questa deriva. – hotpaw2

+0

Ho finito per usare mach_absolute_time(). Ho trovato una piccola classe che lo utilizza, [qui] (http://zpasternack.blogspot.com/2012/07/high-resolution-timing-in-cocoa.html). – zpasternack

5

Usa NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate] per ottenere un orario di inizio, e poi NSLog (@"Operation took %f seconds.", [NSDate timeIntervalSinceReferenceDate] - startTime); alla fine.

+1

Funziona perfettamente, grazie! Non avevo realizzato che NSDate avesse questo livello di precisione. – zpasternack

16

una soluzione migliore è CACurrentMediaTime() che utilizza mach_absolute_time() ma lo converte in un CFTimeInterval (cioè, il tempo in secondi come un doppio) per te.

+0

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

8

Ecco la mia risposta per i timer utilizzando sia mach_absolute_time(), in base al metodo di calcolo shown here e NSDate. In realtà sono gli stessi in termini di precisione.

Mach versione

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 versione

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 
} 

Risultati:

Nota la risoluzione su entrambi questi è veramente buono.

 

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 

* Se si guarda alla storia di modifica di questo post, è possibile vedere il pericolo di usare float al posto di un double!

+0

Hai dimenticato di aggiungere init = true; in machGetClockS(). –

+0

@AndrewSmith Ottimo punto! Fisso. – bobobobo

+0

Non è un buon test di risoluzione temporale, dal momento che è stato testato senza il monitoraggio di wireshark per qualsiasi connessione di rete NTP, che a volte può davvero compromettere i risultati di NSDate. – hotpaw2

Problemi correlati