2009-06-23 9 views
8

Ich möchte einen automatisierten Leistungstest zu meiner Objective-C-Anwendung hinzufügen. (Dies ist ein Spiel, so dass ich gerne die aktuelle Leistung der wichtigsten Teile der Engine sehen möchte, indem ich einfach eine Reihe von Tests durchführe.) Dazu möchte ich eine Timing-Unterstützungsroutine schreiben:Timing Objective-C-Code

- (void) benchmarkSelector: (SEL) msg onObject: (id) target 
{ 
    // run the selector thousands of times, print detailed stats 
} 

Das Problem ist, dass ich in Millisekunden interessiert bin und ich fürchte, dass performSelector im Benchmarking-Code würde die Ergebnisse ziemlich verzerren. Wie würdest du das umgehen? Sollte ich zu objc_msgSend gehen?

+0

ist dieser Cocoa-spezifische Code? – Nippysaurus

+0

Ich bin mir nicht sicher, wahrscheinlich nicht. – zoul

Antwort

12

Verwenden methodForSelector:, die einen Funktionszeiger auf die tatsächliche Implementierung liefert, etwa so:

IMP methodImp = [target methodForSelector:msg]; 
for (int i=0; i<1000; ++i) { 
    NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate]; 
    methodImp(target, msg); 

    NSTimeInterval duration = [NSDate timeIntervalSinceReferenceDate] - start; 
    // Do something with duration 
} 

Beachten Sie, dass diese Strategie zur Messung der tatsächlichen Laufzeit eines Verfahrens nützlich ist, aber wenn du gehst zu sein Wenn Sie es mit der Objective-C-Nachrichtenübergabesyntax aufrufen, ist es möglicherweise genauso wichtig, den Overhead für die Nachrichtenübermittlung in Ihre Messungen aufzunehmen.

Beachten Sie auch, dass, wenn die Methode tatsächlich alle anderen Parameter nimmt, sollten Sie das Ergebnis der methodForSelector: auf einen Funktionszeiger mit den entsprechenden Parametern gegossen, unerwartete Umwandlung von Schwimmern verdoppelt, etc. zu vermeiden Siehe NSObject Class Reference für weitere Informationen und Beispiele.

+0

Sie haben recht, wenn Sie den Overhead für die Nachrichtenübermittlung einbeziehen, aber ich befürchtete, dass der performSelector: "viel" länger dauern könnte, als einfach die Nachricht zu senden. Nach dem Schreiben des Codes sieht es nicht so schlecht aus - und wenn ich wollte, könnte ich immer zum IMP zurückkehren. Vielen Dank. – zoul

+0

Würden Sie nicht bessere Ergebnisse erzielen, wenn Sie verwenden würden uint64_t start = mach_absolute_time(); uint64_t duration = mach_absolute_time() - Start; was gibt Ihnen Nanosekunden statt Sekunden? – micmoo

+2

NSTimeInterval ist ein Doppel. Das Ergebnis wird in Sekunden ausgedrückt, hat jedoch eine Genauigkeit im Millisekundenbereich. Da das OP nach Millisekunden sucht, denke ich, dass es gut genug ist. Aber ja, mach_absolute_time() würde auch funktionieren. –