Meça o tempo decorrido no Swift


132

Como podemos medir o tempo decorrido para executar uma função no Swift? Estou tentando exibir o tempo decorrido assim: "O tempo decorrido é 0,05 segundos". Vimos que em Java , podemos usar System.nanoTime (), existem métodos equivalentes disponíveis no Swift para fazer isso?

Por favor, dê uma olhada no programa de amostra:

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
ele não está relacionado ao seu problema de medição do tempo, mas o loop pode ser interrompido em sqrt(number)vez de numbere você pode economizar um pouco mais de tempo - mas há muito mais idéias para otimizar a busca por números primos.
holex

@holex Por favor, ignore o algoritmo usado. Estou tentando descobrir como podemos medir o tempo decorrido?
Vaquita

1
você pode usar NSDateobjetos e medir a diferença entre eles.
holex

4
Se você estiver usando o XCode, recomendo que você use o novo recurso de teste de desempenho. Ele faz todo o trabalho pesado para você e até mesmo corre-lo várias vezes e dá-lhe o tempo médio com o seu desvio padrão ...
Roshan

1
@dumbledad Você pode medir o desempenho de blocos inteiros diretamente em testes de unidade. Por exemplo, veja isso . Se você deseja detalhar mais (digamos, código de linha por linha), consulte o Time Profiler, que faz parte dos Instrumentos. Isso é muito mais poderoso e abrangente.
Roshan

Respostas:


229

Aqui está uma função do Swift que escrevi para medir os problemas do Project Euler no Swift

A partir do Swift 3, agora existe uma versão do Grand Central Dispatch que é "swiftified". Portanto, a resposta correta provavelmente é usar a API DispatchTime .

Minha função seria algo como:

// 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
}

Resposta antiga

Para Swift 1 e 2, minha função usa 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
}

Observe que o uso do NSdate para funções de temporização é desencorajado: " A hora do sistema pode diminuir devido à sincronização com referências de hora externas ou devido a uma alteração explícita do usuário no relógio. ".


Isso parece dar bons resultados em torno de +/- 2microsec. Talvez isso varie por plataforma, no entanto.
user1021430

6
swift3 não funciona para mim, ele retorna 0,0114653027, que eu sei por um fato que não é verdade, aquele com datas retorna 4.77720803022385sec #
Cristi Băluță

5
Infelizmente não. O tempo de atividade está completamente esgotado por algum motivo. Eu tenho um teste que diz que levou 1004959766 nanossegundos (cerca de um segundo), mas definitivamente estava em execução por cerca de 40 segundos. Eu usei Dateao lado, e com certeza isso relata 41,87 segundos. Não sei o que uptimeNanosecondsestá fazendo, mas não está relatando a duração correta.
jowie

2
Desculpe pela grande edição, priorizando sua solução mais recente, mas eu recomendaria excluir o código NSDate completamente: não é totalmente confiável usar o NSDate: o NSDate é baseado no relógio do sistema, que pode ser alterado a qualquer momento devido a vários motivos diferentes, como como a sincronização da hora da rede (NTP) atualizando o relógio (geralmente acontece para ajustar a deriva), os ajustes de horário de verão, os segundos bissextos e o ajuste manual do usuário do relógio. Além disso, você não pode publicar mais na AppStore nenhum aplicativo usando o Swift 1: Swift 3 é o mínimo. Portanto, não há nenhum ponto em manter seu código NSDate a não ser dizer "não faça".
Cœur

1
@ Sua crítica à versão do NSDate é válida (exceto que as alterações no horário de verão não afetam o NSDate, que está sempre no GMT), e sua edição para reverter a ordem é definitivamente uma melhoria.
26419 JeremyP

69

Esta é uma classe de timer prática, baseada em 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
        }
    }
}

Você pode usá-lo assim:

let timer = ParkBenchTimer()

// ... a long runnig task ...

println("The task took \(timer.stop()) seconds.")

4
" Chamadas repetidas para esta função não garantem resultados crescentes monotonicamente ", de acordo com a documentação .
Franklin Yu

8
Mais contexto: "Chamadas repetidas para esta função não garantem resultados crescentes monotonicamente. A hora do sistema pode diminuir devido à sincronização com referências de hora externas ou devido a uma alteração explícita do usuário no relógio ."
Klaas

O desenvolvedor deve levar em consideração a "sincronização com referências de horário externas" e "uma alteração explícita do usuário no relógio". Você quis dizer que é impossível que as duas situações aconteçam?
Franklin Yu

@FranklinYu não, eu só queria afirmar essas são as duas possíveis razões. Se você confiar sempre em obter valores cada vez maiores de monotonia, há outras opções.
Klaas

Às vezes, desejo medir um curto período de tempo; se a sincronização ocorrer durante isso, eu posso acabar com um tempo negativo. Na verdade, mach_absolute_timenão existe esse problema, por isso estou me perguntando por que esse não é amplamente conhecido. Talvez apenas porque não está bem documentado.
Franklin Yu

54

Use clock, ProcessInfo.systemUptimeou DispatchTimepara simples tempo de arranque.


