[swift] Swift에서 경과 시간 측정
Swift에서 함수를 실행하는 데 걸린 시간을 어떻게 측정 할 수 있습니까? 다음과 같이 경과 시간을 표시하려고합니다. “경과 시간은 .05 초입니다”. 자바에서 봤어 , 우리는 System.nanoTime ()를 사용하여 동등한 방법은 이러한 목표를 달성하기 위해 스위프트에서 사용할 수 있습니다 무엇입니까?
샘플 프로그램을 살펴보십시오 :
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 에서 Project Euler 문제 를 측정하기 위해 작성한 Swift 함수입니다.
Swift 3부터는 “swiftified”버전의 Grand Central Dispatch가 있습니다. 따라서 정답은 아마도 DispatchTime API 를 사용하는 것입니다 .
내 기능은 다음과 같습니다.
// Swift 3
func evaluateProblem(problemNumber: Int, problemBlock: () -> Int) -> Answer
{
print("Evaluating problem \(problemNumber)")
let start = DispatchTime.now() // <<<<<<<<<< Start time
let myGuess = problemBlock()
let end = DispatchTime.now() // <<<<<<<<<< end time
let theAnswer = self.checkAnswer(answerNum: "\(problemNumber)", guess: myGuess)
let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds // <<<<< Difference in nano seconds (UInt64)
let timeInterval = Double(nanoTime) / 1_000_000_000 // Technically could overflow for long running tests
print("Time to evaluate problem \(problemNumber): \(timeInterval) seconds")
return theAnswer
}
이전 답변
Swift 1과 2의 경우 내 함수는 NSDate를 사용합니다.
// Swift 1
func evaluateProblem(problemNumber: Int, problemBlock: () -> Int) -> Answer
{
println("Evaluating problem \(problemNumber)")
let start = NSDate() // <<<<<<<<<< Start time
let myGuess = problemBlock()
let end = NSDate() // <<<<<<<<<< end time
let theAnswer = self.checkAnswer(answerNum: "\(problemNumber)", guess: myGuess)
let timeInterval: Double = end.timeIntervalSinceDate(start) // <<<<< Difference in seconds (double)
println("Time to evaluate problem \(problemNumber): \(timeInterval) seconds")
return theAnswer
}
타이밍 기능에 NSdate를 사용하는 것은 권장되지 않습니다. ” 외부 시간 참조와의 동기화 또는 시계의 명시적인 사용자 변경으로 인해 시스템 시간이 감소 할 수 있습니다. “.
답변
이것은 CoreFoundation
s를 기반으로 한 편리한 타이머 클래스입니다 CFAbsoluteTime
.
import CoreFoundation
class ParkBenchTimer {
let startTime:CFAbsoluteTime
var endTime:CFAbsoluteTime?
init() {
startTime = CFAbsoluteTimeGetCurrent()
}
func stop() -> CFAbsoluteTime {
endTime = CFAbsoluteTimeGetCurrent()
return duration!
}
var duration:CFAbsoluteTime? {
if let endTime = endTime {
return endTime - startTime
} else {
return nil
}
}
}
다음과 같이 사용할 수 있습니다.
let timer = ParkBenchTimer()
// ... a long runnig task ...
println("The task took \(timer.stop()) seconds.")
답변
간단한 시작 시간 clock
에는 ProcessInfo.systemUptime
, 또는를 사용하십시오 DispatchTime
.
내가 아는 한, 경과 시간을 측정하는 방법은 최소한 10 가지입니다.
Monotonic Clock 기반 :
ProcessInfo.systemUptime
.mach_absolute_time
과mach_timebase_info
에서 언급 한 바와 같이 이 답변 .clock()
에서 POSIX 표준 .times()
에서 POSIX 표준 . (사용자 시간과 시스템 시간을 고려해야하고 하위 프로세스가 관련되어 있으므로 너무 복잡합니다.)DispatchTime
(Mach time API를 둘러싼 래퍼) JeremyP가 수락 한 답변에서 언급했습니다.CACurrentMediaTime()
.
벽시계 기반 :
(측정 항목에는 절대 사용하지 마세요. 아래 이유를 참조하세요.)
NSDate
/Date
다른 사람들이 언급했듯이.CFAbsoluteTime
다른 사람들이 언급했듯이.DispatchWallTime
.gettimeofday()
에서 POSIX 표준 .
옵션 1, 2 및 3은 아래에 자세히 설명되어 있습니다.
옵션 1 : Foundation의 Process Info API
do {
let info = ProcessInfo.processInfo
let begin = info.systemUptime
// do something
let diff = (info.systemUptime - begin)
}
어디 diff:NSTimeInterval
초 의해 경과 시간이다.
옵션 2 : Mach C API
do {
var info = mach_timebase_info(numer: 0, denom: 0)
mach_timebase_info(&info)
let begin = mach_absolute_time()
// do something
let diff = Double(mach_absolute_time() - begin) * Double(info.numer) / Double(info.denom)
}
어디 diff:Double
나노초 단위의 경과 시간은 ?
옵션 3 : POSIX 클록 API
do {
let begin = clock()
// do something
let diff = Double(clock() - begin) / Double(CLOCKS_PER_SEC)
}
어디 diff:Double
초 의해 경과 시간이다.
경과 시간에 대한 벽시계 시간이 아닌 이유는 무엇입니까?
문서에서 CFAbsoluteTimeGetCurrent
:
이 함수에 대한 반복 호출은 단조롭게 증가하는 결과를 보장하지 않습니다.
이유는 Java의 currentTimeMillis
vsnanoTime
와 유사합니다 .
다른 목적으로 사용할 수 없습니다. 그 이유는 컴퓨터의 시계가 완벽하지 않기 때문입니다. 항상 표류하며 때때로 수정해야합니다. 이 수정은 수동으로 이루어 지거나 대부분의 컴퓨터에서 실행되고 시스템 시계 ( “벽 시계”)에 대한 작은 수정을 지속적으로 발행하는 프로세스가 있습니다. 이들은 자주 발생하는 경향이 있습니다. 또 다른 수정은 윤초가있을 때마다 발생합니다.
여기 CFAbsoluteTime
에서는 시작 시간 대신 벽시계 시간을 제공합니다. NSDate
벽시계 시간이기도합니다.
답변
Swift 4 짧은 답변 :
let startingPoint = Date()
// ... intensive task
print("\(startingPoint.timeIntervalSinceNow * -1) seconds elapsed")
1.02107906341553 초가 경과 한 것과 같은 것을 인쇄 할 것 입니다 (물론 시간은 작업에 따라 다를 수 있습니다.이 측정에 대한 십진 정밀도 수준을 볼 수 있도록 보여 드리겠습니다).
지금부터 Swift 4의 누군가에게 도움이되기를 바랍니다!
최신 정보
코드의 일부를 테스트하는 일반적인 방법을 원한다면 다음 스 니펫을 제안합니다.
func measureTime(for closure: @autoclosure () -> Any) {
let start = CFAbsoluteTimeGetCurrent()
closure()
let diff = CFAbsoluteTimeGetCurrent() - start
print("Took \(diff) seconds")
}
*Usage*
measureTime(for: <insert method signature here>)
**Console log**
Took xx.xxxxx seconds
답변
let start = NSDate()
for index in 1...10000 {
// do nothing
}
let elapsed = start.timeIntervalSinceNow
// elapsed is a negative value.
답변
이 기능을 복사하여 붙여 넣기 만하면됩니다. swift 5. 여기에 JeremyP를 복사합니다.
func calculateTime(block : (() -> Void)) {
let start = DispatchTime.now()
block()
let end = DispatchTime.now()
let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
let timeInterval = Double(nanoTime) / 1_000_000_000
print("Time: \(timeInterval) seconds")
}
그것을 사용하십시오
calculateTime {
exampleFunc()// function whose execution time to be calculated
}
답변
time
호출을 측정 하는 함수를 만들 수 있습니다 . 나는 Klaas의 대답에 영감을 받았습니다 .
func time <A> (f: @autoclosure () -> A) -> (result:A, duration: String) {
let startTime = CFAbsoluteTimeGetCurrent()
let result = f()
let endTime = CFAbsoluteTimeGetCurrent()
return (result, "Elapsed time is \(endTime - startTime) seconds.")
}
이 함수를 사용하면 time (isPrime(7))
결과와 경과 시간에 대한 문자열 설명을 포함하는 튜플을 반환하는 다음과 같이 호출 할 수 있습니다 .
경과 시간 만 원하는 경우이 작업을 수행 할 수 있습니다. time (isPrime(7)).duration