Optimización del rendimiento de Android: optimización de inicio

La velocidad de inicio de una aplicación es la primera experiencia del usuario. Hay una regla de los ocho segundos en Internet. Si un usuario espera ocho segundos antes de que se abra la aplicación, el 70% de los usuarios dejará de esperar.

 1. Iniciar clasificación

Hora de inicio de la aplicación oficial 

  • Inicio fresco

         El estándar de medición que consume más tiempo

  • Arranque en caliente

         lo más rápido. Entre bastidores ~ Frente al escenario

  • Arranque en caliente

         Más rápido. Sólo repetirá el ciclo de vida de la actividad, pero no la creación del proceso y el ciclo de creación y vida de la Aplicación.

proceso de arranque en frio

  1. Clics del usuario 
  2. Activar operación IPC
  3. Creación del proceso Process.start
  4. ActivityThread es la entrada a cada proceso por separado. Habrá un método principal para crear el bucle de mensajes y el controlador.
  5. bindApplication crea una aplicación a través de la reflexión y llama al ciclo de vida de la aplicación.
  6. Ciclo de vida de la actividad Ciclo de vida 
  7. ViewRootImpl inicia el dibujo de la interfaz real

Antes del arranque en frío (este proceso no se puede intervenir)

  • Iniciar aplicación 
  • Cargar una ventana en blanco 
  • Proceso de creación

Tareas posteriores

  • Crear aplicación 
  • Iniciar el hilo principal
  • Crear actividad principal 
  • Cargar diseño
  • pantalla de diseño
  • Primer cuadro dibujado

Optimice
        el ciclo de vida de la Aplicación y la Actividad

2. Cómo medir el tiempo de inicio

modo de comando adb

        adb shell am start -W nombre del paquete/首屏Actividad 

    Características:

  • Fácil de usar sin conexión pero no se puede conectar a Internet
  • Tiempo no estricto y preciso

El método de marcado manual
        entierra puntos cuando comienza y entierra puntos cuando comienza y termina. La diferencia entre las dos
     características:       

         Preciso, se puede poner en línea, se recomienda su uso

     Evite malentendidos

  • El punto de inicio del tiempo de inicio está en el adjuntoBaseContext de la aplicación. 
  • La posición final del tiempo de inicio adopta la primera visualización del avance.
  • addOnDrawListener requiere API 16

ThisTime El tiempo necesario para iniciar la última actividad
TotalTime El tiempo necesario para iniciar todas las actividades
WaitTime El tiempo total necesario para iniciar la actividad AMS

3. Inicie las herramientas utilizadas para la optimización.

 vista de seguimiento, ruta del sistema 

  • Ambas herramientas se complementan
  • Comprender correctamente las herramientas y elegir las herramientas adecuadas para diferentes escenarios.

vista de seguimiento

  • ventaja
    •  Forma gráfica, que muestra el tiempo de ejecución del código, información de la pila de llamadas, etc.
    • Información completa, incluida toda la información del hilo.
  •  Uso

      Debug.startMethodTracing("nombre de archivo"); el tamaño predeterminado es 8M. Si desea un tamaño mayor, pase el parámetro bufferSize. 
      Debug.stopMethodTracing()
      generará un archivo al final de la tarjeta SD: Android/data/packagename /archivos

Hay un Explorador de archivos de dispositivos en el lado derecho de Android Studio, que puede abrir fácilmente los archivos del sistema del teléfono móvil.
Después de agregar el código de apertura y cierre, ejecútelo, actualícelo en la ubicación de almacenamiento y establezca un nombre de archivo. Se generará el archivo .trace.

  • como analizar
    • La parte superior izquierda es el rango de tiempo especificado con precisión a través del código, y hay un tiempo en la esquina inferior izquierda, que no es particularmente importante.
    • La parte inferior izquierda es la información del hilo. Puede ver el número total de hilos y lo que hizo cada hilo en un momento específico. 

Hay cuatro pestañas a la derecha. 

  • De arriba hacia abajo

total: tiempo total

ser :

niños:

