Prueba de rendimiento de la aplicación Flutter

El marco Flutter funciona bien y rápido por defecto, pero ¿eso significa que no necesita pensar en el rendimiento? No Es absolutamente real escribir aplicaciones Flutter que serán lentas. Por otro lado, también puede usar el marco al máximo y hacer que sus aplicaciones no solo sean rápidas, sino también eficientes, consumiendo menos tiempo de procesador y batería.



Esto es lo que queremos ver: un resultado estadísticamente significativo de comparar dos versiones de su aplicación por alguna métrica significativa. Sigue leyendo para saber cómo.


Existen algunas pautas generales para optimizar el rendimiento en Flutter:


  • Involucre la menor cantidad de widgets posible al actualizar el estado.
  • Actualice el estado solo cuando sea necesario.
  • Realice tareas computacionalmente intensivas de sus métodos de build e idealmente del aislamiento principal.

La triste verdad es que para muchas preguntas sobre la optimización del rendimiento, la respuesta será "qué suerte". ¿Vale la pena esta optimización en particular el esfuerzo y el costo de mantenimiento para este widget en particular? ¿Este enfoque particular tiene sentido en esta situación particular?


La única respuesta útil a estas preguntas es la prueba y la medición. Cuantifique cómo cada opción afecta el rendimiento y tome decisiones basadas en estos datos.


La buena noticia es que Flutter proporciona herramientas de creación de perfiles de gran rendimiento como Dart DevTools (actualmente en la versión de vista previa), que incluye el Inspector de Flutter, o puede usar el Inspector de Flutter directamente desde Android Studio (con el complemento Flutter instalado). Tiene un Flutter Driver para probar su aplicación y el Profile mode para guardar la información de rendimiento.


La mala noticia es que los teléfonos inteligentes modernos son demasiado inteligentes.


El problema con los reguladores


La cuantificación del rendimiento de la aplicación Flutter es especialmente difícil para los controladores iOS y Android. Estos demonios de nivel de sistema controlan la velocidad de los procesadores centrales y gráficos dependiendo de la carga. Por supuesto, básicamente esto es bueno, ya que proporciona un funcionamiento sin problemas con menos consumo de batería.


La desventaja es que puede hacer que su aplicación sea mucho más rápida al aumentar la cantidad de trabajo que realiza.


A continuación, puede ver cómo agregar un ciclo de llamadas de impresión sin sentido a la aplicación hizo que el regulador cambiara la CPU a una frecuencia mayor, lo que hizo que la aplicación fuera mucho más rápida y su rendimiento más predecible.


El problema con los reguladores: por defecto, no puedes confiar en tus números. En este diagrama de tramo, tenemos corridas separadas en el eje x (marcadas por la hora exacta en que comenzaron) y tiempo de construcción en el eje Y. Como puede ver, cuando presentamos algunas declaraciones de impresión completamente innecesarias, esto lleva al hecho de que el tiempo de construcción disminuye pero no arriba


En este experimento, el peor código resultó en un tiempo de compilación más rápido (ver arriba), un tiempo de rasterización más rápido y una mayor velocidad de fotogramas. Cuando un código objetivamente peor conduce a indicadores de rendimiento mejorados, no puede confiar en estos indicadores como guía (recomendación).


Este es solo un ejemplo de cómo las pruebas de rendimiento de aplicaciones móviles pueden ser poco intuitivas y complejas.


A continuación, comparto algunos de los consejos que reuní mientras trabajaba en la aplicación Flutter's Developer Quest para Google I / O.


Consejos generales


  • No mida el rendimiento en modo de depuración ( DEBUG mode ). Mida el rendimiento solo en el Profile mode perfil.
  • Mida en un dispositivo real, no en iOS Simulator o Android Emulator. Los emuladores de software son excelentes para el desarrollo, pero tienen características de rendimiento diferentes a las reales. Flutter no le permitirá trabajar en modo de creación de perfiles en un dispositivo simulado, porque no tiene sentido. Los datos que recopila de esta manera no son aplicables al rendimiento real.
  • Lo ideal es usar exactamente el mismo dispositivo físico. Conviértalo en su dispositivo de prueba de rendimiento dedicado y nunca lo use para otra cosa.
  • Explore las herramientas de creación de perfiles de rendimiento de Flutter.

