Unreal Engine (UE) utiliza un recolector de basura de marcado y barrido para gestionar la memoria de los UObject. En el caso de las aplicaciones de tiempo real variable, los recolectores de basura han tenido históricamente un gran inconveniente: la posibilidad de generar fallos en el juego mientras el recolector de basura determina qué objetos pueden recuperar memoria. En UE, este proceso se denomina análisis de accesibilidad. UE depende de que esta fase de recolección de basura se complete en un solo fotograma, lo que detiene temporalmente todo el procesamiento de UObject (en particular, el juego). Cuantos más objetos tenga que escanear el análisis de accesibilidad, más larga será la pausa, lo que puede provocar problemas visibles en el juego. Los programadores pueden evitar dichos problemas de varias maneras, como por ejemplo mediante:
El ajuste de presupuestos de UObject.
El uso de agrupaciones de UObjects.
La desactivación del recolector de basura durante el juego normal.
No obstante, estas soluciones tienden a aumentar la complejidad del código y los costes generales del proyecto.
Análisis de accesibilidad incremental
UE lo ha mejorado mediante el análisis de accesibilidad incremental. Los usuarios ahora tienen la posibilidad de dividir la fase de análisis de accesibilidad del recolector de basura en varios fotogramas con un límite de tiempo flexible configurable por fotograma. El motor realiza un seguimiento de las referencias de UObject entre iteraciones de accesibilidad a través de las propiedades TObjectPtr, lo que significa que cualquier asignación a un UPROPERTY expuesto por TObjectPtr marca inmediatamente el objeto como accesible mientras se está llevando a cabo la recolección de basura. Esto también se conoce como barrera de escritura del recolector de basura.
El motor ya se ha convertido para usar TObjectPtr en lugar de punteros de C++ sin procesar en cualquier lugar que exponga UObjects al recolector de basura, incluidas las funciones AddReferencedObjects de UObject o FGCObject. Para emplear el análisis de accesibilidad incremental en proyectos creados con Unreal Engine, es fundamental convertir todas las instancias de UPROPERTY para que usen TObjectPtr en lugar de C++ sin procesar, ya que, de lo contrario, la recolección de basura podría recuperar parte de la memoria de UObjects demasiado pronto. En principio, vamos a publicar esta función de forma experimental, ya que es posible que la fase de análisis de la accesibilidad supere el límite de tiempo especificado.
Cómo habilitar el análisis de accesibilidad incremental
El análisis de accesibilidad incremental se puede activar con las siguientes variables de consola cuando se añaden al archivo DefaultEngine.ini de tu proyecto:
[ConsoleVariables]
gc.AllowIncrementalReachability=1 ; enables Incremental Reachability Analysis
gc.AllowIncrementalGather=1 ; enables Incremental Gather Unreachable Objects
gc.IncrementalReachabilityTimeLimit=0.002 ; sets the soft time limit to 2msVariables de consola adicionales
También puede usar variables de consola para las pruebas de esfuerzo y depuración:
| Variable de consola | Descripción | Clase |
|---|---|---|
| Retrasa el análisis de accesibilidad por el número especificado de fotogramas. Se usa para realizar pruebas de esfuerzo a la barrera del recolector de basura. |
|
| Realiza una prueba una vez completado el análisis de accesibilidad para asegurarte de que ningún objeto accesible (válido) haga referencia a un objeto inaccesible (que pronto será destruido). | 0: desactivado; 1: activado |
| Sigue reiniciando la recolección de basura incremental después de que la anterior haya finalizado. | 0: desactivado; 1: activado |
Comparación de rendimiento
A continuación se muestra una comparación de Unreal Insights del grafo de rendimiento de un proyecto de muestra con la accesibilidad incremental desactivada. La línea azul representa el tiempo total del fotograma y la naranja el tiempo que tarda el análisis de accesibilidad. Unreal Insights traza una línea gráfica continua entre eventos individuales separados por varios fotogramas; aunque pueda parecer que la recolección de basura se está ejecutando a lo largo de todo el cronograma, en realidad solo se ejecuta para un fotograma a la vez.
En la primera imagen de la siguiente comparación gráfica, se puede observar un pico cada vez que se ejecuta la recolección de basura (que aparece indicado mediante las etiquetas del recolector de basura en la parte superior del cronograma).
En la segunda imagen, con la accesibilidad incremental activada, se puede observar que los picos de retraso del recolector de basura han desaparecido y que la accesibilidad incremental ahora se divide en varios fotogramas (representados por las barras de color verde claro que ahora son más anchas).
Limitaciones conocidas
La accesibilidad incremental no es totalmente segura para los subprocesos. En algunas circunstancias, un objeto que se está manipulando en un subproceso de trabajo no se marcará como accesible mientras el recolector de basura está escaneando el grafo UObject, lo que puede provocar que el objeto se recoja como basura antes de tiempo. Por ello, recomendamos habilitar la accesibilidad incremental únicamente en compilaciones de un solo subproceso (por ejemplo, servidores dedicados).