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 .

Capturando 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 en el momento del arranque, utilice 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 aparte de mirar el encabezado apropiado (que podría cambiar entre versiones de Android).

Habilitación de eventos ftrace

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, utilice:

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 han habilitado eventos adicionales escribiendo en nodos sysfs, atrace no los restablecerá. Un patrón común para activar dispositivos Qualcomm es habilitar los puntos de seguimiento 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 en modo de usuario). Para ejecutar simplemente 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 proporciona el seguimiento en forma de texto. Para visualizarlo usando Catapult, obtenga el repositorio de 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.

Eventos correlacionados

A menudo resulta útil observar la visualización de Catapult y el registro de ftrace simultáneamente; por ejemplo, Catapult no visualiza algunos eventos ftrace (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 determinado a partir de un evento Catapult:

  1. Abra el registro ftrace sin procesar. Los seguimientos en versiones recientes de systrace están comprimidos de forma predeterminada:
    • Si capturó su systrace con --no-compress , esto está en el archivo html en la sección que comienza con BEGIN TRACE.
    • De lo contrario, ejecute html2trace desde el árbol 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 del seguimiento 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 el evento (o al menos muy cerca de él).

Usando ftrace dinámico

Cuando systrace y ftrace estándar son insuficientes, hay un último recurso disponible: ftrace dinámico . Dynamic ftrace implica la reescritura del código del kernel después del arranque y, como resultado, no está disponible en los kernels de producción por razones de seguridad. Sin embargo, todos los errores de rendimiento difíciles en 2015 y 2016 fueron causados ​​en última instancia por el uso de ftrace dinámico. Es especialmente poderoso para depurar suspensiones ininterrumpidas porque puede obtener un seguimiento de la pila en el kernel cada vez que activa la función que activa la suspensión ininterrumpida. También puede depurar secciones con interrupciones y apropiaciones deshabilitadas, lo que puede resultar muy útil para demostrar problemas.

Para activar ftrace dinámico, edite la configuración defconfig de su kernel:

  1. Elimine CONFIG_STRICT_MEMORY_RWX (si está presente). Si tienes la versión 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 e inicie el nuevo kernel.
  4. Ejecute lo siguiente para comprobar si hay trazadores disponibles:
    cat /sys/kernel/tracing/available_tracers
    
  5. Confirme que el comando devuelve function , irqsoff , preemptoff y preemptirqsoff .
  6. Ejecute lo siguiente para asegurarse de que el ftrace dinámico esté funcionando:
    cat /sys/kernel/tracing/available_filter_functions | grep <a function you care about>
    

Después de completar estos pasos, tendrá disponibles el perfilador dinámico, el perfilador de funciones, el perfilador irqsoff y el perfilador preemptoff. Recomendamos encarecidamente leer la documentación de ftrace sobre estos temas antes de usarlos, ya que son potentes pero complejos. irqsoff y preemptoff son útiles principalmente para confirmar que los conductores pueden estar dejando las interrupciones o la preferencia desactivadas durante demasiado tiempo.

El generador de perfiles de funciones es la mejor opción para problemas de rendimiento y, a menudo, se utiliza para averiguar dónde se llama 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 ftrace se pueden habilitar exactamente de la misma manera que de costumbre y se entrelazarán con su seguimiento. Esto es excelente si ocasionalmente hay una suspensión prolongada e ininterrumpida en una función específica que desea depurar: configure el filtro ftrace 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 formato.

Usando lockstat

A veces, ftrace no es suficiente y realmente es necesario 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 empezar a 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 utiliza la infraestructura de bloqueo de depuración, que es útil para muchas otras aplicaciones. Todos los que trabajan en la recuperación de dispositivos deberían encontrar alguna manera de hacer que esa opción funcione en todos los dispositivos porque habrá un momento en el que pensarás "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 seguimiento de bloqueos es similar a ftrace:

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

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

Usar puntos de seguimiento de proveedores

Utilice primero los puntos de seguimiento ascendentes, pero a veces necesitará utilizar 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 seguimiento son extensibles mediante el servicio HAL, lo que le permite agregar puntos/categorías de seguimiento 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 seguimiento/categorías son:

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