Reguladores de CPU / GPU


Como se discutió anteriormente, los sistemas operativos modernos cambian la frecuencia de cada procesador y GPU a su disposición de acuerdo con la carga y algunas otras heurísticas. (Por ejemplo, tocar la pantalla generalmente aumentará la velocidad de su teléfono Android).


En Android, puede deshabilitar estos controles. Llamamos a este proceso "bloqueo de escala".


  • Cree un script que desactive los controles en su dispositivo para probar el rendimiento. Puedes usar el ejemplo de Skia para inspirarte. También puede consultar la API de CPU de Unix .
  • Es posible que desee algo menos versátil y más ligero si no hace tanto trabajo de prueba como Skia. Consulte el script de shell en Developer Quest para ver a dónde ir. Por ejemplo, la siguiente parte del script establece la CPU para el controlador de espacio de usuario (el único controlador que no cambia la frecuencia del procesador en sí).
     #!/usr/bin/env bash GOV="userspace" echo "Setting CPU governor to: ${GOV}" adb shell "echo ${GOV} > /sys/devices/system/cpu/cpu${CPU_NO}/cpufreq/scaling_governor" ACTUAL_GOV=`adb shell "cat /sys/devices/system/cpu/cpu${CPU_NO}/cpufreq/scaling_governor"` echo "- result: ${ACTUAL_GOV}" 
  • Su objetivo aquí no es simular el rendimiento real (los usuarios no apagan los reguladores en sus dispositivos), sino tener indicadores de rendimiento comparables entre las ejecuciones.
  • Al final, debe experimentar y adaptar el script de shell al dispositivo que usará. Esto funciona, pero hasta que lo haga, sus datos de rendimiento lo engañarán.


Una versión anterior de Developer Quest, probada con el controlador Flutter en mi escritorio.


Conductor de aleteo


Flutter Driver te permite probar automáticamente tu aplicación. Lea la sección "Perfiles de rendimiento" en flutter.dev para saber cómo usarlo al perfilar su aplicación.


  • Para probar el rendimiento, no pruebe manualmente su aplicación. Utilice siempre el controlador Flutter para obtener datos realmente indicativos.
  • Escriba su código de Flutter Driver para que compruebe lo que realmente quiere medir. Si necesita un rendimiento general de la aplicación, intente revisar todas las partes de la aplicación y haga lo que el usuario haría.
  • Si su aplicación tiene un elemento de aleatoriedad ( Random , eventos de red, etc.), cree un "simulacro" para tales situaciones. Las ejecuciones de prueba deben estar tan cerca una de la otra como sea posible.
  • Si lo desea, puede agregar eventos personalizados a la línea de tiempo utilizando los startSync() y finishSync() de la clase Timeline . Esto puede ser útil si está interesado en el desempeño de una función en particular. Coloque startSync() al principio y finishSync() al final.
  • Guarde tanto el resumen ( writeSummaryToFile ) como, lo que es más importante, la línea de tiempo sin formato ( writeTimelineToFile ).
  • Pruebe cada versión de su aplicación muchas veces. Para Developer Quest, pasé 100 inicios. (Cuando mide cosas que pueden ser ruidosas, como el uso de la métrica p99, es posible que necesite muchas más ejecuciones). Para los sistemas basados ​​en POSIX, esto simplemente significa hacer algo como lo siguiente: for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done for i in {1..100}; do flutter drive --target=test_driver/perf.dart --profile; done

La herramienta de línea de tiempo de Chrome para verificar resultados de perfiles en Flutter.


Cronograma


