Android 8.0 incluye pruebas de rendimiento de Binder y hwbinder para la capacidad de procesamiento y latencia. Si bien existen muchas situaciones para detectar el rendimiento perceptible problemas, ejecutar esas situaciones puede llevar mucho tiempo y los resultados suelen ser disponible hasta que se integra un sistema. Cómo usar el rendimiento proporcionado pruebas facilitan la realización de pruebas durante el desarrollo y la detección de problemas graves y mejorar la experiencia del usuario.
Las pruebas de rendimiento incluyen las siguientes cuatro categorías:
- capacidad de procesamiento de Binder (disponible en
system/libhwbinder/vts/performance/Benchmark_binder.cpp
) - latencia de Binder (disponible en
frameworks/native/libs/binder/tests/schd-dbg.cpp
) - capacidad de procesamiento de hwbinder (disponible en
system/libhwbinder/vts/performance/Benchmark.cpp
) - Latencia de hwbinder (disponible en
system/libhwbinder/vts/performance/Latency.cpp
)
Información acerca de Binder y hwbinder
Binder y hwbinder son comunicación entre procesos (IPC) de Android que comparten el mismo controlador de Linux, pero que tienen las siguientes características: Diferencias cualitativas:
Aspecto | carpeta | Hwbinder |
---|---|---|
Propósito | Proporcionar un esquema IPC de uso general para el framework | Comunicación con el hardware |
Propiedad | Optimizado para el uso del framework de Android | Latencia baja de sobrecarga mínima |
Cambia la política de programación para el uso en primer o segundo plano | Sí | No |
Argumentos que pasan | Utiliza la serialización compatible con el objeto Parcel | Usa búferes de dispersión y evita la sobrecarga para copiar los datos necesarios para Serialización de paquetes |
Herencia de prioridad | No | Sí |
Procesos de Binder y hwbinder
Un visualizador de Systrace muestra transacciones de la siguiente manera:
En el ejemplo anterior:
- Los cuatro (4) procesos schd-dbg son procesos de cliente.
- Los cuatro (4) procesos de Binder son procesos de servidor (el nombre comienza con Binder y termina con un número de secuencia).
- Un proceso del cliente siempre está vinculado con un proceso de servidor, que es a su cliente.
- El kernel programa de forma independiente todos los pares de procesos cliente-servidor de forma simultánea.
En la CPU 1, el kernel del SO ejecuta el cliente para emitir la solicitud. Luego, usa la misma CPU siempre que sea posible para activar un proceso del servidor, controlar solicitud, y el cambio de contexto una vez que se completa la solicitud.
Capacidad de procesamiento frente a latencia
En una transacción perfecta, donde el proceso del cliente y del servidor cambian. sin problemas, las pruebas de capacidad de procesamiento y latencia no producen mensajes nuevos. Sin embargo, cuando el kernel del SO maneja una solicitud de interrupción (IRQ) del hardware, esperar bloqueos o simplemente no controlar un mensaje de inmediato, se puede formar una burbuja de latencia.
La prueba de capacidad de procesamiento genera una gran cantidad de transacciones con diferentes de cargas útiles, lo que proporciona una buena estimación del tiempo de transacción regular (en en el mejor de los casos) y la capacidad de procesamiento máxima que Binder puede alcanzar.
Por el contrario, la prueba de latencia no realiza acciones en la carga útil para minimizar la hora de la transacción regular. Podemos usar el tiempo de transacción para estimar sobrecargar, generar estadísticas para el peor de los casos y calcular la proporción transacciones cuya latencia cumple con un plazo especificado.
Cómo controlar las inversiones de prioridad
Una inversión de prioridad se produce cuando, de forma lógica, un subproceso con mayor prioridad esperando un subproceso con menor prioridad. Las aplicaciones en tiempo real (RT) tienen un Problema de inversión de prioridad:
Cuando se usa la programación Completaly Fair Scheduler (CFS) de Linux, un subproceso siempre puede ejecutarse incluso cuando otros subprocesos tienen una prioridad más alta. Como resultado, las aplicaciones con programación CFS manejan la inversión de prioridad como el comportamiento esperado y no como un problema. Cuando el framework de Android necesite programación de RT para garantizar el privilegio de los subprocesos de alta prioridad; sin embargo, la inversión de prioridad debe resolverse.
Ejemplo de inversión de prioridad durante una transacción de Binder (el subproceso RT es lógicamente bloqueados por otros subprocesos de CFS cuando se espera que un subproceso de Binder servicio):
Para evitar bloqueos, puedes usar la herencia de prioridad para escalar temporalmente el subproceso de Binder a un subproceso de RT cuando envía una solicitud de un cliente de RT. Ten en cuenta que la programación de RT tiene recursos limitados y se debe usar con atención. En un sistema con n CPU, la cantidad máxima de RT actual subprocesos también es n; es posible que los subprocesos de RT adicionales deban esperar (y, por lo tanto, no cumplen con sus plazos) si otros subprocesos de RT toman todas las CPU.
Para resolver todas las inversiones de prioridad posibles, puedes usar la para Binder y hwbinder. Sin embargo, ya que Binder se usa mucho en todo el sistema, habilitar la herencia de prioridad para transacciones de Binder podría enviar spam al sistema con más subprocesos de RT de los que puede atender.
Ejecuta pruebas de capacidad de procesamiento
La prueba de capacidad de procesamiento se ejecuta con la capacidad de procesamiento de transacciones de Binder/hwbinder. En en un sistema que no está sobrecargado, las burbujas de latencia son escasas y su impacto pueden eliminarse, siempre y cuando el número de iteraciones sea lo suficientemente alto.
- La prueba de capacidad de procesamiento de binder se encuentra en
system/libhwbinder/vts/performance/Benchmark_binder.cpp
- La prueba de capacidad de procesamiento de hwbinder se encuentra en
system/libhwbinder/vts/performance/Benchmark.cpp
Resultados de la prueba
Ejemplo de resultados de la prueba de capacidad de procesamiento para transacciones que usan una carga útil diferente tamaños:
Benchmark Time CPU Iterations --------------------------------------------------------------------- BM_sendVec_binderize/4 70302 ns 32820 ns 21054 BM_sendVec_binderize/8 69974 ns 32700 ns 21296 BM_sendVec_binderize/16 70079 ns 32750 ns 21365 BM_sendVec_binderize/32 69907 ns 32686 ns 21310 BM_sendVec_binderize/64 70338 ns 32810 ns 21398 BM_sendVec_binderize/128 70012 ns 32768 ns 21377 BM_sendVec_binderize/256 69836 ns 32740 ns 21329 BM_sendVec_binderize/512 69986 ns 32830 ns 21296 BM_sendVec_binderize/1024 69714 ns 32757 ns 21319 BM_sendVec_binderize/2k 75002 ns 34520 ns 20305 BM_sendVec_binderize/4k 81955 ns 39116 ns 17895 BM_sendVec_binderize/8k 95316 ns 45710 ns 15350 BM_sendVec_binderize/16k 112751 ns 54417 ns 12679 BM_sendVec_binderize/32k 146642 ns 71339 ns 9901 BM_sendVec_binderize/64k 214796 ns 104665 ns 6495
- Time indica el retraso de ida y vuelta medido en tiempo real.
- CPU indica el tiempo acumulado en el que se programan las CPU. para la prueba.
- Las iteraciones indican la cantidad de veces que la función de prueba. ejecutado.
Por ejemplo, para una carga útil de 8 bytes:
BM_sendVec_binderize/8 69974 ns 32700 ns 21296
La capacidad de procesamiento máxima que puede alcanzar Binder se calcula de la siguiente manera:
Capacidad de procesamiento de MAX con carga útil de 8 bytes = (8 * 21296)/69974 ~= 2.423 b/ns ~= 2.268 Gb/s
Opciones de prueba
Para obtener resultados en .json, ejecuta la prueba con el archivo
Argumento --benchmark_format=json
:
libhwbinder_benchmark --benchmark_format=json
{
"context": {
"date": "2017-05-17 08:32:47",
"num_cpus": 4,
"mhz_per_cpu": 19,
"cpu_scaling_enabled": true,
"library_build_type": "release"
},
"benchmarks": [
{
"name": "BM_sendVec_binderize/4",
"iterations": 32342,
"real_time": 47809,
"cpu_time": 21906,
"time_unit": "ns"
},
….
}
Ejecuta pruebas de latencia
La prueba de latencia mide el tiempo que tarda el cliente en comenzar inicializar la transacción, cambiar al proceso del servidor para manejar para recibir el resultado. La prueba también busca comportamientos inadecuados del programador conocidos que puede afectar negativamente la latencia de la transacción, como un programador que no admite la herencia de prioridad o usa la marca de sincronización.
- La prueba de latencia de Binder está en
frameworks/native/libs/binder/tests/schd-dbg.cpp
- La prueba de latencia de hwbinder está
system/libhwbinder/vts/performance/Latency.cpp
Resultados de la prueba
Los resultados (en .json) muestran las estadísticas de latencia promedio/mejor/peor y la cantidad de fechas límite incumplidas.
Opciones de prueba
Las pruebas de latencia toman las siguientes opciones:
Comando | Descripción |
---|---|
-i value |
Especifica la cantidad de iteraciones. |
-pair value |
Especifica la cantidad de pares de procesos. |
-deadline_us 2500 |
Especifica la fecha límite. |
-v |
Obtiene un resultado detallado (depuración). |
-trace |
Detén el registro cuando se cumpla un plazo. |
En las siguientes secciones, se detalla cada opción, se describe el uso y se proporciona resultados de ejemplo.
Cómo especificar iteraciones
Ejemplo con una gran cantidad de iteraciones y resultados detallados inhabilitados:
libhwbinder_latency -i 5000 -pair 3
{
"cfg":{"pair":3,"iterations":5000,"deadline_us":2500},
"P0":{"SYNC":"GOOD","S":9352,"I":10000,"R":0.9352,
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996},
"fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
},
"P1":{"SYNC":"GOOD","S":9334,"I":10000,"R":0.9334,
"other_ms":{ "avg":0.19, "wst":2.9 , "bst":0.055, "miss":2, "meetR":0.9996},
"fifo_ms": { "avg":0.16, "wst":3.1 , "bst":0.066, "miss":1, "meetR":0.9998}
},
"P2":{"SYNC":"GOOD","S":9369,"I":10000,"R":0.9369,
"other_ms":{ "avg":0.19, "wst":4.8 , "bst":0.055, "miss":6, "meetR":0.9988},
"fifo_ms": { "avg":0.15, "wst":1.8 , "bst":0.067, "miss":0, "meetR":1}
},
"inheritance": "PASS"
}
Estos resultados de la prueba muestran lo siguiente:
"pair":3
- Crea un par de cliente y servidor.
"iterations": 5000
- Incluye 5,000 iteraciones.
"deadline_us":2500
- El plazo es de 2,500 us (2.5 ms). se espera que la mayoría de las transacciones cumplan valor.
"I": 10000
- Una sola iteración de prueba incluye dos (2) transacciones:
- Una transacción por prioridad normal (
CFS other
) - Una transacción por prioridad en tiempo real (
RT-fifo
)
- Una transacción por prioridad normal (
"S": 9352
- 9,352 de las transacciones se sincronizan en la misma CPU.
"R": 0.9352
- Indica la proporción en la que el cliente y el servidor se sincronizan en la misma CPU.
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996}
- El promedio (
avg
), el peor (wst
) y el mejor (bst
) para todas las transacciones emitidas por un emisor con prioridad normal. Dos transaccionesmiss
la fecha límite, lo que hace que la proporción de cumplimiento (meetR
) 0.9996 "fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
- Similar a
other_ms
, pero para transacciones emitidas por el cliente con Prioridadrt_fifo
. Es probable (pero no obligatorio) que elfifo_ms
tiene un mejor resultado queother_ms
, con menor Valoresavg
ywst
, y unmeetR
más alto (la diferencia puede ser aún más significativa con la carga en segundo plano).
Nota: La carga en segundo plano puede afectar la capacidad de procesamiento
y la tupla other_ms
en la prueba de latencia. Solo los
Es posible que fifo_ms
muestre resultados similares, siempre y cuando la carga en segundo plano haya
una prioridad menor que RT-fifo
.
Especifica valores de par
Cada proceso del cliente se vincula con un proceso de servidor dedicado al cliente
y cada par puede programarse
de forma independiente para cualquier CPU. Sin embargo, la CPU
la migración no debe ocurrir durante una transacción siempre que la marca SYNC se
honor
Asegúrate de que el sistema no esté sobrecargado. Si bien la alta latencia en entornos con sobrecarga
el sistema operativo, los resultados de las pruebas para un sistema sobrecargado no proporcionan
información. Para probar un sistema con una presión más alta, usa -pair
#cpu-1
(o -pair #cpu
con cuidado). Pruebas con
-pair n
con n > #cpu
sobrecarga la
y genera información inútil.
Especifica los valores de plazo
Después de realizar pruebas exhaustivas de situaciones de usuario (ejecutar la prueba de latencia en un calificado), determinamos que el plazo para cumplir es de 2,5 ms. Para nuevos aplicaciones con requisitos más elevados (como 1,000 fotos por segundo), este el valor del plazo cambiará.
Especificar un resultado detallado
Si usas la opción -v
, se muestra un resultado detallado. Ejemplo:
libhwbinder_latency -i 1 -v
-------------------------------------------------- service pid: 8674 tid: 8674 cpu: 1 SCHED_OTHER 0-------------------------------------------------- main pid: 8673 tid: 8673 cpu: 1 -------------------------------------------------- client pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0-------------------------------------------------- fifo-caller pid: 8677 tid: 8678 cpu: 0 SCHED_FIFO 99 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 ??? 99-------------------------------------------------- other-caller pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 SCHED_OTHER 0
- El subproceso de servicio se crea con un
SCHED_OTHER
y se ejecuta enCPU:1
conpid 8674
. - Luego, se inicia la primera transacción con un
fifo-caller
Para realizar esta transacción, hwbinder actualiza la del servidor (pid: 8674 tid: 8676
) en 99 y también la marca con una clase de programación transitoria (impresa como???
) El programador Luego, coloca el proceso del servidor enCPU:0
para que se ejecute y lo sincroniza con el la misma CPU con su cliente. - El emisor de la segunda transacción tiene un
Prioridad
SCHED_OTHER
. El servidor cambia a una versión inferior y entrega llamador con prioridadSCHED_OTHER
.
Cómo usar Trace para la depuración
Puedes especificar la opción -trace
para depurar los problemas de latencia. Cuándo
la latencia, la prueba de latencia detiene el registro de tracelog en el momento en que la
si se detecta latencia. Ejemplo:
atrace --async_start -b 8000 -c sched idle workq binder_driver sync freq
libhwbinder_latency -deadline_us 50000 -trace -i 50000 -pair 3
deadline triggered: halt ∓ stop trace log:/sys/kernel/debug/tracing/trace
Los siguientes componentes pueden afectar la latencia:
- Modo de compilación de Android: El modo de ingeniería suele ser más lento que el modo userdebug.
- Marco de trabajo. ¿Cómo usa el servicio de framework
¿
ioctl
para configurar Binder? - Controlador de Binder ¿El controlador admite reglas de el bloqueo? ¿Contiene todos los parches de transformación de rendimiento?
- Versión de kernel. A mayor capacidad en tiempo real, el kernel mejores serán los resultados.
- Configuración del kernel. ¿La configuración del kernel contiene
Los parámetros de configuración de
DEBUG
, comoDEBUG_PREEMPT
y ¿DEBUG_SPIN_LOCK
? - Programador de kernel. ¿El kernel tiene una configuración de eficiencia energética?
de procesamiento multiprocesamiento heterogéneo (EAS) o HMP? Usa cualquier kernel
conductores (
cpu-freq
conductor,cpu-idle
conductor,cpu-hotplug
, etc.) afectan al programador?