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");
}
swift
time
nsdate
elapsedtime
Vaquita
fonte
fonte
sqrt(number)
vez denumber
e você pode economizar um pouco mais de tempo - mas há muito mais idéias para otimizar a busca por números primos.NSDate
objetos e medir a diferença entre eles.Respostas:
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:
Resposta antiga
Para Swift 1 e 2, minha função usa NSDate:
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. ".
fonte
Date
ao lado, e com certeza isso relata 41,87 segundos. Não sei o queuptimeNanoseconds
está fazendo, mas não está relatando a duração correta.Esta é uma classe de timer prática, baseada em
CoreFoundation
sCFAbsoluteTime
:Você pode usá-lo assim:
fonte
mach_absolute_time
não existe esse problema, por isso estou me perguntando por que esse não é amplamente conhecido. Talvez apenas porque não está bem documentado.Use
clock
,ProcessInfo.systemUptime
ouDispatchTime
para simples tempo de arranque.Até onde eu sei, existem pelo menos dez maneiras de medir o tempo decorrido:
Relógio monotônico baseado:
ProcessInfo.systemUptime
.mach_absolute_time
commach_timebase_info
como mencionado nesta resposta .clock()
no padrão POSIX .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.)DispatchTime
(um invólucro em torno da API do horário do Mach), conforme mencionado por JeremyP na resposta aceita.CACurrentMediaTime()
.Relógio de parede baseado:
(nunca use esses para métricas: veja abaixo o porquê)
NSDate
/Date
como mencionado por outros.CFAbsoluteTime
como mencionado por outros.DispatchWallTime
.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
onde
diff:NSTimeInterval
é o tempo decorrido em segundos.Opção 2: API Mach C
onde
diff:Double
é o tempo decorrido em nanossegundos.Opção 3: API do relógio POSIX
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
:O motivo é semelhante ao
currentTimeMillis
vsnanoTime
em Java :Aqui
CFAbsoluteTime
fornece a hora do relógio de parede em vez da hora de inicialização.NSDate
é a hora do relógio de parede também.fonte
clock()
função.ProcessInfo.processInfo.systemUptime
,mach_absolute_time()
,DispatchTime.now()
eCACurrentMediaTime()
. Mas a solução comclock()
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. "Swift 4 resposta mais curta:
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:
fonte
fonte
Basta copiar e colar esta função. Escrito em rápido 5. Copiando JeremyP aqui.
Use-o como
fonte
Você pode criar uma
time
função para medir suas chamadas. Eu sou inspirado pela resposta de Klaas .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
fonte
Função auxiliar simples para medir o tempo de execução com fechamento.
Uso:
Resultado:
#Init - execution took 1.00104497105349 seconds
fonte
você pode medir os nanossegundos como por exemplo:
fonte
NSCalendar
procedimento é 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 umaNSDate
instância e o–components(_:, fromDate:)
método de chamada ainda levam tempo, portanto, provavelmente você nunca terá0.0
nanossegundos.6.9
microssegundos no meu dispositivo.Eu uso isso:
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:
fonte
Aqui está a minha tentativa de resposta mais simples:
Notas
startTime
eendTime
são do tipoTimeInterval
, que é apenas umtypealias
paraDouble
, por isso é fácil convertê-lo para umInt
ou o que for. O tempo é medido em segundos com precisão abaixo de milissegundos.DateInterval
, que inclui um horário real de início e término.fonte
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:
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á, portantoprint("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:
fonte
Embrulhe em um bloco de conclusão para facilitar o uso.
fonte
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.
Aqui está um exemplo de como usá-lo:
Outra maneira é fazê-lo de forma mais explícita:
fonte
Foi assim que eu escrevi.
Para medir um algoritmo, use -o assim.
fonte
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:
Ligue para capturar e imprimir o tempo decorrido:
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.
}
fonte
mach_timebase_info
já foi implementado melhor do que você fez no código fonte deProcessInfo.processInfo.systemUptime
. Então simplesmente façawatches[name] = ProcessInfo.processInfo.systemUptime
. E* TimeInterval(NSEC_PER_MSEC)
se você quiser nanos.Baseado na resposta de Franklin Yu e nos comentários de Coeur
Detalhes
Solução 1
a medida(_:)
Solução 2
Uso da solução 2
fonte
Date
para medir qualquer coisa é extremamente desencorajado (massystemUptime
ouclock()
está OK). Quanto aos testes, nósmeasure(_:)
já temos .