La línea de tiempo es el resultado bruto de los resultados de su perfil. Flutter escribe esta información en un archivo JSON, que se puede descargar en chrome://tracing .


  • Comprende cómo abrir la línea de tiempo completa en Chrome. Simplemente abra chrome://tracing en el navegador Chrome, haga clic en "Cargar" y seleccione el archivo JSON. Puedes leer más en esta breve guía . (También hay una herramienta de línea de tiempo de Flutter que se encuentra actualmente en la vista previa técnica. No la usé porque el proyecto Developer Quest se lanzó antes de que las herramientas de Flutter estuvieran listas).
  • Use las teclas WSAD para navegar por la línea de tiempo en chrome://tracing y 1234 para cambiar los modos de funcionamiento.
  • Cuando configure las pruebas de rendimiento por primera vez, considere ejecutar Flutter Driver con la herramienta Systrace de Android. Esto le da una mejor idea de lo que realmente está sucediendo en el dispositivo, incluida la información sobre la escala de la frecuencia del procesador. No mida toda la aplicación con Systrace, ya que esto hará que todo sea más lento y menos predecible.
  • ¿Cómo ejecutar Android Systrace con Flutter Driver? Primero, inicie Android Systrace con /path/to/your/android/sdk/platform-tools/systrace/systrace.py --atrace-categories=gfx,input,view,webview,wm,am,sm,audio,video,camera,hal,app,res,dalvik,rs,bionic,power,pm,ss,database,network,adb,pdx,sched,irq,freq,idle,disk,load,workq,memreclaim,regulators,binder_driver,binder_lock . Luego, flutter run test_driver/perf.dart --profile --trace-systrace aplicación flutter run test_driver/perf.dart --profile --trace-systrace . Finalmente, ejecute la flutter drive --driver=test_driver/perf_test.dart --use-existing-app=http://127.0.0.1:NNNNN/ Driver Flutter flutter drive --driver=test_driver/perf_test.dart --use-existing-app=http://127.0.0.1:NNNNN/ (donde NNNNN es el puerto que le proporciona la aplicación de flutter anterior).

Métricas


Es mejor ver tantas métricas como sea posible, pero decidí que algunas son más útiles que otras.


  • El tiempo de compilación y el tiempo de rasterización (las métricas que se proporcionan de manera predeterminada usando TimelineSummary ) solo son útiles para pruebas de rendimiento realmente difíciles, que no incluyen mucho más que crear una interfaz de usuario.


  • No considere TimelineSummary.frameCount como una forma de calcular fotogramas por segundo (FPS). Las herramientas de creación de perfiles de aleteo no proporcionan información de velocidad de fotogramas real. TimelineSummary proporciona el método countFrames() , pero solo cuenta el número de conjuntos de marcos completados. Una aplicación bien optimizada que limita las reconstrucciones innecesarias (actualizaciones) tendrá un FPS más bajo que una aplicación no optimizada que se reconstruye con frecuencia.


  • Personalmente, obtengo los datos más útiles al medir el tiempo total del procesador dedicado a ejecutar el código Dart. Esto cuenta el código ejecutado tanto en sus métodos de build como fuera de ellos. Suponiendo que ejecuta pruebas de creación de perfiles en un dispositivo con bloqueo de escala, el tiempo total de CPU puede considerarse una buena aproximación a la cantidad de batería que consumirá más o menos batería.


  • La forma más fácil de averiguar el tiempo total de procesador empleado en la ejecución del código Dart es estimar la cantidad de eventos de MessageLoop:FlushTasks en la línea de tiempo. Para Developer Quest, escribí una herramienta Dart para extraerlos.


  • Para encontrar basura (basura) (es decir, cuadros descartados), busque los extremos. Por ejemplo, para un caso específico de Developer Quest y el dispositivo en el que probamos, es útil echar un vistazo al tiempo de construcción del percentil 95. (El tiempo de construcción del percentil 90 fue demasiado similar, incluso si compara el código con niveles de rendimiento completamente diferentes, y los números del percentil 99 suelen ser ruidosos. Su rendimiento puede variar).


  • Como se mencionó anteriormente, pruebe cada versión de su aplicación varias (quizás 100) veces. Luego use datos promedio o percentiles con campos de error. Mejor aún, use gráficos de span.



Resultados


Después de la optimización, puede comparar con confianza las confirmaciones y realizar experimentos. A continuación puede ver la respuesta a un dilema común: "¿Vale la pena esta optimización de los costos de mantenimiento?"


Creo que en este caso particular la respuesta es sí. Gracias a unas pocas líneas de código, cada paso automatizado de nuestra aplicación requiere un promedio de 12% menos de tiempo de CPU.


Pero, y este es el mensaje principal de este artículo, las mediciones de otra optimización pueden mostrar algo completamente diferente. Es tentador pero incorrecto intentar extrapolar una medición de rendimiento de manera demasiado amplia.


En otras palabras: "qué suerte". Y tenemos que aguantarlo.

Source: https://habr.com/ru/post/451840/


All Articles