Análisis de la huella de memoria física de su aplicación utilizando Memory Profiler

ANTON KRUGLYAKOV / UNITYSenior Software Engineer
Mar 28, 2023|10 minutos
Análisis de la huella de memoria física de su aplicación utilizando Memory Profiler
Para tu comodidad, tradujimos esta página mediante traducción automática. No podemos garantizar la precisión ni la confiabilidad del contenido traducido. Si tienes alguna duda sobre la precisión del contenido traducido, consulta la versión oficial en inglés de la página web.

Cuando se trata de detectar eficazmente problemas de memoria y optimizar el rendimiento, la información mostrada en el Memory Profiler, así como la precisión de la información, es clave. Estamos invirtiendo grandes esfuerzos en este ámbito. En dos blogs recientes, miembros de mi equipo presentaron Memory Profiler 1.0.0 y compartieron cinco flujos de trabajo clave para diagnosticar y examinar problemas relacionados con la memoria en tu juego.

Pronto lanzaremos Memory Profiler 1.1 ( ya está disponible una versión experimental), que incluye etiquetas y descripciones actualizadas para explicar cómo funciona la memoria y cómo se calcula la huella de memoria de las aplicaciones.

Dado que la huella de memoria sigue siendo un tema candente en nuestras conversaciones con los desarrolladores, estoy aquí para responder a sus preguntas más frecuentes, en concreto, para tratar estos tres temas:

  • Qué es la memoria residente
  • Cómo se calcula la huella de memoria de la aplicación
  • Cómo analizar la huella de memoria
Memoria residente, definida

Vamos a profundizar en la asignación de memoria en Unity. Cuando el motor asigna memoria, primero reserva varias páginas de memoria en el espacio de direcciones virtual en las que quepa la asignación solicitada. Las páginas son las unidades más pequeñas de gestión de memoria. El espacio de direcciones virtual y el almacenamiento físico se organizan en páginas, y el tamaño de página depende de la plataforma utilizada. Por ejemplo, en los ordenadores x86 un tamaño de página es de 4 KB.

Una vez que el motor ha reservado suficientes páginas, pide al sistema operativo (SO) que "comprometa" el almacenamiento físico en la memoria. Por eso, la memoria asignada suele denominarse "comprometida". A continuación, el SO registra que las páginas tienen ahora almacenamiento físico asignado y se puede acceder a ellas. La "memoria comprometida total" indicada por la aplicación aumentará. Sin embargo, la huella de memoria física de su aplicación sigue siendo la misma.

Representación gráfica de las páginas reservadas | Memory Profiler deep dive

La huella sigue siendo la misma porque, aunque hayas asignado tu región al almacenamiento físico, la mayoría de los SO son perezosos y ahorradores, por lo que no hay asignación de una ubicación de almacenamiento físico específica. Por ejemplo, supongamos que decide escribir algo en la región comprometida. Todavía no hay memoria física debajo de la región, por lo que acceder a ella incurrirá en un fallo de página. En respuesta, el gestor de memoria del sistema operativo asignará una página física previamente disponible para completar su operación. Dado que todas las operaciones se realizan con granularidad de tamaño de página, las páginas no procesadas de la región permanecerán vacías y sin memoria física asignada. Del mismo modo, el tamaño de la memoria residente de su aplicación aumentará en el tamaño total de todas las páginas de memoria física asignadas para completar su operación.

Representación gráfica de las páginas comprometidas | Memory Profiler deep dive

Si no se ha accedido a una página durante un tiempo o la demanda de memoria física es alta, un sistema operativo puede descargar algunas páginas de su región asignada a memoria comprimida o a un archivo de intercambio de páginas, dependiendo de lo que admita su plataforma.

Representación gráfica de las páginas intercambiadas | Memory Profiler deep dive

En este caso, la memoria asignada de tu aplicación seguirá siendo la misma, pero el tamaño de la memoria residente disminuirá.

Cómo se calcula la huella de memoria de la aplicación

Como ya te habrás dado cuenta, si sólo te fijas en la memoria asignada puedes confundirte con la asignación que consume tu memoria física, lo que puede engañarte para que optimices algo que no es un problema. Esto no sólo le hace perder un tiempo valioso, sino que no ve ninguna diferencia en el rendimiento y la estabilidad de su aplicación.

En general, el estado de la memoria de tu aplicación puede describirse mediante este diagrama:

Diagrama de estado de la memoria de la aplicación

En resumen, así es como se calcula la huella de memoria:

Huella de memoria física = Memoria residente de la aplicación + Páginas de memoria comprimida de la aplicación
Analizar la huella de memoria

