[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를 사용하는 것은 권장되지 않습니다. ” 외부 시간 참조와의 동기화 또는 시계의 명시적인 사용자 변경으로 인해 시스템 시간이 감소 할 수 있습니다. “.


답변

이것은 CoreFoundations를 기반으로 한 편리한 타이머 클래스입니다 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 기반 :

  1. ProcessInfo.systemUptime.
  2. mach_absolute_timemach_timebase_info에서 언급 한 바와 같이 이 답변 .
  3. clock()에서 POSIX 표준 .
  4. times()에서 POSIX 표준 . (사용자 시간과 시스템 시간을 고려해야하고 하위 프로세스가 관련되어 있으므로 너무 복잡합니다.)
  5. DispatchTime (Mach time API를 둘러싼 래퍼) JeremyP가 수락 한 답변에서 언급했습니다.
  6. CACurrentMediaTime().

벽시계 기반 :

(측정 항목에는 절대 사용하지 마세요. 아래 이유를 참조하세요.)

  1. NSDate/ Date다른 사람들이 언급했듯이.
  2. CFAbsoluteTime 다른 사람들이 언급했듯이.
  3. DispatchWallTime.
  4. 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의 currentTimeMillisvsnanoTime 와 유사합니다 .

다른 목적으로 사용할 수 없습니다. 그 이유는 컴퓨터의 시계가 완벽하지 않기 때문입니다. 항상 표류하며 때때로 수정해야합니다. 이 수정은 수동으로 이루어 지거나 대부분의 컴퓨터에서 실행되고 시스템 시계 ( “벽 시계”)에 대한 작은 수정을 지속적으로 발행하는 프로세스가 있습니다. 이들은 자주 발생하는 경향이 있습니다. 또 다른 수정은 윤초가있을 때마다 발생합니다.

여기 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