Swift에서 경과 시간 측정


132

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");
}

1
시간 측정 문제와 관련이 없지만에서 sqrt(number)대신 루프를 멈출 수 있으며 number시간을 조금 더 절약 할 수 있습니다.
holex

@holex 사용 된 알고리즘을 무시하십시오. 경과 시간을 측정하는 방법을 알아 내려고합니다.
Vaquita 2014

1
당신이 사용할 수있는 NSDate객체를 그리고 당신은 그들 사이의 차이를 측정 할 수 있습니다.
holex

4
XCode를 사용하는 경우 새로운 성능 테스트 기능을 사용하는 것이 좋습니다. 그것은 당신에 대한 모든 무거운 리프팅을 수행하고도 ... 여러 번 실행하면 표준 편차와 평균 시간을 제공합니다
의 Roshan

1
@dumbledad 단위 테스트에서 전체 블록의 성능을 직접 측정 할 수 있습니다. 예를 들어 다음을 참조하십시오 . 실행을 더 자세히 나누고 싶다면 (예 : 한 줄씩 코드) Instruments의 일부인 Time Profiler 를 확인하십시오 . 이것은 훨씬 더 강력하고 포괄적입니다.
Roshan

답변:


229

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


이것은 약 +/- 2microsec까지 좋은 결과를 제공하는 것으로 보입니다. 그러나 플랫폼에 따라 다를 수 있습니다.
user1021430

6
swift3는 나를 위해 작동하지 않습니다. 0.0114653027을 반환합니다. 사실이 아닌 사실을 알고 있습니다. 날짜가있는 것은 4.77720803022385sec를 반환합니다.
Cristi Băluță

5
불행히도. 어떤 이유로 가동 시간이 완전히 사라졌습니다. 1004959766 나노초 (약 1 초)가 걸렸지 만 확실히 약 40 초 동안 실행 중이라는 테스트가 있습니다. 나는 Date함께 사용 했고 41.87 초를보고 할만큼 충분히 확신했다. 나는 무엇 uptimeNanoseconds을하고 있는지 모르지만 올바른 기간을보고하지 않습니다.
jowie

2
새로운 솔루션의 우선 순위를 정하고 큰 편집에 대해 죄송하지만 NSDate 코드를 완전히 삭제하는 것이 좋습니다. 네트워크 시간 동기화 (NTP)가 시계를 업데이트 (드리프트를 조정하기 위해 자주 발생 함), DST 조정, 윤초 및 시계의 사용자 수동 조정. 또한 Swift 1 : Swift 3을 사용하는 앱은 더 이상 AppStore에 게시 할 수 없습니다. 따라서 "하지 마세요"라고 말하는 것 외에 NSDate 코드를 유지할 필요가 없습니다.
Cœur

1
@ Cœur NSDate 버전에 대한 귀하의 비판은 유효하며 (DST 변경 사항은 항상 GMT에있는 NSDate에 영향을주지 않음) 순서를 반대로 수정하는 것은 확실히 개선 된 것입니다.
JeremyP

69

이것은 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.")

4
" 이 함수에 대한 반복적 인 호출은 단조롭게 증가하는 결과를 보장하지 않습니다. " 문서 에 따르면 .
Franklin Yu

8
더 많은 컨텍스트 : "이 함수에 대한 반복 호출은 단조롭게 증가하는 결과를 보장하지 않습니다. 외부 시간 참조와의 동기화 또는 시계의 명시적인 사용자 변경으로 인해 시스템 시간이 감소 할 수 있습니다 ."
Klaas

개발자는 "외부 시간 참조와의 동기화"및 "시계의 명시적인 사용자 변경"을 고려해야합니다. 두 가지 상황이 발생하는 것이 불가능하다는 뜻입니까?
Franklin Yu

@FranklinYu 아니요, 두 가지 가능한 이유가 있다고 말하고 싶었습니다. 항상 단조롭게 증가하는 값에 의존하는 경우 다른 옵션이 있습니다.
Klaas

