usando ftrace

ftrace es una herramienta de depuración para comprender lo que sucede dentro del kernel de Linux. Las siguientes secciones detallan la funcionalidad básica de ftrace, el uso de ftrace con atrace (que captura eventos del kernel) y ftrace dinámico.

Para obtener detalles sobre la funcionalidad avanzada de ftrace que no está disponible en systrace, consulte la documentación de ftrace en <kernel tree>/Documentation/trace/ftrace.txt .

Captura de eventos del kernel con atrace

atrace ( frameworks/native/cmds/atrace ) usa ftrace para capturar eventos del kernel. A su vez, systrace.py (o run_systrace.py en versiones posteriores de Catapult ) usa adb para ejecutar atrace en el dispositivo. atrace hace lo siguiente:

  • Configura el seguimiento en modo de usuario estableciendo una propiedad ( debug.atrace.tags.enableflags ).
  • Habilita la funcionalidad ftrace deseada escribiendo en los nodos ftrace sysfs apropiados. Sin embargo, como ftrace admite más funciones, puede configurar algunos nodos sysfs usted mismo y luego usar atrace.

Con la excepción del seguimiento durante el arranque, confíe en el uso de atrace para establecer la propiedad en el valor adecuado. La propiedad es una máscara de bits y no hay una buena manera de determinar los valores correctos que no sea mirar el encabezado apropiado (que podría cambiar entre las versiones de Android).

Habilitación de eventos de seguimiento

Los nodos ftrace sysfs están en /sys/kernel/tracing y los eventos de seguimiento se dividen en categorías en /sys/kernel/tracing/events .

Para habilitar eventos por categoría, use:

echo 1 > /sys/kernel/tracing/events/irq/enable

Para habilitar eventos por evento, use:

echo 1 > /sys/kernel/tracing/events/sched/sched_wakeup/enable

Si se habilitaron eventos adicionales escribiendo en los nodos sysfs, atrace no los restablecerá. Un patrón común para la activación del dispositivo Qualcomm es habilitar los puntos de kgsl (GPU) y mdss (display pipeline) y luego usar atrace o systrace :

adb shell "echo 1 > /sys/kernel/tracing/events/mdss/enable"
adb shell "echo 1 > /sys/kernel/tracing/events/kgsl/enable"
./systrace.py sched freq idle am wm gfx view binder_driver irq workq ss sync -t 10 -b 96000 -o full_trace.html

También puede usar ftrace sin atrace o systrace, lo cual es útil cuando desea realizar seguimientos solo del kernel (o si se ha tomado el tiempo de escribir a mano la propiedad de seguimiento del modo de usuario). Para ejecutar solo ftrace:

  1. Establezca el tamaño del búfer en un valor lo suficientemente grande para su seguimiento:
    echo 96000 > /sys/kernel/tracing/buffer_size_kb
    
  2. Habilitar seguimiento:
    echo 1 > /sys/kernel/tracing/tracing_on
    
  3. Ejecute su prueba, luego deshabilite el seguimiento:
    echo 0 > /sys/kernel/tracing/tracing_on
    
  4. Volcar el rastro:
    cat /sys/kernel/tracing/trace > /data/local/tmp/trace_output
    

trace_output da la traza en forma de texto. Para visualizarlo usando Catapult, obtenga el repositorio Catapult de GitHub y ejecute trace2html:

catapult/tracing/bin/trace2html ~/path/to/trace_file

De forma predeterminada, esto escribe trace_file.html en el mismo directorio.

Correlación de eventos

A menudo es útil mirar la visualización de Catapult y el registro de seguimiento simultáneamente; por ejemplo, Catapult no visualiza algunos eventos de seguimiento (especialmente los específicos del proveedor). Sin embargo, las marcas de tiempo de Catapult son relativas al primer evento en el seguimiento o a una marca de tiempo específica descargada por atrace, mientras que las marcas de tiempo sin procesar de ftrace se basan en una fuente de reloj absoluta particular en el kernel de Linux.

Para encontrar un evento ftrace dado de un evento Catapult:

  1. Abra el registro de seguimiento sin procesar. Los seguimientos en versiones recientes de systrace están comprimidos de forma predeterminada:
    • Si capturó su systrace con --no-compress , está en el archivo html en la sección que comienza con BEGIN TRACE.
    • De lo contrario, ejecute html2trace desde el árbol de Catapult ( tracing/bin/html2trace ) para descomprimir el seguimiento.
  2. Encuentre la marca de tiempo relativa en la visualización de Catapult.
  3. Busque una línea al comienzo de la traza que contenga tracing_mark_sync . Debería verse así:
    <5134>-5134  (-----) [003] ...1    68.104349: tracing_mark_write: trace_event_clock_sync: parent_ts=68.104286
    

    Si esta línea no existe (o si usó ftrace sin atrace), los tiempos serán relativos desde el primer evento en el registro de ftrace.
    1. Agregue la marca de tiempo relativa (en milisegundos) al valor en parent_ts (en segundos).
    2. Busque la nueva marca de tiempo.

Estos pasos deberían ubicarlo en (o al menos muy cerca) del evento.

Uso de seguimiento dinámico