Por ejemplo: se llama a la función A, el tiempo total es total, se llama a una línea de código en la función A y luego se ejecuta la función B. Su selfTime es el momento en que se ejecuta una línea de código y ChildrenTime es el momento en que Se ejecuta la función B. La suma de selfTime y childTime debe ser igual a totalTime.

Lista de llamadas de función, haga clic en el salto correspondiente a souse para saltar al código detallado

ThreadTime definitivamente disminuirá, el momento en que la CPU ejecuta
Wall Clock Time El código ocurre en este hilo, el tiempo de ejecución real

  • chat de llamada 

Cada fila muestra el período de tiempo de la llamada a la función y se llama al método vertical.
El color de la llamada a la API del sistema es naranja,
la llamada a la función propia de la aplicación es verde y
la llamada a la API de terceros es azul.

  • Gráfico de llamas de chat de llamas

Gráfico de llamadas invertidas, que recoge la misma secuencia de llamadas

  • De abajo hacia arriba

Quien me llamó es lo opuesto a De arriba hacia abajo

Resumen:
        La sobrecarga del tiempo de ejecución es grave y todo se ralentizará. Esta herramienta es demasiado poderosa y capturará todas las funciones de ejecución de todos los subprocesos y el orden puede
        sesgar la dirección de optimización. Los beneficios de
        traceview y cpu Profiler 
                traceview pueden ser enterrado en el código Utilice el análisis del perfilador de CPU
                Es casi imposible usar simplemente el perfilador de CPU para capturar la ubicación de inicio precisa.

 sistematrace

Combine datos del kernel de Android para generar
un script Python de informe html

  • Uso

• python systrace.py -t 10 [otras opciones] [categorías]

  • Documentación oficial:

https://developer.android.com/studio/command-line/systrace#command_options

  • Casos de uso

python /Users/Liuzhao.Future/Library/Android/sdk/platform-tools/ systrace/systrace.py -b 32768 -t 5 -a com.optimize.rendimiento -o rendimiento. aplicación html programada gf view wm am

  • utilizado en el código

Abierto: TraceCompat.beginSection(“apponCreate”)
Fin: TraceCompat.endSection 

  • Analizar archivos html

La cantidad de núcleos de CPU está relacionada con diferentes teléfonos móviles. Algunos fabricantes de teléfonos móviles le ofrecen 8 núcleos. Algunos teléfonos móviles tienen 8 núcleos, pero solo se utilizan 4 núcleos.

  • Resumir:
    • Ligero, con pocos gastos generales, simplemente haz lo que quieras
    • Refleja intuitivamente la utilización de la CPU

cpuTime y wallTime

  • wallTime es el momento en que se ejecuta el código
  • cpuTime es el tiempo que el código consume la CPU (indicador clave)

Ejemplo: ¿Por qué los dos tienen diferentes
        conflictos de bloqueo? Por ejemplo, un subproceso necesita adquirir el bloqueo A para su ejecución, pero el bloqueo A está retenido por otros subprocesos y no se ha liberado. Sin embargo, este subproceso es liviano y solo ocupa un poco tiempo de la CPU, por lo que en este momento cpuTime será muy corto y wallTime será muy largo.

4. Cómo obtener elegantemente el consumo de tiempo de CPU

Necesita saber qué método está consumiendo más tiempo

  • Método convencional: puntos de enterramiento manuales
    • muy invasivo
    • Pesada carga de trabajo
  • Método AOP: programación orientada a aspectos, programación orientada a aspectos
    • Manejo unificado del mismo tipo de problemas.
    • Agregar código sin intrusión

Uso de aspectos

  • classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.0'
  • implementación 'org.aspectjaspectjrt:1.8.+'
  • aplicar complemento: 'android-aspectix'

