Cesar Vega
Feb 17 · 6 min read

Este artículo es una traducción de un artículo publicado originalmente en inglés por Matt Sullivan en Medium. Por favor, visita el siguiente enlace y recomienda el artículo original si te gusta el contenido:


Flutter utiliza Dart como lenguaje de desarrollo y como runtime. El runtime de Dart está siempre presente, tanto en los modos debug como en release, pero hay grandes diferencias entre los dos sabores de build.

En el modo debug, la mayor parte de la plomería de Dart se envía al dispositivo: el runtime de Dart, el compilador/intérprete just in time (JIT para Android e intérprete para iOS), los servicios de debugging y profiling. En el modo release, los servicios de JIT/intérprete y de debugging se eliminan, pero el runtime permanece, y este es uno de los principales factores que contribuyen al tamaño base de una aplicación Flutter.

Componentes Dart en los modos debug y release de Flutter

El runtime de Dart incluye un garbage collector, un componente necesario para asignar y anular la asignación de memoria a medida que los objetos se instancian y se vuelven inalcanzables.

Y con Flutter, puede haber muchos objetos. Los Widgets sin estado se crean a medida que se renderizan en pantalla, se destruyen y se reconstruyen cuando cambia el estado de la aplicación o cuando ya no son visibles, la mayoría con una vida útil corta. Para una aplicación con una interfaz de usuario razonablemente compleja, esta puede ejecutar miles de widgets.

Entonces, ¿deberían los desarrolladores de Flutter temer al garbage collector? Con Flutter creando y destruyendo objetos con gran frecuencia, ¿deberían los desarrolladores tomar medidas para limitar este comportamiento? No es raro ver a los nuevos desarrolladores de Flutter crear referencias a widgets que saben que no cambiarán con el tiempo, y ponerlos en estado para que no sean destruidos y reconstruidos.

No hagas esto

El temor al garbage collector de Dart es en gran medida infundado, debido a su arquitectura generacional y a una implementación optimizada para la rápida creación y destrucción de objetos. En la mayoría de los escenarios, deberías dejar que el motor de Flutter cree y destruya todos los widgets que desee.

El Garbage Collector de Dart

El recolector de basura de Dart es generacional y consta de dos fases: el joven limpiador de espacio y los recolectores de marcado paralelo y barrido concurrentes.

Programación

Para minimizar los efectos de la recolección de basura en el rendimiento de la aplicación y de la interfaz de usuario, el garbage collector proporciona ganchos al motor Flutter que lo alertan cuando el motor detecta que la aplicación está en reposo y que no hay interacción con el usuario. Esto le da al recolector de basura la oportunidad de ejecutar sus fases de recolección sin afectar el rendimiento.

El recolector de basura también puede realizar una compactación deslizante durante esos intervalos de inactividad, lo que minimiza la sobrecarga de memoria al reducir la fragmentación de la misma.

El joven limpiador de espacio

Esta fase está diseñada para limpiar objetos efímeros que tienen una vida corta, como los widgets sin estado. Mientras esté bloqueando, es mucho más rápido que la marca/barrido de segunda generación, y cuando se combina con la programación, prácticamente elimina las pausas percibidas en la aplicación cuando se ejecuta.

En esencia, los objetos se asignan a un espacio contiguo en la memoria y, a medida que se crean, se les asigna el siguiente espacio disponible, hasta que se llena la memoria asignada. Dart utiliza la asignación del bump pointer para asignar rápidamente en un nuevo espacio, lo que hace que el proceso sea muy rápido.

El nuevo espacio (o cuarto), en donde se asignan nuevos objetos, consta de dos mitades, conocidas como semi-espacios. Sólo se utiliza una mitad en cada momento: una activa y la otra inactiva. Los nuevos objetos se asignan en la mitad activa y, una vez completados, los objetos activos se trasladan de activos a inactivos, ignorando los objetos ya inactivos. La mitad inactiva se activa y el proceso se repite.

Para determinar cuáles objetos están activos o inactivos, el recolector comienza con los objetos raíz, como las variables de stack, y examina a qué hacen referencia. A continuación, desplaza los objetos de referencia. Desde allí examina a qué apuntan estos objetos evacuados y mueve estos objetos referenciados. Esto continúa hasta que se muevan todos los objetos activos. Los objetos inactivos no tienen referencias y, por lo tanto, se dejan atrás; los objetos activos se copiarán sobre ellos en un evento futuro de recolección de basura.

Para más información sobre esto, consulte el algoritmo de Cheney.

Joven Limpiador de Espacio recolector de basura

Marcado Paralelo y Barrido Concurrente

Cuando los objetos alcanzan una cierta vida útil, son trasladados a un nuevo espacio de memoria, gestionado por la segunda generación de colectores: mark-sweep.

Esta técnica de recolección de basura tiene dos fases: el objeto graph se recorre primero y se marcan los objetos que todavía están en uso. Durante la segunda fase se escanea toda la memoria y se reciclan los objetos no marcados. A continuación, se borran todas las banderas.

Esta forma de recolección de basura se bloquea en la fase de marcado; no se puede producir ninguna mutación en la memoria y se bloquea el thread de la interfaz de usuario. Esta colección es más infrecuente ya que los objetos de vida corta son manipulados por el joven limpiador, pero habrá momentos en que el runtime de Dart necesite pausarse para ejecutar esta forma de recolección de basura. Dada la capacidad de Flutter para programar la recolección, el impacto de esto debe ser minimizado.

Debe tenerse en cuenta que si una aplicación no se adhiere a la hipótesis generacional débil (que afirma que la mayoría de los objetos mueren jóvenes), entonces esta forma de colección ocurrirá con más frecuencia. Dada la forma en que funciona la implementación de widgets de Flutter, esto es poco probable, pero hay que tenerlo en cuenta.

Isolates

Cabe señalar que los isolates de Dart tienen su propio heap privado, independiente el uno del otro. Dado que cada isolate se ejecuta en un hilo separado, los eventos de recolección de basura para cada isolate no deben afectar el desempeño de otros. El uso de isolates es una gran forma de evitar el bloqueo de la interfaz de usuario y el proceso de descarga intensivo de actividades.

Terminando

Y ahí lo tienen: Dart emplea un potente recolector de basura generacional para minimizar los efectos del bloqueo en la recolección de basura, en las aplicaciones Flutter. No temas al recolector de basura; tiene los mejores intereses de tu aplicación en el corazón.

Les dejo mi cuenta de Twitter y los invito a ser parte de:

Comunidad Flutter de habla hispana.
https://www.facebook.com/groups/flutter.dart.spanish

Telegram (link: https://t.me/flutter_dart_spanish)

Slack: (link: http://bit.ly/FlutterDevsEnEspañol)

Comunidad Flutter

Artículos e Historias de la Comunidad de Flutter

    Cesar Vega

    Written by

    Systems Engineer, postgrade in Software Development, postgrade in Information Security

    Comunidad Flutter

    Artículos e Historias de la Comunidad de Flutter

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade