Version: 2017.1
Caídas
Optimizaciones

Profiling

Primeros pasos

Unity depende en el CPU (altamente optimizado para la parte SIMD de este, como SSE en X86 o NEON en ARM) para skinning, batching, física, scripts de usuario, partículas, etc.

El GPU es utilizado para shaders, drawcalls, efectos de imagen.

Unido a CPU o GPU

  • Utilice el profiler interno para detectar el ms CPU y GPU

Análisis Pareto

Una gran cantidad de problemas (80%) son producidos por unas causas claves (20%). Usted puede utilizar el perfilador del Editor para identificar la mayoría de llamadas de funciones intensivas al procesador y optimizarlas primero. A menudo, optimizar unas pocas funciones claves nos puede dar un aumento significativo en la velocidad de ejecución en general.

Usted debería asegurarse que las funciones solo son ejecutados cuando sean realmente necesarias. Por ejemplo, usted puede utilizar eventos como OnBecameVisible y OnBecameInvisible para detectar cuando un objeto no puede ser visto y evitar actualizarlo. Las Coroutines pueden ser una manera útil de llamar código que necesite actualizaciones regulares pero no necesitar correr cada cuadro:-

// Do some stuff every frame:
void Update () {
}

//Do some stuff every 0.2 seconds:
IEnumerator SlowUpdate () {
   while (true) {
      //do something
      yield return new WaitForSeconds (0.2f);
   }
}


Usted puede utilizar la clase .NET System.Threading.Thread para correr cálculos pesados en un thread separado. Esto el permite a usted correr múltiples núcleos pero tenga en cuenta que el API de Unity no es seguro para thread- usted necesita buffer los inputs y resultados y leer y asignarlos al thread principal con el fin de utilizar las llamadas de la API de Unity.

CPU Profiling (Perfilado)

Profile (perfilando) código de usuario

No todo el código del usuario es mostrado en el Profiler (perfilador). Pero usted puede utilizar Profiler.BeginSample y Profiler.EndSample para hacer que el código del usuario requerido aparezca en el perfilador.

GPU Profiling (Perfilado)

El Perfilador del Editor de Unity no puede mostrar datos del GPU por ahora. Nosotros estamos trabajando con fabricantes de hardware para hace que suceda con dispositivos Tegra siendo los primeros en aparecer en el perfilador del Editor.

Herramientas para iOS

  • El perfilador interno de Unity (no el perfilador del Editor). Este muestra el tiempo GPU para la escena entera.
  • El analizador de shader PowerVR PVRUniSCo. Ver abajo.
  • iOS: Los Instrumentos de Xcode OpenGL ES Driver puede mostrar solo información de alto-nivel:
    • “% de Utilización del Dispositivo” - tiempo GPU gastado en total del renderizado. >95% significa que la app está sujeta al GPU.
    • “% de la Utilización del Renderizador” - Tiempo GPU gastado dibujando píxeles.
    • “Tiler Utilization %” - el tiempo GPU gastado procesando vertices.
    • “Split count” - el número de divisiones de frame, dónde los datos del vértice no encajo a los buffer asignados.

PowerVR es un renderizador deferred en tejas, por lo que es imposible obtener tiempos de GPU por draw call. No obstante, usted puede obtener tiempos GPU para la escena entera utilizando el profiler (perfilador) integrado de Unity (el que imprime resultados a los output de Xcode). Las herramientas de Apple actualmente solo pueden decir qué tan ocupado el GPU y su partes están, pero no da tiempo en milisegundos.

PVRUniSCo da ciclos para el shader entero, y aproxima ciclos por cada linea en el código shader. Windows & Mac! Pero no va a coincidir con lo que los drivers de Apple están haciendo exactamente igual. Sin embargo, es una buena medida de estadio.

Herramientas para Android

  • Adreno (Qualcomm)
  • NVPerfHUD (NVIDIA)
  • PVRTune, PVRUniSCo (PowerVR)

On Tegra, NVIDIA proporciona unas herramientas de rendimiento excelentes que hace todo lo que usted quiera - el tiempo del GPU por draw call, Ciclos por shader, textura 2x2 Force, un rectángulo de vista nulo, corre en Windows, OSX, Linux. PerfHUD ES no funciona fácil con dispositivos de un consumidor, usted necesita la tabla de desarrollo de NVIDIA.

Qualcomm proporciona un excelente Perfilador Adreno (Windows solamente) que es solamente para Windows, pero funciona con dispositivos de consumo! Éste tiene de características gráficas Timeline, captura de frame, depuración de Frame, llamados API, analizador de Shader, edición en vivo.

Gráficas relacionadas al profiling (perfilamiento) de CPU

El profiler (perfilador) interno da una buena visión general por módulo:

  • tiempo gastado en OpenGL ES API
  • eficiencia de batching
  • skinning, animaciones, partículas

Puertos del Profiler (Perfilador)

Puertos que usa el profiler de Unity:

  • MulticastPort : 54998
  • ListenPorts : 55000 - 55511
  • Multicast (unittests) : 55512 - 56023

Estos deberían ser accesibles desde el nodo de network. Esto es, los dispositivos que usted está intentando perfilar deberían ser capaces de ver estos puertos en la maquina con el Editor de Unity con el Profile prendido.

Memoria

Hay dos tipos de memoria, memoria Mono y memoria de Unity.

Memoria Mono

La memoria Mono maneja objetos scripts, envolturas para objetos de Unity (game objects, assets, componentes, etc). El Garbage Collector limpia cuando la asignación no encaja en la memoria disponible o un llamado System.GC.Collect().

