DEV Community

GoyesDev
GoyesDev

Posted on

[SC] Reduciendo puntos de suspensión

Comprensión durante la lectura

¿Qué es un "punto de suspensión" y por qué no siempre ocurre cuando usamos await?

Un "punto de suspensión" es un lugar donde ocurre un cambio de dominio de aislamiento. Al usar await, aparece un POSIBLE punto de suspensión, lo que significa que puede o no haber el cambio. Si el dominio de aislamiento de destino coincide con el de origen, entonces no hay suspensión.

¿Por qué es problemático tener mucho código entre dos puntos de suspensión?

Podríamos tener potenciales:

  • "actor reentrancy"
  • estado inconsciente
  • saltos entre hilos
  • deterioro en el desempeño de la app

¿Cuáles son las principales técnicas para controlar o reducir los puntos de suspensión en Swift Concurrency?

El principio detrás de todas las técnicas es:

  1. Hacer tanto trabajo síncrono como se pueda, antes de la suspensión
  2. Saltar al otro dominio, solo una vez.
  3. Terminar la tarea.
  4. Solo volver a saltar si es estrictamente necesario

Las técnicas son:

  1. Usar métodos síncronos mientras sea posible: Si tenemos dos métodos f1() async y f2() async, donde f2() es privado e invocado desde f1(). En este caso, si f2() puede ser síncrono, es mejor quitar el async.
  2. Tratar de evitar el "actor-reentrancy": Saliendo del actor cuando ya se hizo todo el trabajo que involucraba su estado.
  3. Usar nonisolated(nonsending) y @concurrent: Los métodos nonisolated(nonsending) herendan el dominio de aislamiento del invocador así que no hay punto de suspensión. @concurrent fuerza la ejecución en otro dominio de aislamiento.
  4. Heredar el actor con #isolation: Si se hereda el dominio de aislamiento, no hay punto de suspensión.
  5. Preferir APIs que no suspenden: por ejemplo, usar Task.isCancelled en lugar de try await Task.checkCancellation().
  6. Usar APIs paralelas para reducir el tiempo de ejecución.

¿Qué ventajas concretas ofrece usar métodos sincrónicos en lugar de marcar todo con async?

Si ya se está en un dominio de aislamiento diferente de MainActor y se puede vivir con bloquear el hilo (ejecución asíncrona), entonces es mejor no poner otro punto de suspensión.

De esta forma:

  • No hay actor reentrancy.
  • No hay saltos inesperados entre executors.
  • El estado del actor es consistente durante el método.
  • No hay puntos de suspensión ocultos.

¿Qué es el actor reentrancy y cómo se puede evitar restructurando el código?

Ante un punto de suspensión, puede haber un cambio de dominio de aislamiento. Aquí, en lugar de bloquear el hilo, el actor tiene permitido tomar alguna otra tarea mientras que la primera está suspendida. Esto se conoce como "interleaving" o solapamiento.

El "actor reentrancy" ocurre cuando, debido al "interleaving" una segunda tarea modifica el estado de una primera tarea, que inicialmente había sido suspendida.

El problema se resume en que el estado del actor podría cambiar entre dos líneas de código si hay un await de por medio.

Se puede evitar haciendo todo el trabajo que modifica el estado, y poniendo el punto de suspensión al final.

¿Cómo funciona nonisolated(nonsending) y en qué situaciones evita un punto de suspensión?

nonisolated(nonsending) sirve para heredar el dominio de aislamiento el método invocador. Sirve para evitar poner un punto de suspensión siempre y cuando no sea inconveniente bloquear el hilo en cuestión.

Si lo es, entonces se debe hacer que el tipo de dato transferido sea Sendable.

¿En qué se diferencian Task.isCancelled y Task.checkCancellation() respecto a la suspensión?

Task.isCancelled no suspende, mientras que Task.checkCancellation() puede hacerlo. Se prefiere el primer método sobre el segundo, siempre que no sea necesario arrojar un error cuando se detecte la cancelación.


Recordar sin releer

¿Puedes explicar con tus propias palabras la metáfora del "border crossing" entre isolation domains?

¿Cuáles son los seis puntos del checklist que el autor propone al escribir un await?


Revisión y síntesis

¿De qué manera el paralelismo con async let o Task Groups complementa la reducción de puntos de suspensión?

¿Cómo se conecta lo aprendido en este artículo con el uso de Xcode Instruments mencionado al final?


Bibliografía

Top comments (0)