¿Cómo podemos medir el tiempo transcurrido para ejecutar una función en Swift? Estoy tratando de mostrar el tiempo transcurrido de esta manera: "El tiempo transcurrido es 0,05 segundos". Vimos que en Java , podemos usar System.nanoTime (), ¿hay métodos equivalentes disponibles en Swift para lograr esto?
Por favor, eche un vistazo al programa de muestra:
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
fuente
fuente
sqrt(number)
lugar denumber
, y puede ahorrar un poco más de tiempo, pero hay muchas más ideas que optimizan la búsqueda de números primos.NSDate
objetos y puedes medir la diferencia entre ellos.Respuestas:
Aquí hay una función Swift que escribí para medir los problemas del Proyecto Euler en Swift
A partir de Swift 3, ahora hay una versión de Grand Central Dispatch que está "acelerada". Entonces, la respuesta correcta es probablemente usar la API DispatchTime .
Mi función se vería así:
Vieja respuesta
Para Swift 1 y 2, mi función usa NSDate:
Tenga en cuenta que se desaconseja el uso de NSdate para las funciones de temporización: " La hora del sistema puede disminuir debido a la sincronización con referencias de hora externas o debido a un cambio explícito del reloj del usuario ".
fuente
Date
lado, y efectivamente eso reporta 41.87 segundos. No sé quéuptimeNanoseconds
está haciendo, pero no informa la duración correcta.Esta es una práctica clase de temporizador basada en
CoreFoundation
sCFAbsoluteTime
:Puedes usarlo así:
fuente
mach_absolute_time
que no sufre este problema, por lo que me pregunto por qué ese no es ampliamente conocido. Quizás solo porque no está bien documentado.Use
clock
,ProcessInfo.systemUptime
oDispatchTime
para un tiempo de inicio simple.Hasta donde yo sé, hay al menos diez formas de medir el tiempo transcurrido:
Reloj monotónico basado:
ProcessInfo.systemUptime
.mach_absolute_time
conmach_timebase_info
lo mencionado en esta respuesta .clock()
en POSIX estándar .times()
en POSIX estándar . (Demasiado complicado ya que necesitamos considerar el tiempo de usuario frente al tiempo del sistema, y los procesos secundarios están involucrados).DispatchTime
(un contenedor alrededor de Mach time API) como lo menciona JeremyP en la respuesta aceptadaCACurrentMediaTime()
.Reloj de pared basado:
(nunca los use para métricas: vea a continuación por qué)
NSDate
/Date
como lo mencionaron otros.CFAbsoluteTime
según lo mencionado por otros.DispatchWallTime
.gettimeofday()
en POSIX estándar .Las opciones 1, 2 y 3 se detallan a continuación.
Opción 1: API de información de proceso en Foundation
donde
diff:NSTimeInterval
es el tiempo transcurrido por segundos.Opción 2: API Mach C
donde
diff:Double
es el tiempo transcurrido en nano-segundos.Opción 3: API de reloj POSIX
donde
diff:Double
es el tiempo transcurrido por segundos.¿Por qué no la hora del reloj de pared para el tiempo transcurrido?
En la documentación de
CFAbsoluteTimeGetCurrent
:La razón es similar a
currentTimeMillis
vsnanoTime
en Java :Aquí
CFAbsoluteTime
proporciona la hora del reloj de pared en lugar de la hora de inicio.NSDate
es la hora del reloj de pared también.fuente
clock()
función.ProcessInfo.processInfo.systemUptime
,mach_absolute_time()
,DispatchTime.now()
yCACurrentMediaTime()
. Pero la solución conclock()
no estaba convirtiendo a segundos correctamente. Así que yo le aconsejaría para actualizar su primera frase de: " Uso ProcessInfo.systemUptime o DispatchTime por el tiempo de puesta en marcha precisa. "La respuesta más rápida de Swift 4:
Le imprimirá algo así como 1.02107906341553 segundos transcurridos (el tiempo, por supuesto, variará dependiendo de la tarea, solo les estoy mostrando esto para que vean el nivel de precisión decimal para esta medición).
¡Espero que ayude a alguien en Swift 4 de ahora en adelante!
Actualizar
Si desea tener una forma genérica de probar porciones de código, le sugiero el siguiente fragmento:
fuente
fuente
Simplemente copie y pegue esta función. Escrito en Swift 5. Copiando JeremyP aquí.
Úselo como
fuente
Puede crear una
time
función para medir sus llamadas. Me inspira la respuesta de Klaas .Esta función le permitiría llamarlo así,
time (isPrime(7))
lo que devolvería una tupla que contiene el resultado y una descripción de cadena del tiempo transcurrido.Si solo desea el tiempo transcurrido, puede hacerlo
time (isPrime(7)).duration
fuente
Función auxiliar simple para medir el tiempo de ejecución con cierre.
Uso:
Resultado:
#Init - execution took 1.00104497105349 seconds
fuente
puede medir los nanosegundos de la siguiente manera:
fuente
NSCalendar
procedimiento costoso, pero puede hacerlo antes de comenzar a ejecutar su procedimiento, por lo que no se agregará al tiempo de ejecución de su procedimiento largo ... tenga en cuenta que la creación de unaNSDate
instancia y el–components(_:, fromDate:)
método de llamada aún requieren tiempo, por lo que probablemente nunca obtendrás0.0
nanosegundos.6.9
microsegundos en mi dispositivo.Yo uso esto:
No sé si es más o menos preciso que el publicado anteriormente. Pero los segundos tienen muchos decimales y parecen captar pequeños cambios de código en algoritmos como QuickSort usando swap () versus implementar swap urself, etc.
Recuerde aumentar sus optimizaciones de compilación cuando pruebe el rendimiento:
fuente
Aquí está mi intento por la respuesta más simple:
Notas
startTime
yendTime
son del tipoTimeInterval
, que es solotypealias
paraDouble
, por lo que es fácil convertirlo a unoInt
o lo que sea. El tiempo se mide en segundos con una precisión inferior a milisegundos.DateInterval
, que incluye una hora de inicio y finalización real.fuente
He tomado prestada la idea de Klaas para crear una estructura ligera para medir el tiempo de ejecución y el intervalo:
Uso del código:
No es necesario llamar a la función de parada, ya que la función de impresión dará el tiempo transcurrido. Se puede llamar repetidamente para que transcurra el tiempo. Pero para detener el temporizador en cierto punto del uso del código
timer.stop()
, también puede usarse para devolver el tiempo en segundos:let seconds = timer.stop()
después de que se detiene el temporizador, el temporizador de intervalo no loprint("Running: \(timer) ")
hará , por lo que dará la hora correcta incluso después de unas pocas líneas de código.El siguiente es el código para RunningTimer. Está probado para Swift 2.1:
fuente
Envuélvala en un bloque de terminación para facilitar su uso.
fuente
Este es el fragmento que se me ocurrió y parece funcionar para mí en mi Macbook con Swift 4.
Nunca probé en otros sistemas, pero pensé que vale la pena compartir de todos modos.
Aquí hay un ejemplo de cómo usarlo:
Otra forma es hacerlo más explícitamente:
fuente
Así es como lo escribí.
Para medir un algoritmo utilízalo así.
fuente
Clase Swift3 estática para temporización de funciones básicas. Realizará un seguimiento de cada temporizador por nombre. Llámelo así en el punto en que desea comenzar a medir:
Llame a esto para capturar e imprimir el tiempo transcurrido:
Este es el resultado: *** PhotoCapture transcurrió ms: 1402.415125 Hay un parámetro "useNanos" si desea usar nanos. Por favor, siéntase libre de cambiar según sea necesario.
}
fuente
mach_timebase_info
ya está implementado mejor de lo que lo hizo en el código fuente deProcessInfo.processInfo.systemUptime
. Así que simplemente hazlowatches[name] = ProcessInfo.processInfo.systemUptime
. Y* TimeInterval(NSEC_PER_MSEC)
si quieres nanos.Basado en la respuesta de Franklin Yu y los comentarios de Coeur
Detalles
Solución 1
medida(_:)
Solución 2
Uso de la solución 2
fuente
Date
para medir cualquier cosa es extremadamente desaconsejado (perosystemUptime
oclock()
está bien). En cuanto a las pruebas, ya lo hemosmeasure(_:)
hecho.