Gibt es eine andere Möglichkeit / Software, um die genaue Zeit anzugeben, die zum Ausführen eines in Swift geschriebenen Codeblocks erforderlich ist, außer den folgenden?
let date_start = NSDate()
// Code to be executed
println("\(-date_start.timeIntervalSinceNow)")
swift
performance
ielyamani
quelle
quelle
Antworten:
Wenn Sie nur eine eigenständige Timing-Funktion für einen Codeblock benötigen, verwende ich die folgenden Swift-Hilfsfunktionen:
func printTimeElapsedWhenRunningCode(title:String, operation:()->()) { let startTime = CFAbsoluteTimeGetCurrent() operation() let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime print("Time elapsed for \(title): \(timeElapsed) s.") } func timeElapsedInSecondsWhenRunningCode(operation: ()->()) -> Double { let startTime = CFAbsoluteTimeGetCurrent() operation() let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime return Double(timeElapsed) }
Ersteres protokolliert die für einen bestimmten Codeabschnitt erforderliche Zeit, wobei letzteres diese als Float zurückgibt. Als Beispiel für die erste Variante:
printTimeElapsedWhenRunningCode(title:"map()") { let resultArray1 = randoms.map { pow(sin(CGFloat($0)), 10.0) } }
wird sich abmelden wie:
Beachten Sie, dass die Swift-Benchmarks je nach ausgewähltem Optimierungsgrad stark variieren. Dies kann daher nur für relative Vergleiche der Swift-Ausführungszeit hilfreich sein. Auch das kann sich pro Beta-Version ändern.
quelle
Wenn Sie einen Einblick in die Leistung eines bestimmten Codeblocks erhalten und sicherstellen möchten, dass die Leistung bei Änderungen nicht beeinträchtigt wird , verwenden Sie am besten die Messleistungsfunktionen von XCTest , z
measure(_ block: () -> Void)
.Schreiben Sie einen Komponententest, der die Methode ausführt, die Sie vergleichen möchten. Dieser Komponententest führt ihn mehrmals aus, sodass Sie Zeit benötigen und die Ergebnisse abweichen
func testExample() { self.measure { //do something you want to measure } }
Weitere Informationen finden Sie in den Apple-Dokumenten unter Testen mit Xcode -> Leistungstests
quelle
measureBlock
, dass der Blockcode mehrmals ausgeführt wird, um bessere Statistiken zu erhalten.measureBlock
? Woher kommt es (was soll ich importieren)? in Swift 4Mit dieser Funktion können Sie sowohl asynchronen als auch synchronen Code messen:
import Foundation func measure(_ title: String, block: (@escaping () -> ()) -> ()) { let startTime = CFAbsoluteTimeGetCurrent() block { let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime print("\(title):: Time: \(timeElapsed)") } }
Im Grunde übergeben Sie also einen Block, der eine Funktion als Parameter akzeptiert, mit der Sie messen, wann zu beenden ist.
Um beispielsweise zu messen, wie lange ein Aufruf mit dem Namen "myAsyncCall" dauert, würden Sie ihn folgendermaßen aufrufen:
measure("some title") { finish in myAsyncCall { finish() } // ... }
Für synchronen Code:
measure("some title") { finish in // code to benchmark finish() // ... }
Dies sollte MeasureBlock von XCTest ähneln, obwohl ich nicht weiß, wie genau es dort implementiert ist.
quelle
Benchmarking-Funktion - Swift 4.2
Dies ist eine unglaublich vielseitige Benchmarking-Funktion, die es ermöglicht, Tests zu kennzeichnen, viele Tests durchzuführen und ihre Ausführungszeiten zu mitteln. Dies ist ein Setup-Block, der zwischen den Tests aufgerufen wird (dh das Mischen eines Arrays zwischen dem Messen eines Sortieralgorithmus) und das klare Drucken des Benchmarking Ergebnisse, und es gibt auch die durchschnittliche Ausführungszeit als
Double
.Versuche Folgendes:
@_transparent @discardableResult public func measure(label: String? = nil, tests: Int = 1, printResults output: Bool = true, setup: @escaping () -> Void = { return }, _ block: @escaping () -> Void) -> Double { guard tests > 0 else { fatalError("Number of tests must be greater than 0") } var avgExecutionTime : CFAbsoluteTime = 0 for _ in 1...tests { setup() let start = CFAbsoluteTimeGetCurrent() block() let end = CFAbsoluteTimeGetCurrent() avgExecutionTime += end - start } avgExecutionTime /= CFAbsoluteTime(tests) if output { let avgTimeStr = "\(avgExecutionTime)".replacingOccurrences(of: "e|E", with: " × 10^", options: .regularExpression, range: nil) if let label = label { print(label, "▿") print("\tExecution time: \(avgTimeStr)s") print("\tNumber of tests: \(tests)\n") } else { print("Execution time: \(avgTimeStr)s") print("Number of tests: \(tests)\n") } } return avgExecutionTime }
Verwendung
var arr = Array(1...1000).shuffled() measure(label: "Map to String") { let _ = arr.map { String($0) } } measure(label: "Apple Shuffle", tests: 1000, setup: { arr.shuffle() }) { arr.sort() } measure { let _ = Int.random(in: 1...10000) } let mathExecutionTime = measure(printResults: false) { let _ = 219 * 354 } print("Math Execution Time: \(mathExecutionTime * 1000)ms") // Prints: // // Map to String ▿ // Execution time: 0.021643996238708496s // Number of tests: 1 // // Apple's Sorting Method ▿ // Execution time: 0.0010601345300674438s // Number of tests: 1000 // // Execution time: 6.198883056640625 × 10^-05s // Number of tests: 1 // // Math Execution Time: 0.016927719116210938ms //
Hinweis:
measure
Gibt auch die Ausführungszeit zurück. Dielabel
,tests
undsetup
Argumente sind optional. DasprintResults
Argument isttrue
standardmäßig eingestellt.quelle
Ich mag Brad Larsons Antwort auf einen einfachen Test, den Sie sogar auf einem Spielplatz durchführen können. Für meine eigenen Bedürfnisse habe ich es ein bisschen optimiert:
averageTimeTo()
Benchmarking-Funktion aufnehmen muss.averageTime
(was Sie von einer Funktion namens 'durchschnittlichTimeTo' erwarten können), sodass keine zwei separaten Funktionen mit nahezu identischer Funktionalität erforderlich sind.Zum Beispiel:
func myFunction(args: Int...) { // Do something } func testMyFunction() -> String { // Wrap the call to myFunction here, and optionally test with different arguments myFunction(args: 1, 2, 3) return #function } // Measure average time to complete test func averageTimeTo(_ testFunction: () -> String, repeated reps: UInt = 10) -> Double { let functionName = testFunction() var totalTime = 0.0 for _ in 0..<reps { let startTime = CFAbsoluteTimeGetCurrent() testFunction() let elapsedTime = CFAbsoluteTimeGetCurrent() - startTime totalTime += elapsedTime } let averageTime = totalTime / Double(reps) print("Total time to \(functionName) \(reps) times: \(totalTime) seconds") print("Average time to \(functionName): \(averageTime) seconds\n") return averageTime } averageTimeTo(testMyFunction) // Total time to testMyFunction() 10 times: 0.000253915786743164 seconds // Average time to testMyFunction(): 2.53915786743164e-05 seconds averageTimeTo(testMyFunction, repeated: 1000) // Total time to testMyFunction() 1000 times: 0.027538537979126 seconds // Average time to testMyFunction(): 2.7538537979126e-05 seconds
quelle
@discardableResult
könnte nützlich sein, da Sie bereits dieaverageTime
Sie haben mehrere Möglichkeiten
CFAbsoluteTimeGetCurrent
Date().timeIntervalSince1970
DispatchTime.now().uptimeNanoseconds
(und div am 1_000_000)let metrics: [XCTMetric] = [XCTMemoryMetric(), XCTStorageMetric(), XCTClockMetric()] let measureOptions = XCTMeasureOptions.default measureOptions.iterationCount = 3 measure(metrics: metrics, options: measureOptions) { //block of code }
* Ich würde Ihnen nicht empfehlen, eine allgemeine Funktion mit
measure
Block zu erstellen , da Xcode manchmal nicht richtig damit umgehen kann. Verwenden Sie deshalbmeasure
Block für jeden Leistungstestquelle