La memoria es asignada en bloques heap. Más se puede asignar si los datos no pueden encajar en el bloque asignado. Los bloques heap se mantendrán en Mono hasta que la app se cierre. En otras palabras, Mono no suelta cualquier memoria utilizado al OS (Unity 3.x). Una vez usted asigne cierta cantidad de memoria, se reserva para mono y no está disponible para el OS. cuando usted lo suelta, se mantendrá disponible internamente para Mono solamente y no para el OS. el valor de memoria heap en el Profiler (perfilador) solamente aumentará, nunca va a disminuir.

Si el sistema no puede encajar nuevos datos al bloque heap asignado, el Mono llamada un “GC” y puede asignar un nuevo bloque heap (por ejemplo, debido a la fragmentación).

“Too many heap sections” significa que usted se ha quedado sin memoria Mono (debido a la fragmentación o un uso fuerte).

Utilice System.GC.GetTotalMemory para obtener la memoria Mono utilizada localmente.

El consejo general es, utilice una asignación tan pequeña como sea posible.

Memoria de Unity

La memoria de Unity maneja los datos de Assets (Textura, Meshes, Audio, Animación, etc), Game Objects, internos del Motor (Renderización, Partículares, Física, etc). Utilice Profiler.usedHeapSize para obtener la memoria de Unity utilizada totalmente.

Mapa de Memoria

No hay herramientas todavía pero usted puede utilizar lo siguiente.

  • Unity Profiler (Perfilador de Unity) - no es perfecto, omite cosas, pero usted puede obtener una visión en general. Funciona en el dispositivo!
  • Internal Profiler (Perfilador Interno). Muestra el heap utilizado y asignado - ver memoria mono. Muestra el número de asignaciones mono por frame.
  • Herramientas Xcode - iOS
  • El Monitor de Actividad de Instrumentos Xcode - Columna real de memoria.
  • Asignaciones de Instrumentos Xcode - asignaciones netas para objetos creados y viviendo.
  • VM Tracker (las texturas usualmente son asignadas con una etiqueta IOKit y los meshes por lo usual van a una Asignación VM).

Usted también puede hacer su propia herramienta utilizando llamadas del API de Unity:-

  • FindObjectsOfTypeAll (type : Type) : Object[]
  • FindObjectsOfType (type : Type): Object[]
  • GetRuntimeMemorySize (o : Object) : int
  • GetMonoHeapSize
  • GetMonoUsedSize
  • Profiler.BeginSample/EndSample - perfile su propio código
  • UnloadUnusedAssets () : AsyncOperation
  • System.GC.GetTotalMemory/Profiler.usedHeapSize

Referencias a los objetos cargados - No hay forma de averiguar esto. Una solución alternativa es “Encontrar referencias en la escena” para variables públicas.

Recolector de basura

  • Eso se dispara cuando el sistema no puede encajar nuevos datos a bloque heap asignado.
  • No utilice OnGUI() en móviles: dispara varias veces por frame, re-dibuja completamente la vista y crea muchos llamados de asignaciones de memoria que requieren que el Garbage Collection sea invocado.

Creando/quitando muchos objetos muy rápido ?

  • Esto puede llevar a la fragmentación.
  • Utilice el perfilador del Editor para hacerle seguimiento a la actividad de memoria.
  • El perfilador interno puede ser utilizado para hacerle seguimiento a la actividad mono de memoria.
  • System.GC.Collect() Usted puede utilizar esta función .Net cuando sea bueno tener un hiccup.

Hiccups de Asignación

  • Utilice listas de instancias de clases pre-asignadas, re-utilizables para implementar su propio esquema de manejo de memoria.
  • No haga agrandes asignaciones por frame, cache, pre-asigne más bien
  • Hay problemas con la fragmentación?

Pre-asignaciones de una pool de memoria

  • Mantenga una lista de GameObjects inactivos y re-utilicelos en vez de instanciar y destruirlos.

Fuera de memoria mono

  • Perfile la actividad de memoria - cuándo es que la primera página de memoria se llena?
  • De verdad necesita tantos gameobjects que una sola página de memoria no es suficiente?
  • Utilice structs en vez de clases para datos locales. Las classes son almacenadas en el heap; structs en la stack.
  • Leer la página de entendiendo el Manejo de Memoria Automática

Fallas por falta de memoria

En algunos puntos un juego podría fallar con “out of memory” (falta de memoria) aunque en teoría debería encajar perfecto. Cuando esto sucede compare el footprint de memoria de su juego y el tamaño de memoria asignada cuando la falla sucede. Si los números no son similares, entonces hay un pico de memoria. Esto se puede dar a:

  • Dos escenas grandes siendo cargadas al mismo tiempo - utilice una escena vacía entre dos más grandes para arreglar esto.
  • Carga de escena aditiva - quite partes no utilizadas para mantener el tamaño de la memoria.
  • Grandes asset bundles siendo cargados a la memoria
  • Texturas sin una compresión apropiada (un no para móviles).
  • Las texturas teniendo Get/Set pixeles habilitado. Esto requiere una copia descomprimida de la textura en memoria.
  • Las Texturas siendo cargadas de JPEG/PNGs en tiempo de ejecución están descomprimidas.
  • Archivos mp3 grandes marcados como decompress (descomprimir) en la carga.
  • Mantener assets no utilizados en caches raros como campos estáticos de monobehavior, que no son limpiados cuando cambie escenas.
Caídas
Optimizaciones