때로는 짧은 시간을 측정하고 싶습니다. 그 동안 동기화가 발생하면 부정적인 시간이 될 수 있습니다. 실제로이 mach_absolute_time문제로 고통받지 않는 것이 있는데 , 왜 그것이 널리 알려지지 않았는지 궁금합니다. 잘 문서화되지 않았기 때문일 수도 있습니다.
Franklin Yu

54

간단한 시작 시간 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벽시계 시간이기도합니다.


최선의 대답-그러나 도대체 최선의 접근 방법은 무엇입니까?!
Fattie 16.16.16

1
옵션 5가 나에게 가장 적합했습니다. 다중 플랫폼 코드를 고려하고 있다면 이것을 시도하십시오. Darwin 및 Glibc 라이브러리 모두 clock()기능 이 있습니다.
Misha Svyatoshenko

시스템 시계 기반 솔루션의 경우 : 내가 성공을했다 ProcessInfo.processInfo.systemUptime, mach_absolute_time(), DispatchTime.now()CACurrentMediaTime(). 그러나 솔루션 clock()은 초 단위로 제대로 변환되지 않았습니다. 나는 당신의 첫 문장 업데이트 할 권합니다 그래서 " 정확한 시작 시간을 사용 ProcessInfo.systemUptime 또는 DispatchTime을. "
쾨르

36

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

누군가 왜 * -1을 설명 할 수 있습니까?
Maksim Kniazev

1
@MaksimKniazev 부정적인 가치이기 때문에 사람들은 긍정적 인 가치를 원합니다!
thachnb

@thachnb 나는 아무 생각 "startingPoint.timeIntervalSinceNow"을 없었다 ... 음의 값을 생성
막심 Kniazev

1
@MaksimKniazev Apple은 다음과 같이 말합니다. 날짜 개체가 현재 날짜 및 시간보다 이전이면이 속성 값은 음수입니다.
Peter Guan

13
let start = NSDate()

for index in 1...10000 {
    // do nothing
}

let elapsed = start.timeIntervalSinceNow

// elapsed is a negative value.

2
ABS (start.timeIntervalSinceNow) // <- 양수
eonist

제가 본 것 중 가장 간단한 해결책입니다. 감사합니다
MiladiuM

10

이 기능을 복사하여 붙여 넣기 만하면됩니다. 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
}

6

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


3
"이 함수에 대한 반복적 인 호출은 단조롭게 증가하는 결과를 보장하지 않습니다." 문서 에 따르면 .
Franklin Yu

3

클로저로 실행 시간을 측정하는 간단한 도우미 기능.

func printExecutionTime(withTag tag: String, of closure: () -> ()) {
    let start = CACurrentMediaTime()
    closure()
    print("#\(tag) - execution took \(CACurrentMediaTime() - start) seconds")
}

용법:

printExecutionTime(withTag: "Init") {
    // Do your work here
}

결과: #Init - execution took 1.00104497105349 seconds


2

다음 과 같이 나노초 를 측정 할 수 있습니다 .

let startDate: NSDate = NSDate()

// your long procedure

let endDate: NSDate = NSDate()
let dateComponents: NSDateComponents = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian).components(NSCalendarUnit.CalendarUnitNanosecond, fromDate: startDate, toDate: endDate, options: NSCalendarOptions(0))
println("runtime is nanosecs : \(dateComponents.nanosecond)")

방금 "// your long procedure"에 코드를 넣지 않고 실행 한 결과 240900993 (0.24 초)이 나왔습니다.
user1021430

인스턴스화 NSCalendar는 비용이 많이 드는 프로 시저이지만 프로 시저 실행을 시작 하기 전에 수행 할 수 있으므로 긴 프로 시저의 런타임에 추가되지 않습니다. NSDate인스턴스 생성 을 호출하고 –components(_:, fromDate:)메서드를 호출 하는 데 여전히 시간이 걸립니다. 당신은 결코 0.0나노초를 얻지 못할 것 입니다.
holex

