¿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.NSDateobjetos 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
Datelado, y efectivamente eso reporta 41.87 segundos. No sé quéuptimeNanosecondsestá haciendo, pero no informa la duración correcta.Esta es una práctica clase de temporizador basada en
CoreFoundationsCFAbsoluteTime:Puedes usarlo así:
fuente
mach_absolute_timeque 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.systemUptimeoDispatchTimepara 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_timeconmach_timebase_infolo 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/Datecomo lo mencionaron otros.CFAbsoluteTimesegú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:NSTimeIntervales el tiempo transcurrido por segundos.Opción 2: API Mach C
donde
diff:Doublees el tiempo transcurrido en nano-segundos.Opción 3: API de reloj POSIX
donde
diff:Doublees 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
currentTimeMillisvsnanoTimeen Java :Aquí
CFAbsoluteTimeproporciona la hora del reloj de pared en lugar de la hora de inicio.NSDatees 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
timefunció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)).durationfuente
Función auxiliar simple para medir el tiempo de ejecución con cierre.
Uso:
Resultado:
#Init - execution took 1.00104497105349 secondsfuente
puede medir los nanosegundos de la siguiente manera:
fuente
NSCalendarprocedimiento 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 unaNSDateinstancia y el–components(_:, fromDate:)método de llamada aún requieren tiempo, por lo que probablemente nunca obtendrás0.0nanosegundos.6.9microsegundos 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
startTimeyendTimeson del tipoTimeInterval, que es solotypealiasparaDouble, por lo que es fácil convertirlo a unoInto 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_infoya 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
Datepara medir cualquier cosa es extremadamente desaconsejado (perosystemUptimeoclock()está bien). En cuanto a las pruebas, ya lo hemosmeasure(_:)hecho.