Até onde eu sei, existem pelo menos dez maneiras de medir o tempo decorrido:

Relógio monotônico baseado:

  1. ProcessInfo.systemUptime.
  2. mach_absolute_timecom mach_timebase_infocomo mencionado nesta resposta .
  3. clock()no padrão POSIX .
  4. times()no padrão POSIX . (Muito complicado, pois precisamos considerar o tempo do usuário versus o tempo do sistema, e os processos filhos estão envolvidos.)
  5. DispatchTime (um invólucro em torno da API do horário do Mach), conforme mencionado por JeremyP na resposta aceita.
  6. CACurrentMediaTime().

Relógio de parede baseado:

(nunca use esses para métricas: veja abaixo o porquê)

  1. NSDate/ Datecomo mencionado por outros.
  2. CFAbsoluteTime como mencionado por outros.
  3. DispatchWallTime.
  4. gettimeofday()no padrão POSIX .

As opções 1, 2 e 3 são elaboradas abaixo.

Opção 1: API de informações do processo no Foundation

do {
    let info = ProcessInfo.processInfo
    let begin = info.systemUptime
    // do something
    let diff = (info.systemUptime - begin)
}

onde diff:NSTimeIntervalé o tempo decorrido em segundos.

Opção 2: API Mach C

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

onde diff:Doubleé o tempo decorrido em nanossegundos.

Opção 3: API do relógio POSIX

do {
    let begin = clock()
    // do something
    let diff = Double(clock() - begin) / Double(CLOCKS_PER_SEC)
}

onde diff:Doubleé o tempo decorrido em segundos.

Por que não o tempo do relógio de parede pelo tempo decorrido?

Na documentação de CFAbsoluteTimeGetCurrent:

Chamadas repetidas para esta função não garantem resultados crescentes monotonicamente.

O motivo é semelhante ao currentTimeMillisvs nanoTimeem Java :

Você não pode usar esse para o outro propósito. A razão é que o relógio do computador não é perfeito; sempre deriva e, ocasionalmente, precisa ser corrigido. Essa correção pode ocorrer manualmente ou, no caso da maioria das máquinas, existe um processo que executa e emite continuamente pequenas correções no relógio do sistema ("relógio de parede"). Estes tendem a acontecer frequentemente. Outra correção desse tipo ocorre sempre que há um salto de segundo.

Aqui CFAbsoluteTimefornece a hora do relógio de parede em vez da hora de inicialização. NSDateé a hora do relógio de parede também.


a melhor resposta - mas qual é a melhor abordagem a seguir ?!
Fattie

1
A opção 5 é mais adequada para mim. Se você está pensando em código multiplataforma, tente este. As bibliotecas Darwin e Glibc têm clock()função.
Misha Svyatoshenko

Para as soluções baseadas Relógio do sistema: Eu tive sucesso com ProcessInfo.processInfo.systemUptime, mach_absolute_time(), DispatchTime.now()e CACurrentMediaTime(). Mas a solução com clock()não estava convertendo para segundos corretamente. Portanto, recomendo que você atualize sua primeira frase para: " Use ProcessInfo.systemUptime ou DispatchTime para um tempo preciso de inicialização. "
Cœur

36

Swift 4 resposta mais curta:

let startingPoint = Date()
//  ... intensive task
print("\(startingPoint.timeIntervalSinceNow * -1) seconds elapsed")

Ele imprimirá algo como 1,02107906341553 segundos decorridos (o tempo do curso variará dependendo da tarefa, estou apenas mostrando isso para vocês verem o nível de precisão decimal para essa medição).

Espero que ajude alguém no Swift 4 a partir de agora!

Atualizar

Se você quiser ter uma maneira genérica de testar partes do código, sugiro o próximo snippet:

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

Alguém pode explicar por que * -1?
Maksim Kniazev 11/06/19

1
@MaksimKniazev Por ser um valor negativo, as pessoas querem um valor positivo!
Thachnb

@thachnb Eu não tinha idéia "startingPoint.timeIntervalSinceNow" produz valor negativo ...
Maksim Kniazev

1
@MaksimKniazev A Apple diz que: se o objeto de data for anterior à data e hora atuais, o valor desta propriedade será negativo.
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) // <- valor positivo
eonist 9/09/16

praticamente a solução para a frente mais que eu vi, obrigado
MiladiuM

10

Basta copiar e colar esta função. Escrito em rápido 5. Copiando JeremyP aqui.

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

Use-o como

calculateTime {
     exampleFunc()// function whose execution time to be calculated
}

6

Você pode criar uma timefunção para medir suas chamadas. Eu sou inspirado pela resposta de 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.")
}

Essa função permitiria que você a chamasse assim time (isPrime(7)), retornando uma tupla contendo o resultado e uma descrição de string do tempo decorrido.

Se você deseja apenas o tempo decorrido, pode fazer isso time (isPrime(7)).duration


3
"Chamadas repetidas para esta função não garantem resultados crescentes monotonicamente." de acordo com a documentação .
Franklin Yu

3

Função auxiliar simples para medir o tempo de execução com fechamento.

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

Uso:

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