NSCalendar 생성자의 모양을 보면 미리 생성 할 수없는 것처럼 보입니다 (startDate는 필수 입력입니다). 그런 돼지 인 것 같아 놀랍습니다.
user1021430

당신은 이것을 할 수 있습니다 (내 업데이트 된 답변), 추가 절차없이 측정 된 시간은 6.9내 장치에서 약 마이크로 초입니다.
holex

감사합니다. 기본 절차는 이제 JeremyP의 답변과 비슷하지만보고 내용이 다릅니다.
user1021430 2014-08-14

2

나는 이것을 사용한다 :

public class Stopwatch {
    public init() { }
    private var start_: NSTimeInterval = 0.0;
    private var end_: NSTimeInterval = 0.0;

    public func start() {
        start_ = NSDate().timeIntervalSince1970;
    }

    public func stop() {
        end_ = NSDate().timeIntervalSince1970;
    }

    public func durationSeconds() -> NSTimeInterval {
        return end_ - start_;
    }
}

나는 그것이 이전에 게시 된 것보다 다소 정확한지 모르겠습니다. 그러나 초는 십진수가 많고 swap ()을 사용하는 QuickSort와 같은 알고리즘에서 작은 코드 변경 사항을 포착하는 것 같습니다.

성능을 테스트 할 때 빌드 최적화를 강화하는 것을 잊지 마십시오.

Swift 컴파일러 최적화


2

가장 간단한 대답을위한 나의 시도는 다음과 같습니다.

let startTime = Date().timeIntervalSince1970  // 1512538946.5705 seconds

// time passes (about 10 seconds)

let endTime = Date().timeIntervalSince1970    // 1512538956.57195 seconds
let elapsedTime = endTime - startTime         // 10.0014500617981 seconds

노트

  • startTimeendTime유형 TimeIntervaltypealiasfor Double일 뿐이 므로 쉽게 변환 할 수 Int있습니다. 시간은 밀리 초 미만의 정밀도로 초 단위로 측정됩니다.
  • DateInterval실제 시작 및 종료 시간이 포함 된을 참조하십시오 .
  • 1970 년 이후의 시간을 사용하는 것은 Java 타임 스탬프 와 유사합니다 .

가장 쉬운 방법은 두 개의 문자열에서 원하는 것입니다. 두 번째는 let elapsedTime = Date (). timeIntervalSince1970-startTime
FreeGor

1

나는 Klaas에서 아이디어를 빌려 러닝 및 인터벌 시간을 측정하는 경량 구조체를 만들었습니다.

코드 사용 :

var timer = RunningTimer.init()
// Code to be timed
print("Running: \(timer) ") // Gives time interval
// Second code to be timed
print("Running: \(timer) ") // Gives final time

인쇄 기능이 경과 시간을 제공하므로 중지 기능을 호출 할 필요가 없습니다. 시간 경과를 얻기 위해 반복적으로 호출 될 수 있습니다. 그러나 코드의 특정 지점에서 타이머를 중지하려면 timer.stop()시간을 초 단위로 반환하는 데 사용할 수도 있습니다 let seconds = timer.stop() . 타이머가 중지 된 후에는 간격 타이머가 작동하지 않으므로 print("Running: \(timer) ")몇 줄의 코드 후에도 올바른 시간을 제공합니다.

다음은 RunningTimer의 코드입니다. Swift 2.1에서 테스트되었습니다.

import CoreFoundation
// Usage:    var timer = RunningTimer.init()
// Start:    timer.start() to restart the timer
// Stop:     timer.stop() returns the time and stops the timer
// Duration: timer.duration returns the time
// May also be used with print(" \(timer) ")

struct RunningTimer: CustomStringConvertible {
    var begin:CFAbsoluteTime
    var end:CFAbsoluteTime

