Wie können wir die Zeit messen, die zum Ausführen einer Funktion in Swift vergangen ist? Ich versuche, die verstrichene Zeit folgendermaßen anzuzeigen: "Die verstrichene Zeit beträgt 0,05 Sekunden". Saw , dass in Java , können wir System.nanoTime () verwenden, ist es gleichwertige Verfahren in Swift verfügbar sind , dies zu erreichen?
Bitte schauen Sie sich das Beispielprogramm an:
func isPrime(var number:Int) ->Bool {
var i = 0;
for i=2; i<number; i++ {
if(number % i == 0 && i != 0) {
return false;
}
}
return true;
}
var number = 5915587277;
if(isPrime(number)) {
println("Prime number");
} else {
println("NOT a prime number");
}
swift
time
nsdate
elapsedtime
Vaquita
quelle
quelle
sqrt(number)
werdennumber
, und Sie können etwas mehr Zeit sparen - aber es gibt viel mehr Ideen zur Optimierung der Suche nach Primzahlen.NSDate
Objekte verwenden und den Unterschied zwischen ihnen messen.Antworten:
Hier ist eine Swift-Funktion, die ich geschrieben habe, um Project Euler- Probleme in Swift zu messen
Ab Swift 3 gibt es jetzt eine Version von Grand Central Dispatch, die "schnell" ist. Die richtige Antwort ist also wahrscheinlich die Verwendung der DispatchTime-API .
Meine Funktion würde ungefähr so aussehen:
Alte Antwort
Für Swift 1 und 2 verwendet meine Funktion NSDate:
Beachten Sie, dass von der Verwendung von NSdate für Zeitsteuerungsfunktionen abgeraten wird: " Die Systemzeit kann sich aufgrund der Synchronisation mit externen Zeitreferenzen oder aufgrund einer expliziten Änderung der Uhr durch den Benutzer verringern. "
quelle
Date
nebenbei verwendet, und zwar 41,87 Sekunden. Ich weiß nicht, wasuptimeNanoseconds
es tut, aber es wird nicht die richtige Dauer angegeben.Dies ist eine praktische Timer-Klasse, die auf
CoreFoundation
s basiertCFAbsoluteTime
:Sie können es so verwenden:
quelle
mach_absolute_time
diejenigen, die nicht unter diesem Problem leiden, also frage ich mich, warum dieses nicht allgemein bekannt ist. Vielleicht nur, weil es nicht gut dokumentiert ist.Verwenden Sie
clock
,ProcessInfo.systemUptime
oderDispatchTime
für eine einfache Startzeit.Soweit ich weiß, gibt es mindestens zehn Möglichkeiten, die verstrichene Zeit zu messen:
Monotone Uhr basiert:
ProcessInfo.systemUptime
.mach_absolute_time
mitmach_timebase_info
wie in dieser Antwort erwähnt .clock()
im POSIX-Standard .times()
im POSIX-Standard . (Zu kompliziert, da wir Benutzerzeit und Systemzeit berücksichtigen müssen und untergeordnete Prozesse beteiligt sind.)DispatchTime
(ein Wrapper um die Mach-Zeit-API), wie von JeremyP in der akzeptierten Antwort erwähnt.CACurrentMediaTime()
.Wanduhr basiert:
(Verwenden Sie diese niemals für Metriken: siehe unten, warum)
NSDate
/Date
wie von anderen erwähnt.CFAbsoluteTime
wie von anderen erwähnt.DispatchWallTime
.gettimeofday()
im POSIX-Standard .Option 1, 2 und 3 werden nachstehend erläutert.
Option 1: Verarbeiten der Info-API in Foundation
Wo
diff:NSTimeInterval
ist die verstrichene Zeit in Sekunden.Option 2: Mach C API
Wo
diff:Double
ist die verstrichene Zeit in Nanosekunden?Option 3: POSIX Clock API
Wo
diff:Double
ist die verstrichene Zeit in Sekunden.Warum nicht die Wanduhrzeit für die verstrichene Zeit?
In der Dokumentation von
CFAbsoluteTimeGetCurrent
:Grund ist ähnlich wie
currentTimeMillis
vsnanoTime
in Java :Hier wird
CFAbsoluteTime
die Wanduhrzeit anstelle der Startzeit angegeben.NSDate
ist auch Wanduhrzeit.quelle
clock()
Funktion.ProcessInfo.processInfo.systemUptime
,mach_absolute_time()
,DispatchTime.now()
undCACurrentMediaTime()
. Aber die Lösung mitclock()
wurde nicht richtig in Sekunden konvertiert. Daher würde ich empfehlen, Ihren ersten Satz zu aktualisieren: " Verwenden Sie ProcessInfo.systemUptime oder DispatchTime für eine genaue Startzeit. "Swift 4 kürzeste Antwort:
Es druckt Ihnen ungefähr 1.02107906341553 Sekunden (die Zeit variiert natürlich je nach Aufgabe, ich zeige dies nur, damit Sie die Dezimalgenauigkeit für diese Messung sehen können).
Hoffe, es hilft jemandem in Swift 4 von nun an!
Aktualisieren
Wenn Sie eine generische Methode zum Testen von Codeteilen haben möchten, würde ich das nächste Snippet vorschlagen:
quelle
quelle
Kopieren Sie diese Funktion einfach und fügen Sie sie ein. Geschrieben in Swift 5. Kopieren Sie JeremyP hier.
Verwenden Sie es wie
quelle
Sie können eine
time
Funktion zum Messen Ihrer Anrufe erstellen . Ich bin inspiriert von Klaas ' Antwort.Mit dieser Funktion können Sie es so aufrufen, dass
time (isPrime(7))
ein Tupel mit dem Ergebnis und einer Zeichenfolgenbeschreibung der verstrichenen Zeit zurückgegeben wird.Wenn Sie nur die verstrichene Zeit wünschen, können Sie dies tun
time (isPrime(7)).duration
quelle
Einfache Hilfsfunktion zur Messung der Ausführungszeit mit Verschluss.
Verwendung:
Ergebnis:
#Init - execution took 1.00104497105349 seconds
quelle
Sie können die Nanosekunden wie folgt messen :
quelle
NSCalendar
Prozedur ist teuer, aber Sie können dies tun, bevor Sie mit der Ausführung Ihrer Prozedur beginnen, damit sie nicht zur Laufzeit Ihrer langen Prozedur hinzugefügt wird. Denken Sie daran, dass das Aufrufen des Erstellens einerNSDate
Instanz und das Aufrufen der–components(_:, fromDate:)
Methode immer noch Zeit in Anspruch nimmt Sie werden nie0.0
Nanosekunden bekommen .6.9
Mikrosekunden auf meinem Gerät.Ich benutze das:
Ich weiß nicht, ob es mehr oder weniger genau ist als zuvor veröffentlicht. Aber die Sekunden haben viele Dezimalstellen und scheinen kleine Codeänderungen in Algorithmen wie QuickSort mit swap () oder der Implementierung von swap urself usw. zu erfassen.
Denken Sie daran, Ihre Build-Optimierungen zu verbessern, wenn Sie die Leistung testen:
quelle
Hier ist mein Versuch für die einfachste Antwort:
Anmerkungen
startTime
undendTime
sind von der ArtTimeInterval
, die nur eintypealias
für istDouble
, so ist es einfach, es in eineInt
oder was auch immer umzuwandeln . Die Zeit wird in Sekunden mit einer Genauigkeit von weniger als einer Millisekunde gemessen.DateInterval
, einschließlich einer tatsächlichen Start- und Endzeit.quelle
Ich habe mir die Idee von Klaas geliehen, eine leichte Struktur zum Messen der Laufzeit und der Intervallzeit zu erstellen:
Code-Verwendung:
Die Stoppfunktion muss nicht aufgerufen werden, da die Druckfunktion die verstrichene Zeit angibt. Es kann wiederholt aufgerufen werden, um die abgelaufene Zeit zu erhalten. Um den Timer an einem bestimmten Punkt in der Code-Verwendung anzuhalten
timer.stop()
, kann er auch verwendet werden, um die Zeit in Sekunden zurückzugeben:let seconds = timer.stop()
Nach dem Anhalten des Timers wird der Intervall-Timer nicht mehr angezeigt , sodassprint("Running: \(timer) ")
auch nach einigen Codezeilen die richtige Zeit angezeigt wird .Es folgt der Code für RunningTimer. Es ist für Swift 2.1 getestet:
quelle
Wickeln Sie es zur einfachen Verwendung in einen Fertigstellungsblock.
quelle
Dies ist der Ausschnitt, den ich mir ausgedacht habe und der auf meinem Macbook mit Swift 4 zu funktionieren scheint.
Nie auf anderen Systemen getestet, aber ich dachte, es lohnt sich trotzdem zu teilen.
Hier ist ein Beispiel für die Verwendung:
Eine andere Möglichkeit besteht darin, dies expliziter zu tun:
quelle
So habe ich es geschrieben.
Um einen Algorithmus zu messen, verwenden Sie ihn so.
quelle
Statische Swift3-Klasse für das Timing grundlegender Funktionen. Jeder Timer wird anhand seines Namens verfolgt. Nennen Sie es an dem Punkt, an dem Sie mit der Messung beginnen möchten, so:
Rufen Sie dies auf, um die verstrichene Zeit zu erfassen und auszudrucken:
Dies ist die Ausgabe: *** PhotoCapture abgelaufen ms: 1402.415125 Es gibt einen "useNanos" -Parameter, wenn Sie Nanos verwenden möchten. Bitte zögern Sie nicht, nach Bedarf zu ändern.
}}
quelle
mach_timebase_info
ist bereits besser implementiert als im Quellcode vonProcessInfo.processInfo.systemUptime
. Also einfach tunwatches[name] = ProcessInfo.processInfo.systemUptime
. Und* TimeInterval(NSEC_PER_MSEC)
wenn Sie Nanos wollen.Basierend auf Franklin Yu Antwort und Cœur Kommentaren
Einzelheiten
Lösung 1
messen(_:)
Lösung 2
Verwendung der Lösung 2
quelle
Date
wird dringend davon abgeraten, etwas zu messen (abersystemUptime
oderclock()
sind in Ordnung). Tests haben wirmeasure(_:)
bereits.