Resultado: #Init - execution took 1.00104497105349 seconds


2

você pode medir os nanossegundos como por exemplo:

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

Eu apenas executei isso sem nenhum código colocado no "// seu procedimento longo" e deu um resultado de 240900993, que é 0,24 segundos.
user1021430

instanciar um NSCalendarprocedimento é caro, mas você pode fazê-lo antes de começar a executá-lo, para que não seja adicionado ao tempo de execução do seu procedimento longo ... lembre-se de que a criação de uma NSDateinstância e o –components(_:, fromDate:)método de chamada ainda levam tempo, portanto, provavelmente você nunca terá 0.0nanossegundos.
holex

Pela aparência do construtor NSCalendar, parece que talvez não seja possível criá-lo antes do tempo (startDate é uma entrada necessária). É meio surpreendente que pareça ser um porco.
user1021430

você pode fazer isso (minha resposta atualizada), o tempo medido sem nenhum procedimento adicional é de 6.9microssegundos no meu dispositivo.
holex

Legal, obrigado. O procedimento básico agora é semelhante à resposta de JeremyP, mas os relatórios são diferentes.
user1021430

2

Eu uso isso:

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_;
    }
}

Não sei se é mais ou menos preciso do que publicado anteriormente. Mas os segundos têm muitas casas decimais e parecem capturar pequenas alterações de código em algoritmos como o QuickSort usando swap () vs. implementando o próprio swap etc.

Lembre-se de aumentar suas otimizações de construção ao testar o desempenho:

Otimizações rápidas do compilador


2

Aqui está a minha tentativa de resposta mais simples:

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

Notas

  • startTimee endTimesão do tipo TimeInterval, que é apenas um typealiaspara Double, por isso é fácil convertê-lo para um Intou o que for. O tempo é medido em segundos com precisão abaixo de milissegundos.
  • Consulte também DateInterval, que inclui um horário real de início e término.
  • O uso do tempo desde 1970 é semelhante aos registros de data e hora do Java .

maneira mais fácil, gostaria que em duas seqüências, segundo é deixado decorridoTime = Date (). timeIntervalSince1970
startTime

1

Eu emprestei a ideia do Klaas para criar uma estrutura leve para medir o tempo de execução e o intervalo:

Uso do código:

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

A função de parada não precisa ser chamada, pois a função de impressão fornecerá o tempo decorrido. Pode ser chamado repetidamente para que o tempo termine. Mas, para parar o cronômetro em um determinado momento do uso do código, timer.stop()ele também pode ser usado para retornar o tempo em segundos: let seconds = timer.stop() Depois que o cronômetro é parado, o cronômetro de intervalo não será, portanto print("Running: \(timer) "), o tempo correto será dado, mesmo depois de algumas linhas de código.

A seguir está o código para o RunningTimer. Foi testado para o 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

Embrulhe em um bloco de conclusão para facilitar o uso.

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

Este é o trecho que eu criei e parece funcionar para mim no meu Macbook com Swift 4.

Nunca testei em outros sistemas, mas achei que vale a pena compartilhar de qualquer maneira.

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())
}

Aqui está um exemplo de como usá-lo:

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

Outra maneira é fazê-lo de forma mais explícita:

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

Foi assim que eu escrevi.

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

Para medir um algoritmo, use -o assim.

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

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

Quão preciso é esse tempo? Porque eu usei o timer antes para atualizar a cada 0,1 segundos. Comparei esta resposta e um com temporizador e resultado dessa resposta é 0,1 segundos mais depois com temporizador ..
Maksim Kniazev

0

Classe Swift3 estática para sincronização básica das funções. Ele acompanhará cada timer por nome. Chame assim no ponto em que deseja começar a medir:

Stopwatch.start(name: "PhotoCapture")

Ligue para capturar e imprimir o tempo decorrido:

Stopwatch.timeElapsed(name: "PhotoCapture")

Esta é a saída: *** PhotoCapture decorrido ms: 1402.415125 Existe um parâmetro "useNanos" se você deseja usar nanos. Por favor, sinta-se livre para mudar conforme necessário.

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

}


Todo o seu trabalho mach_timebase_infojá foi implementado melhor do que você fez no código fonte de ProcessInfo.processInfo.systemUptime. Então simplesmente faça watches[name] = ProcessInfo.processInfo.systemUptime. E * TimeInterval(NSEC_PER_MSEC)se você quiser nanos.
Cœur

0

Baseado na resposta de Franklin Yu e nos comentários de Coeur

Detalhes

  • Xcode 10.1 (10B61)
  • Swift 4.2

Solução 1

a medida(_:)

Solução 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)
    }
}

Uso da solução 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)")

Não sei por que precisaríamos usar implementações variáveis. Usar Datepara medir qualquer coisa é extremamente desencorajado (mas systemUptimeou clock()está OK). Quanto aos testes, nós measure(_:)já temos .
Cœur

1
Outra observação: por que tornar o fechamento opcional?
Cœur

@ Você está certo! Obrigado por seus comentários. Vou atualizar a postagem mais tarde.
Vasily Bodnarchuk
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.