Sampling Profiler y Rogue Case of App Profiling | de Akash Khunt | marzo 2023

Imagen generada por DALL E (caricatura de un mamut dormido en una jungla) Esta es una publicación sobre cómo un problema de rendimiento de falso positivo (es decir, El hilo principal duerme durante aproximadamente 1 segundo durante el inicio de la aplicación) me dejó perdiendo muchos días depurando e identificando la causa raíz. Este problema solo se observó al perfilar una compilación de lanzamiento, y eso también en un dispositivo que estaba limitado por la memoria (RAM) y la potencia de la CPU.

Contenidos

fondo

Primero, cubramos algunos antecedentes. Si recientemente intentó crear un perfil de una aplicación de Android para identificar/depurar algunos problemas de rendimiento o simplemente para recopilar métricas de tiempo de lanzamiento, es posible que esté familiarizado con una recomendación muy común pero muy útil de que siempre debe perfilar liberar construye

La razón para usar liberar se construye mientras se perfila es que depurar Las compilaciones incurren en penalizaciones de rendimiento significativas y variables y no son útiles para medir con precisión el tiempo. Esta caída en el rendimiento se puede atribuir a una de las muchas funciones de compilación de depuración que permiten a los desarrolladores agregar un depurador en cualquier momento, lo que requiere el seguimiento de muchas cosas, como la memoria y los seguimientos de la pila.

Pero dado que las compilaciones de lanzamiento están destinadas a ser no depurables y de mayor rendimiento, no rastrea nada listo para usar y, por lo tanto, no es perfilable. Para abordar este problema, el equipo de Android ha introducido Configuración de manifiesto perfilable en API 29, que también se puede mantener seguro en las compilaciones de lanzamiento, lo que nos permite perfilar una compilación de lanzamiento con muy poca sobrecarga de rendimiento y una mínima preocupación por la divulgación de datos, ya que las herramientas de creación de perfiles del host no pierden datos de memoria y pueden ser leídos por el shell proceso.

El tema

Me enfrenté a este problema de inactividad del subproceso principal al perfilar nuestra aplicación en diferentes conjuntos de dispositivos para reducir el tiempo de arranque en frío. Para obtener la hora de inicio (es decir, TTID & TTFD) Creé uno punto de referencia macro módulo en mi aplicación. La belleza de las macropruebas comparativas es que también generan sistema Archivos que puede usar para comprender qué están haciendo los diferentes subprocesos en cualquier momento. A partir de los resultados de la prueba, encontré algunos de los cuellos de botella, uno de los más grandes fue la devolución de llamada de mapeo de usuarios donde una llamada de red contribuyó del 20% al 25% del tiempo TTFD. El problema aquí fue que hicimos esperar al usuario. Obtenemos los datos de atribución de la llamada de la red. A partir de los datos de systrace en un nivel bajo (2 GB de memoria), también vimos que el hilo principal durmió durante ~1 segundo 😲 como se muestra en la captura de pantalla a continuación.

Nota: El nombre del hilo principal está oculto por motivos de confidencialidad de la aplicación.

sistema espectáculos Ante todo sueño de hilo para ~1 segundoEsto parecía una victoria fácil para reducir el tiempo de arranque en frío, por lo que comenzamos la discusión con nuestro equipo de productos y recibimos la aprobación para continuar con el procesamiento diferido de la devolución de llamada de mapeo, es decir, permitir que el usuario continúe en nuestra página de inicio sin bloquearlo.

Los ojos muy observadores también deberían haber notado esto en la captura de pantalla de systrace anterior Grupo de subprocesos Jit también se ejecuta durante una cantidad de tiempo decente, que la integración puede reducir significativamente perfiles basicos. 🙂

Después de hacer el cambio apropiado, volvimos a ejecutar las pruebas y vimos caer nuestro tiempo TTFD. ~20% En un dispositivo de gama alta (8 GB de RAM y Android 13), pero en un dispositivo de gama baja (2 GB de RAM y Android 10), seguía siendo muy similar. Como primer paso para la resolución de problemas, volvimos a ejecutar la prueba de tiempo de inicio (como muchas otras cosas en la vida, el primer paso para la resolución de problemas siempre es volver a intentar el paso fallido 😉), pero el resultado siguió siendo el mismo 😅. Luego pasé unos días tratando de identificar el problema que podría estar causando que el subproceso principal se suspendiera durante 1 segundo, pero no se encontró nada. Luego, un día, miré qué hacían todos y cada uno de los hilos generados por nuestra aplicación cuando el hilo principal se durmió y finalmente encontré al culpable. Era el Perfilador de muestreo Hilo que, por alguna razón, solo estuvo activo durante 1 segundo (exactamente el mismo tiempo que el hilo principal se durmió) donde también durmió la mayor parte del tiempo, como se muestra en la captura de pantalla a continuación.Perfilador de muestreo Thread vive y duerme al mismo tiempo durante 1s como Ante todo El subproceso se va a dormir Cuando revisé los rastros del subproceso Sampling Profiler, descubrí que estaba realizando dos operaciones principales Adjuntar hilo actual & Desconectar hilo actual Como se muestra abajo.Ejecutar registros de Perfilador de muestreo También intenté mover una gran cantidad de código aquí y allá para ver si hay una condición específica que podría causar que se inicie este subproceso del generador de perfiles de muestreo. Una correlación muy vaga que he visto fue cada vez que el subproceso principal parecía libre durante unos cientos de milisegundos del generador de perfiles de muestreo para hacer su trabajo. Como el nombre «Sampling Profiler sugiere que parecía hacer algún trabajo relacionado con la creación de perfiles, por lo que llegamos a la conclusión de que esto no debería afectar las sesiones reales de los usuarios. Pero como todavía queríamos estar seguros, los eliminé. <perfilable> -Elemento del archivo de manifiesto para garantizar que la aplicación ni siquiera sea perfilable al capturar las pistas. y desde que lo hice elemento, no pude ejecutar las pruebas comparativas correctamente, así que terminé usándolo Capturar/registrar seguimiento Opción presente en opciones de desarrollador para capturar el archivo de seguimiento. Y después de mirar los archivos de seguimiento, confirmamos que el problema de suspensión del subproceso principal de 1s finalmente se solucionó 🙌.

Diploma

A pesar de agregó un retraso de 1 segundo a la mayoría de las métricas de tiempo macro, es decir, TTID y TTFD. No es posible eliminarlo ya que se necesita con urgencia para ejecutar las pruebas de evaluación comparativa. Así que hemos llegado a la conclusión de que antes de usar una métrica de tiempo macro en dispositivos de gama baja, eliminamos 1s del tiempo informado (después de analizar los archivos de seguimiento). ni siquiera afecta a los usuarios reales 🙂.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.