Calcular tiempo de ejecución de un código
Libranner Santos
26 febrero, 20233min de lectura
En un artículo anterior vimos como podemos usar async let
para ejecutar procesos en paralelo. ¿Cómo podemos medir que en realidad está tomando menos tiempo la ejecución con este cambio?
La respuesta es usando Clock
. Más específicamente, ContinuousClock
un tipo de Clock
introducido en Swift 5.7, que nos permite medir el tiempo de ejecución de manera continua tomando en cuenta cuando la aplicación esta en estado de suspensión.
¿Cómo usar ContinuousClock para medir tiempo de ejecución?
El siguiente código muestra como podemos medir el tiempo de ejecución de una función:
// 1let clock = ContinuousClock()// 2let result = clock.measure {// Llamar la función aquí}// 3print(result)
Esto es lo que hace este código:
- Creamos una instancia de
ContinuousClock
y la guardamos en la variableclock
. - Usamos
measure(_:)
y asignamos el resultado de la llamada en la variableresult
. - Por último imprimimos el contenido de
result
. Aquí se imprimiría el tiempo total que toma en ejecutar el código.
Un ejemplo con código
Usemos el siguiente código para medir el tiempo de ejecución:
func getInt() async -> Int {try? await Task.sleep(for: .seconds(1))return 1}func getString() async -> String {try? await Task.sleep(for: .seconds(2))return "Texto"}func getData() async {async let numberOperation = getInt()async let textOperation = getString()let (number, text) = await (numberOperation, textOperation)print("\(number) \(text)")}
Aquí tenemos una getData()
que ejecuta getInt()
y getString()
usando async let
.
Note que cada una de estas funciones tiene un Task.sleep(for:)
que provoca una pausa en tiempo de ejecución, en el caso de getInt()
de un segundo y getString()
de dos segundos. Sin embargo, como estamos usando async let
la ejecución de getData()
debería tomar alrededor de dos segundos no tres.
Pongamos esto a prueba. Usando ContinuousClock
:
func measureExecution() {Task {let clock = ContinuousClock()let result = await clock.measure {await getData()}}print("Tiempo ejecución \(result.components.seconds) segundos")}
Hay varias cosas diferentes en este código con respecto a como explicamos en el principio que debía utilizarse:
- Lo estamos envolviendo todo dentro un
Task
y cuando llamamosclock.measure
lo precedimos conawait
. Estos cambios se deben a que estamos tratando de medir el tiempo de ejecución de una función asíncrona. - No estamos imprimiendo
result
, sinoresult.components.seconds
, porque solo nos interesan los segundos que toma la ejecución.
El resultado
Si ejecutamos measureExecution()
podremos ver los siguientes datos en consola:
Siendo la primera línea el resultado de print("\(number) \(text)")
y la segunda la cantidad de segundos que toma ejecutar la función, emitido por print(result.components.seconds)
.
Así probamos nuestra hipótesis de que el tiempo total de ejecución es dos segundos en ves de tres gracias a async let
.
Cosas a tomar en cuenta
- La manera como el sistema operativo asigna los recursos no es controlada totalmente por nosotros. Por lo que en una aplicación real no podríamos garantizar cuanto tiempo tomará ejecutar algo. Para tratar de influir un poco en la prioridad que el sistema da a la ejecución de nuestro código podemos usar otras herramientas, como por ejemplo, utilizando la propiedad
priority
de los objetosTask
. - Recuerda usar
await
cuando quieras medir el tiempo de ejecución de funciones asíncronas. Clock
y sus derivados están disponibles solo a partir de iOS 16.