En Memory Profiler 1.1, las vistas Summary, Unity Objects y All Of Memory no sólo mostrarán el tamaño de la memoria asignada, sino que también proporcionarán información sobre la memoria residente. Sin embargo, esta información sólo se mostrará si la instantánea de Memory Profiler se realiza con Unity 2023.1 o posterior. Con las instantáneas más antiguas, seguirás viendo la interfaz de usuario actualizada y las vistas de desglose, pero sin información sobre la memoria residente.

Vista resumida de Memory Profiler 1.1 en el editor de Unity

La vistaResumen proporciona una visión general y una métrica esencial: Total de residentes en el dispositivo. Si su aplicación debe ejecutarse en una plataforma con memoria limitada, Total Resident on Device es fundamental para revisar los avisos de memoria insuficiente y los desalojos por falta de memoria. Como regla general, no deberías superar el 70% de la memoria física total disponible en un dispositivo.

Para un análisis detallado, puede utilizar las vistas Objetos de unidad yToda la memoria. Deberá seleccionar Residente en dispositivo o Asignado y residente en dispositivo en el menú desplegable y ordenar por tamaño de residente para ver los objetos que más contribuyen a la memoria física total utilizada.

Toda la vista de Memoria para Memory Profiler 1.1 en el Editor de Unity

Cuando analices el uso de memoria residente, recuerda:

  • La memoria gestionada será predominantemente residente. Mono Heap y Boehm Garbage Collector acceden regularmente a los objetos y los hacen residentes.
  • La memoria gráfica (estimada) se muestra como estimada. En la mayoría de las plataformas, no tenemos acceso a información sobre el paradero exacto de los recursos gráficos, por lo que estimamos el tamaño basándonos en la información disponible, como anchura, altura, profundidad, formato de píxeles, etc. Esto también significa que no tenemos información sobre el estatus de residencia de los recursos gráficos. Por razones de usabilidad, todos los objetos gráficos sólo se muestran en el modo de vista Asignado.
  • No rastreada es toda la memoria que el sistema operativo indica como asignada por la aplicación, pero que carece de información sólida sobre el origen de la asignación. Puede tratarse de plugins nativos, bibliotecas del sistema operativo, pilas de hilos, etc. En algunas plataformas, proporcionamos información adicional sobre quién podría haber asignado esa memoria en el desglose por grupos.

Al analizar la memoria nativa, que contiene todas las asignaciones no gestionadas de Unity utilizadas por los objetos, verá el elemento Memoria reservada. Esta es la memoria asignada por el Administrador de Memoria de Unity pero no utilizada por ningún objeto de Unity durante la captura. Aquí tienes información útil:

  • La memoria reservada puede ser residente, lo que significa que puede haber habido un objeto que se haya borrado recientemente.
  • Puede acceder a información adicional sobre el desglose de memoria reservada yendo a la configuración de Memory Profiler y activando la casilla "Mostrar desglose de memoria reservada". Por defecto, esto está deshabilitado, ya que el desglose Reservado no siempre contiene suficiente información procesable y requiere una comprensión profunda de cómo funciona el Administrador de Memoria de Unity.
  • Puede obtener más información sobre el Administrador de memoria de Unity y las estrategias de asignación en la documentación de configuración de los asignadores.

En algunas plataformas, mostramos grupos adicionales específicos de la plataforma si son de tamaño significativo, como Android Runtime en Android. He aquí algunas notas sobre Android Runtime:

  • En algunas versiones, Android Runtime tiende a preasignar una cantidad significativa de memoria pero nunca la utiliza. En ese caso, la memoria asignada no se añade a la huella de memoria de la aplicación y sólo es necesario tener en cuenta la parte residente de la misma.
  • Si la parte residente de Android Runtime está ocupando una cantidad significativa de la huella de memoria de la aplicación, utilice el perfilador de Android Studio para analizar las asignaciones realizadas en Java.
  • Aunque Android no tiene un archivo de página o compresión de memoria por defecto, el kernel de Linux permite a las aplicaciones sobrecomprometerse y asignar más memoria de la que está físicamente disponible.
  • Al capturar, asegúrate de que entiendes el dispositivo que estás utilizando. Algunos proveedores suministran al kernel Linux de Android herramientas de compresión de memoria (zRAM) o de archivos de intercambio de páginas personalizadas por el proveedor.
Conclusión

Esperamos que esta descripción general de lo que cabe esperar de Memory Profiler 1.1(versión experimental disponible ya) y la exploración de diversos temas relacionados con la huella de memoria hayan sido de utilidad.

Mi equipo y yo planeamos seguir mejorando el Memory Profiler para proporcionar información más precisa y específica, así como advertirle sobre posibles situaciones de falta de memoria y lo cerca que podrían estar. Siga el progreso de nuestra hoja de ruta de productos y díganos lo que piensa.

Comparta sus comentarios con nosotros en los foros. Asegúrate de estar atento a los nuevos blogs técnicos de otros desarrolladores de Unity como parte de la serie Tech from the Trenches.