Cuando systrace y ftrace estándar son insuficientes, hay un último recurso disponible: ftrace dinámico . El seguimiento dinámico implica la reescritura del código del núcleo después del arranque y, como resultado, no está disponible en los núcleos de producción por motivos de seguridad. Sin embargo, cada error de rendimiento difícil en 2015 y 2016 fue causado en última instancia por el uso de Dynamic Ftrace. Es especialmente poderoso para depurar los períodos de suspensión ininterrumpidos porque puede obtener un seguimiento de la pila en el kernel cada vez que presiona la función que activa el período de suspensión ininterrumpida. También puede depurar secciones con interrupciones y preferencias deshabilitadas, lo que puede ser muy útil para probar problemas.

Para activar el seguimiento dinámico, edite la configuración predeterminada de su kernel:

  1. Quite CONFIG_STRICT_MEMORY_RWX (si está presente). Si está en 3.18 o posterior y arm64, no está allí.
  2. Agregue lo siguiente: CONFIG_DYNAMIC_FTRACE=y, CONFIG_FUNCTION_TRACER=y, CONFIG_IRQSOFF_TRACER=y, CONFIG_FUNCTION_PROFILER=y y CONFIG_PREEMPT_TRACER=y
  3. Reconstruya y arranque el nuevo kernel.
  4. Ejecute lo siguiente para verificar los rastreadores disponibles:
    cat /sys/kernel/tracing/available_tracers
    
  5. Confirme que el comando devuelve la function , irqsoff , preemptoff y preemptirqsoff .
  6. Ejecute lo siguiente para asegurarse de que el seguimiento dinámico esté funcionando:
    cat /sys/kernel/tracing/available_filter_functions | grep <a function you care about>
    

Después de completar estos pasos, tiene disponibles Dynamic Ftrace, Function Profiler, Irqsoff Profiler y Preemptoff Profiler. Recomendamos enfáticamente leer la documentación de ftrace sobre estos temas antes de usarlos, ya que son poderosos pero complejos. irqsoff y preemptoff son principalmente útiles para confirmar que los controladores pueden estar desactivando las interrupciones o la preferencia durante demasiado tiempo.

El perfilador de funciones es la mejor opción para los problemas de rendimiento y, a menudo, se usa para averiguar dónde se llama a una función.


Si los datos del generador de perfiles de funciones no son lo suficientemente específicos, puede combinar los puntos de seguimiento de ftrace con el generador de perfiles de funciones. Los eventos de seguimiento se pueden habilitar exactamente de la misma manera que de costumbre, y se intercalarán con su seguimiento. Esto es excelente si hay una suspensión ininterrumpida prolongada ocasional en una función específica que desea depurar: establezca el filtro de seguimiento en la función que desea, habilite los puntos de seguimiento, realice un seguimiento. Puede analizar el seguimiento resultante con trace2html , encontrar el evento que desea y luego obtener seguimientos de pila cercanos en el seguimiento sin procesar.

Usando lockstat

A veces, ftrace no es suficiente y realmente necesita depurar lo que parece ser una contención de bloqueo del kernel. Hay una opción más del kernel que vale la pena probar: CONFIG_LOCK_STAT . Este es un último recurso, ya que es extremadamente difícil trabajar en dispositivos Android porque infla el tamaño del kernel más allá de lo que la mayoría de los dispositivos pueden manejar.

Sin embargo, lockstat usa la infraestructura de bloqueo de depuración, que es útil para muchas otras aplicaciones. Todos los que trabajen en la activación del dispositivo deberían encontrar alguna forma de hacer que esa opción funcione en todos los dispositivos porque habrá un momento en el que pienses "Si tan solo pudiera activar LOCK_STAT , podría confirmar o refutar esto como el problema en cinco minutos en lugar de cinco días."


Si puede iniciar un kernel con la opción de configuración, el rastreo de bloqueo es similar a ftrace:

  1. Habilitar rastreo:
    echo 1 > /proc/sys/kernel/lock_stat
    
  2. Ejecute su prueba.
  3. Deshabilitar seguimiento:
    echo 0 > /proc/sys/kernel/lock_stat
    
  4. Vuelca tu rastro:
    cat /proc/lock_stat > /data/local/tmp/lock_stat
    

Para obtener ayuda para interpretar la salida resultante, consulte la documentación de lockstat en <kernel>/Documentation/locking/lockstat.txt .

Uso de puntos de seguimiento de proveedores

Utilice primero los puntos de seguimiento aguas arriba, pero a veces tendrá que utilizar los puntos de seguimiento del proveedor:

  { "gfx",        "Graphics",         ATRACE_TAG_GRAPHICS, {
        { OPT,      "events/mdss/enable" },
        { OPT,      "events/sde/enable" },
        { OPT,      "events/mali_systrace/enable" },
    } },

Los puntos de rastreo son extensibles por el servicio HAL, lo que le permite agregar puntos de rastreo/categorías específicos del dispositivo. Los puntos de seguimiento están integrados con perfetto, atrace/systrace y la aplicación de seguimiento del sistema en el dispositivo.

Las API para implementar puntos de rastreo/categorías son:

  • listCategories() genera (categorías vec<TracingCategory>);
  • enableCategories(vec<cadena> categorías) genera (estado de estado);
  • disabledAllCategories() genera (estado de estado);
Para obtener más información, consulte la definición de HAL y la implementación predeterminada en AOSP :