introducir

  • Unirse a puntos
    • El punto de ejecución cuando el programa se está ejecutando se puede utilizar como lugar para aspectos
    • llamada de función, ejecución
    • Obtener y establecer variables
    • Inicialización de clase
  • Punto de corte
    • JoinPoints con condiciones
  • Consejo
    • Una especie de gancho, donde se insertará el código.
    • Antes: ejecutado antes de PointCut
    • Después: ejecutado después de PointCut
    • Alrededor: ejecutar por separado antes y después de Pointcut
  • Introducción a la gramática
    //Before:Advice,具体插入位置
    //execution :处理Join Point的类型
    //(* android.app.Activity.on**(.)):匹配规则
    @Before("execution(* android.app.Activity.on** (.))") 
    public void onActivityCalled (JoinPoint joinPoint) thr
    ows Throwable {
        ……
    }
  • Casos de uso
@Aspect
public class Performanceaop{

    Around("call(*com.optimize.performance.PerformanceApp.**(..))") 
    public void getTime(ProceedingJoinPointjoinPoint){
        Signature signature=joinPoint.getSignature(); 
        String name=signaturetoShortString(); 
        long time=System.currentTimeMillis(); 
        try {
            joinPoint.proceed();
        } catch(Throwable throwable){
            throwable.printStackTrace();
        }
        LogUtils.i(msg:name+" cost "+(System.currentTimeMillis() - time));
    }
}
  • ventaja
    • No invasivo
    • Fácil de modificar

5. Optimización asincrónica

  • Optimización asincrónica general: uso de grupos de subprocesos para optimización asincrónica
  • Launcher (la solución óptima para la optimización del inicio asíncrono)

Modo asíncrono normal

Cosas a tener en cuenta sobre los métodos asincrónicos convencionales:

  • No todo el código puede ser directamente asincrónico
  1. No cumple con los requisitos asincrónicos: algunas tareas deben ejecutarse en el hilo principal
  2. Debe completarse en una etapa determinada. Las tareas asincrónicas se utilizan en la interfaz de presentación. Al ejecutar la interfaz, algunos códigos deben completarse en una etapa determinada antes de que se complete la tarea asincrónica. Solución: CountDownLatch es equivalente a agregar un candado.
  3. Distinguir entre tareas con uso intensivo de CPU y tareas con uso intensivo de IO

Puntos débiles de las soluciones asincrónicas convencionales:

  • El código no es lo suficientemente elegante.
  • La escena es difícil de manejar (dependencia), finalice una tarea dentro de un tiempo específico
  • Altos costos de mantenimiento

Modo lanzador

Idea central:
     aprovechar al máximo los múltiples núcleos de la CPU y ordenar automáticamente la secuencia de tareas.Proceso
de inicio:

  • El código está orientado a tareas y la lógica de inicio se abstrae en Tarea. 
  • Genere un gráfico acíclico dirigido basado en las dependencias de todas las tareas.
  • Los subprocesos múltiples se ejecutan secuencialmente según la prioridad ordenada.

6. Inicialización retrasada

  • Solución general: handler.postDelay 
  • Mejor solución: inicializar las tareas retrasadas en lotes

Problemas con las soluciones convencionales:

  • El momento es difícil de controlar.
  • Causando retraso en la alimentación

Ventajas de la mejor solución: aprovechando la función IdleHandler, ejecución inactiva

  • El tiempo de ejecución es claro.
  • Aliviar el retraso en la alimentación

7. Resumen: poner en marcha la política general de optimización

  • Carga asíncrona, retrasada y diferida
  • Combinando tecnología y negocios

8. Precauciones

  • Permisos de modificación del código de inicio de convergencia
  • La modificación del código de inicio junto con Ci requiere una revisión o notificación

9. Otras opciones

  • Cargue SharedPreferences con anticipación 

        Cargue antes de multidex, aproveche al máximo esta etapa y la CPU 
        sobrescribirá getApplicationContext y devolverá esto

  • No inicie procesos secundarios durante el inicio

        Los procesos secundarios compartirán recursos de la CPU, lo que provocará que la CPU del proceso principal se esfuerce.
         Preste atención a la secuencia de inicio. La aplicación onCreate está precedida por ContentProvider. 

  • Optimización de la carga de clases, carga de clases asincrónica por adelantado
  • Suprimir GC durante la fase de inicio 
  • Bloqueo de frecuencia de la CPU

Supongo que te gusta

Origin blog.csdn.net/weixin_42277946/article/details/131808262
Recomendado
Clasificación