    init() {
        begin = CFAbsoluteTimeGetCurrent()
        end = 0
    }
    mutating func start() {
        begin = CFAbsoluteTimeGetCurrent()
        end = 0
    }
    mutating func stop() -> Double {
        if (end == 0) { end = CFAbsoluteTimeGetCurrent() }
        return Double(end - begin)
    }
    var duration:CFAbsoluteTime {
        get {
            if (end == 0) { return CFAbsoluteTimeGetCurrent() - begin } 
            else { return end - begin }
        }
    }
    var description:String {
    let time = duration
    if (time > 100) {return " \(time/60) min"}
    else if (time < 1e-6) {return " \(time*1e9) ns"}
    else if (time < 1e-3) {return " \(time*1e6) µs"}
    else if (time < 1) {return " \(time*1000) ms"}
    else {return " \(time) s"}
    }
}

1

쉽게 사용할 수 있도록 완성 블록에 포장하십시오.

public class func secElapsed(completion: () -> Void) {
    let startDate: NSDate = NSDate()
    completion()
    let endDate: NSDate = NSDate()
    let timeInterval: Double = endDate.timeIntervalSinceDate(startDate)
    println("seconds: \(timeInterval)")
}

0

이것은 내가 생각해 낸 스 니펫이며 Swift 4가 설치된 Macbook에서 작동하는 것 같습니다.

다른 시스템에서는 테스트하지 않았지만 어쨌든 공유 할 가치가 있다고 생각했습니다.

typealias MonotonicTS = UInt64
let monotonic_now: () -> MonotonicTS = mach_absolute_time

let time_numer: UInt64
let time_denom: UInt64
do {
    var time_info = mach_timebase_info(numer: 0, denom: 0)
    mach_timebase_info(&time_info)
    time_numer = UInt64(time_info.numer)
    time_denom = UInt64(time_info.denom)
}

// returns time interval in seconds
func monotonic_diff(from: MonotonicTS, to: MonotonicTS) -> TimeInterval {
    let diff = (to - from)
    let nanos = Double(diff * time_numer / time_denom)
    return nanos / 1_000_000_000
}

func seconds_elapsed(since: MonotonicTS) -> TimeInterval {
    return monotonic_diff(from: since, to:monotonic_now())
}

다음은 사용 방법의 예입니다.

let t1 = monotonic_now()
// .. some code to run ..
let elapsed = seconds_elapsed(since: t1)
print("Time elapsed: \(elapsed*1000)ms")

또 다른 방법은 더 명시 적으로 수행하는 것입니다.

let t1 = monotonic_now()
// .. some code to run ..
let t2 = monotonic_now()
let elapsed = monotonic_diff(from: t1, to: t2)
print("Time elapsed: \(elapsed*1000)ms")

0

이것이 내가 쓴 방법입니다.

 func measure<T>(task: () -> T) -> Double {
        let startTime = CFAbsoluteTimeGetCurrent()
        task()
        let endTime = CFAbsoluteTimeGetCurrent()
        let result = endTime - startTime
        return result
    }

알고리즘을 측정하려면 그렇게 사용 하십시오.

let time = measure {
    var array = [2,4,5,2,5,7,3,123,213,12]
    array.sorted()
}

print("Block is running \(time) seconds.")

그 시간은 얼마나 정확합니까? 0.1 초마다 업데이트하기 전에 타이머를 사용했기 때문입니다. 이 답변과 타이머를 비교 한 결과,이 답변의 결과는 타이머보다 0.1 초 더
큽니다

0

기본 함수 타이밍을위한 정적 Swift3 클래스. 이름별로 각 타이머를 추적합니다. 측정을 시작하려는 지점에서 다음과 같이 호출하십시오.

Stopwatch.start(name: "PhotoCapture")

경과 시간을 캡처하고 인쇄하려면 다음을 호출하십시오.

Stopwatch.timeElapsed(name: "PhotoCapture")

