Android renderiza la IU generando un fotograma desde tu app y mostrándolo en la pantalla. Si tu app renderiza la IU lentamente, el sistema se verá obligado a omitir fotogramas. Cuando esto sucede, el usuario percibe un parpadeo recurrente en la pantalla, que se conoce como bloqueo.
Cuando se produce un bloqueo, generalmente se debe a alguna obstaculización o desaceleración de la llamada asíncrona en el subproceso de IU (en la mayoría de las apps, es el subproceso principal). Puedes usar los registros del sistema para identificar dónde está el problema.
Cómo detectar bloqueos en Android 12 y versiones posteriores
En el caso de los dispositivos que ejecutan Android 12 (nivel de API 31) o versiones posteriores, se muestra un seguimiento capturado en el segmento fotogramas con bloqueos, en el panel Display del Generador de perfiles de CPU.
Para detectar bloqueos, haz lo siguiente:
En Android Studio, selecciona View > Tool Windows > Profiler o haz clic en el botón Profile
de la barra de herramientas.
Si aparece el diálogo Select Deployment Target, elige el dispositivo en el que quieres implementar tu app para la generación de perfiles. Si conectaste un dispositivo mediante USB, pero no lo ves en la lista, asegúrate de haber habilitado la depuración por USB.
Haz clic en cualquier parte del cronograma CPU para abrir CPU Profiler.
Selecciona System Trace en el menú de configuración del Generador de perfiles de CPU y haz clic en Record. Cuando termines de interactuar con la app, haz clic en Stop.
Deberías ver el segmento Janky frames en Display. De forma predeterminada, el generador de perfiles solo muestra fotogramas con bloqueos como candidatos para la investigación. En cada fotograma con bloqueos, la parte roja destaca la duración del fotograma después de su plazo de renderización.
Una vez que encuentres un fotograma con bloqueos, haz clic en él. También puedes presionar M para ajustar el zoom y enfocar el fotograma seleccionado. Los eventos relevantes se destacan en estos subprocesos: el principal, RenderThread y GPU completion.
De manera opcional, puedes ver todos los fotogramas o un desglose del tiempo de renderización si activas las casillas de verificación All Frames y Lifecycle, respectivamente.
Cómo detectar bloqueos en Android 11
En los dispositivos con Android 11 (nivel de API 30), se muestra un seguimiento capturado en la sección Frame Lifecycle en el Generador de perfiles de CPU.
La sección Frame Lifecycle contiene el nombre de la capa y cuatro segmentos. Cada segmento representa una etapa de la canalización de procesamiento de fotogramas. Los elementos de Frame Lifecycle son los siguientes:
- Frame Lifecycle (nombre de la capa): El título de la sección contiene el nombre de la capa entre paréntesis. Una capa es una unidad de composición única.
- Application: Este segmento muestra el tiempo desde que la app retiró el búfer hasta que se volvió a poner en cola. Por lo general, corresponde a los eventos de seguimiento en
RenderThread
. - Wait for GPU: Este segmento muestra el tiempo que el búfer fue propiedad de la GPU. Es el tiempo que transcurre desde que se envía el búfer a la GPU hasta que esta termina de trabajar en el búfer. Esto no indica que la GPU haya estado funcionando solo en ese búfer durante ese tiempo. Para obtener información detallada sobre el trabajo de la GPU en un momento determinado, te recomendamos que uses el Inspector de GPU de Android.
- Composition: Este segmento muestra el tiempo que transcurre desde que SurfaceFlinger se conecta al búfer y lo envía para su composición hasta que se envía el búfer a la pantalla.
- Frames on display: Este segmento muestra cuánto tiempo estuvo el fotograma en la pantalla.
En la sección Frame Lifecycle, se ilustra cómo se mueve un búfer de fotogramas entre las diferentes etapas de la canalización de procesamiento. Los fotogramas están codificados por colores según el número de fotograma para que sea más fácil realizar un seguimiento de un elemento específico.
Android Studio también muestra todos los fotogramas del seguimiento en formato de tabla en la pestaña All Frames.
Las columnas Frame #, Application, Wait for GPU y Composition representan los mismos datos que los segmentos de la sección Frame Lifecycle, como se muestra más arriba. La columna Frame Duration representa la hora desde el inicio de Application hasta el inicio de Frames on Display. En esencia, es el tiempo que lleva procesar un fotograma de extremo a extremo.
Puedes ordenar la tabla de fotogramas por cualquier columna para encontrar rápidamente el fotograma más corto o más largo. La tabla también admite controles de paginación que te permiten navegar por cientos de fotogramas.
Para detectar e investigar bloqueos en Android 11, sigue estos pasos:
Ordena la tabla All Frames por la columna Application en orden descendente para que aparezcan los fotogramas que más tardan en completarse.
Busca los fotogramas con mayor tiempo de ejecución y selecciona la fila de la tabla. Se acerca el marco seleccionado en la vista de cronograma a la izquierda.
Busca subprocesos relevantes en las secciones Frame Lifecycle y Threads.
Cómo detectar bloqueos en Android 10 y versiones anteriores
En el caso de los dispositivos que ejecutan Android 10 (nivel de API 29) y versiones anteriores, la información de la canalización de gráficos de SO relevantes se muestra en una sola sección en el seguimiento del sistema del Generador de perfiles de CPU denominado Display.
- Frames: En esta sección, se muestran el subproceso de IU y los eventos de seguimiento de
RenderThread
en tu app. Los eventos que duran más de 16 ms se muestran en color rojo para destacar posibles fotogramas con bloqueos porque exceden el plazo de renderización a 60 fotogramas por segundo (fps). - SurfaceFlinger: En esta sección, se muestra cuándo SurfaceFlinger procesa los búferes de fotogramas. SurfaceFlinger es un proceso del sistema que se encarga de enviar búferes a la pantalla.
- VSYNC: En esta sección, se muestra VSYNC, una señal que sincroniza la canalización de la pantalla. En el segmento, se muestra la señal de VSYNC-app, que indica cuándo tu app se inicia demasiado tarde. Por lo general, esto ocurre porque el subproceso de IU está ocupado. Hace que aparezca un parpadeo visible en la pantalla durante una animación y agrega latencia de entrada adicional hasta que se completa la animación o el desplazamiento. Es muy importante visualizar esta información en pantallas con una frecuencia de actualización alta, ya que pueden ocurrir con más frecuencia que 60 veces por segundo o a una frecuencia variable.
- BufferQueue: En esta sección, se muestra cuántos búferes de fotogramas están en cola y esperando que SurfaceFlinger los use. En el caso de las apps implementadas en dispositivos con Android 9 (nivel de API 28) o versiones posteriores, este segmento muestra el recuento de búferes de la plataforma BufferQueue de la app (
0
,1
o2
). BufferQueue puede ayudarte a comprender el estado de los búferes de imagen mientras se mueven entre los componentes gráficos de Android. Por ejemplo, si el valor es2
, significa que la app tiene búfer triple, que generará una latencia de entrada adicional.
La sección Display proporciona indicadores útiles para detectar posibles bloqueos, por ejemplo, cuando el subproceso de IU o RenderThread
tardan más de 16 ms. Para investigar detalles exactos de qué provocó el bloqueo, puedes sondear la sección Threads, que muestra los subprocesos relevantes para la renderización de la IU.
En la figura anterior, la sección Threads muestra el subproceso de IU (java.com.google.samples.apps.iosched
), RenderThread
y el subproceso GPU completion
. Son los subprocesos relevantes para la renderización de la IU y pueden contribuir al bloqueo.
Para detectar bloqueos en Android 10 o versiones anteriores, sigue estos pasos:
Busca el segmento Frames en Display. Los fotogramas rojos son candidatos para la investigación.
Una vez que encuentres un fotograma con el posible bloqueo, presiona
W
o desplázate por la rueda del mouse mientras mantienes presionado Ctrl (Command en macOS). Sigue acercando la imagen hasta que empieces a ver los eventos de seguimiento en el subproceso de IU yRenderThread
.En la figura anterior,
Choreographer#doFrame
muestra cuándo el subproceso de IU llama aChoreographer
para coordinar la animación, el diseño de la vista, el dibujo de imágenes y los procesos relacionados.DrawFrames
muestra cuándoRenderThread
se forma y emite comandos de dibujo reales a la GPU.Si ves un evento de seguimiento muy largo, puedes acercar la imagen y descubrir qué podría haber generado la renderización lenta. En la figura anterior, se muestra el objeto
inflate
en el subproceso de IU, lo que significa que la app dedica tiempo a aumentar el diseño. Cuando haces zoom en uno de los eventosinflate
, puedes averiguar exactamente cuánto tiempo toma cada componente de la IU, como se muestra a continuación.
Más información
Si deseas obtener más información para reducir el bloqueo, consulta Fuentes comunes de bloqueos.