다음은 출력입니다. *** PhotoCapture elapsed ms : 1402.415125 나노를 사용하려는 경우 "useNanos"매개 변수가 있습니다. 필요에 따라 자유롭게 변경하십시오.

   class Stopwatch: NSObject {

  private static var watches = [String:TimeInterval]()

  private static func intervalFromMachTime(time: TimeInterval, useNanos: Bool) -> TimeInterval {
     var info = mach_timebase_info()
     guard mach_timebase_info(&info) == KERN_SUCCESS else { return -1 }
     let currentTime = mach_absolute_time()
     let nanos = currentTime * UInt64(info.numer) / UInt64(info.denom)
     if useNanos {
        return (TimeInterval(nanos) - time)
     }
     else {
        return (TimeInterval(nanos) - time) / TimeInterval(NSEC_PER_MSEC)
     }
  }

  static func start(name: String) {
     var info = mach_timebase_info()
     guard mach_timebase_info(&info) == KERN_SUCCESS else { return }
     let currentTime = mach_absolute_time()
     let nanos = currentTime * UInt64(info.numer) / UInt64(info.denom)
     watches[name] = TimeInterval(nanos)
  }

  static func timeElapsed(name: String) {
     return timeElapsed(name: name, useNanos: false)
  }

  static func timeElapsed(name: String, useNanos: Bool) {
     if let start = watches[name] {
        let unit = useNanos ? "nanos" : "ms"
        print("*** \(name) elapsed \(unit): \(intervalFromMachTime(time: start, useNanos: useNanos))")
     }
  }

}


와 전체 작업은 mach_timebase_info당신이에서보다 이미 더 나은 구현 소스 코드ProcessInfo.processInfo.systemUptime. 그래서 간단하게하십시오 watches[name] = ProcessInfo.processInfo.systemUptime. 그리고 * TimeInterval(NSEC_PER_MSEC)나노를 원한다면.
Cœur

0

을 바탕으로 프랭클린 유 대답과 쾨르의 의견

세부

  • Xcode 10.1 (10B61)
  • 스위프트 4.2

해결책 1

법안(_:)

해결책 2

import Foundation

class Measurer<T: Numeric> {

    private let startClosure: ()->(T)
    private let endClosure: (_ beginningTime: T)->(T)

    init (startClosure: @escaping ()->(T), endClosure: @escaping (_ beginningTime: T)->(T)) {
        self.startClosure = startClosure
        self.endClosure = endClosure
    }

    init (getCurrentTimeClosure: @escaping ()->(T)) {
        startClosure = getCurrentTimeClosure
        endClosure = { beginningTime in
            return getCurrentTimeClosure() - beginningTime
        }
    }

    func measure(closure: ()->()) -> T {
        let value = startClosure()
        closure()
        return endClosure(value)
    }
}

솔루션 2의 사용법

// Sample with ProcessInfo class

m = Measurer { ProcessInfo.processInfo.systemUptime }
time = m.measure {
    _ = (1...1000).map{_ in Int(arc4random()%100)}
}
print("ProcessInfo: \(time)")

// Sample with Posix clock API

m = Measurer(startClosure: {Double(clock())}) { (Double(clock()) - $0 ) / Double(CLOCKS_PER_SEC) }
time = m.measure {
    _ = (1...1000).map{_ in Int(arc4random()%100)}
}
print("POSIX: \(time)")

변수 구현을 사용해야하는 이유를 모르겠습니다. 사용 Date아무것도를 측정하는 것은 매우 낙담 (되지만, systemUptime또는 clock()OK입니다). 테스트에 관해서는 measure(_:)이미 있습니다.
Cœur

1
또 다른 메모 : 폐쇄를 선택적으로 만드는 이유는 무엇입니까?
Cœur

@ Cœur 맞아! 귀하의 의견에 감사드립니다. 나중에 게시물을 업데이트하겠습니다.
Vasily Bodnarchuk 2019 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.