Desordenar al principio: autopsia sobre la velocidad de lanzamiento de una aplicación iOS

Una aplicación moderna tiene muchos requisitos no funcionales: tamaño de la aplicación, tráfico consumido, accesibilidad para personas con discapacidades, estabilidad, inicio y velocidad de operación. Nuestra aplicación comenzó durante mucho tiempo, decenas de segundos. Hoy se lanzó una actualización en la que la aplicación iOS comenzó a ejecutarse muchas veces más rápido. Te cuento cómo sucedió y por qué solo ahora.



Comienza por mucho tiempo


La aplicación tiene mucho código, muchas clases y de alguna manera están conectadas. Para gestionar estas relaciones, utilizamos Dip (léase: Swinject o cualquier otro marco DI sin generación de código).

Funciona así: al comienzo de la aplicación, todas las dependencias se agrupan en el "contenedor", y luego se extrae la clase deseada con todas las dependencias puestas. Toma tiempo comenzar, toma tiempo abrir cualquier pantalla.

Pero las fotos son hermosas


Durante mucho tiempo, ni siquiera nos asustó: simplemente dibujamos protectores de pantalla hermosos con pizza nueva y no hicimos vapor. Los protectores de pantalla de pizza tuvieron que eliminarse cuando comenzamos en varios países, porque la variedad es diferente en todas partes. La imagen no se ha vuelto tan interesante, esperar el lanzamiento se ha vuelto más aburrido, pero nos perdimos este punto.

Aquí están nuestras salpicaduras. Hermoso, pero ocultando un problema que ni siquiera intentamos resolver.



Después del próximo lanzamiento, comenzamos a ralentizar el giro de las tarjetas en el controlador de página. El generador de perfiles de tiempo mostró que las dependencias se eliminan durante mucho tiempo cuando aparece una nueva pantalla. Por qué Es imposible de entender. Dip es muy difícil de depurar debido a las mismas llamadas abstractas. Intentamos dividir un contenedor común en muchos pequeños, pero solo empeoró. Como resultado, apagamos las tarjetas y continuamos con las actualizaciones de Año Nuevo.

Así es como se ve Dip en el perfilador. Al final de la lista se alcanza el límite de la pila de llamadas. Es imposible hacer algo razonable con esto.



Vuela a 4S? Arreglar después


En este momento, el error "no comenzó la compilación de lanzamiento en 4S" estaba en la cartera de pedidos, aunque se lanzaron los debug. Nadie notó la conexión de los problemas, elevaron la versión mínima de iOS a 10 y también pospusieron los cambios. Hay pocos usuarios en 4S, ¿verdad?

Vimos Dip: no al principio, sino en la compilación


Sin embargo, quedó claro que Dip necesitaba ser cortado. ¿Y qué cambiar? Muy a tiempo, nos encontramos con la inyección de dependencia en el artículo de Swift .

Funciona de manera simple: escribimos un montón de funciones resolve() con un tipo diferente (el compilador lo resolverá). Por lo tanto, las comunicaciones dejarán de calcularse al principio, y el compilador incluso podrá optimizar el código. Esto también es útil para el desarrollo: si describió las dependencias incorrectamente, lo descubrirá al inicio y no cuando abra la pantalla. Por supuesto, hay problemas: si la función resolve() no comprende el tipo, entonces producirá un error tan inútil con cien candidatos:



Hicimos esto en noviembre. Hubo MUY MUCHOS cambios, y en ese momento lanzamos el nuevo producto Combo y nos preparamos para los últimos cambios antes del Año Nuevo. El nuevo código apareció en el proyecto antes del Año Nuevo, pero no lo publicamos hasta enero debido al congelamiento del código previo a las vacaciones. Para esto, durante tres semanas, utilizamos el programa en modo de prueba, encontramos problemas y los solucionamos.

Así es como se ve el código de dependencia ahora. Sucio pero funcionando. 450 plazas con registro y 1400 plazas con extracción.



Funcionalmente, el código es el mismo, solo difiere la forma de trabajar con él. La diferencia de velocidad es visible en todos los modelos. En XS: el doble de rápido, y en SE, compruébelo usted mismo:


Así que aceleramos no solo el inicio, sino también la apertura de las pantallas. Antes de los cambios, cada pantalla tardaba entre 0,3 y 1 segundos solo en la dependencia.

Año nuevo sin pizza


En diciembre, comenzaron a escribirnos que la aplicación se bloquea al inicio, no se inicia y, después de reiniciar, la reinstalación no ayuda. Anteriormente, solo había una razón para esto: las migraciones de la base de datos, pero nos deshicimos de ella y no vimos nuevas salidas en Crashlytics. ¿Qué salió mal?


Hipótesis: este iOS descarta aplicaciones si se ejecutan durante mucho tiempo. La versión fue confirmada por el hecho de que todas las revisiones eran de dispositivos antiguos: 5, 5S, 6. El número de tales revisiones aumentó significativamente, debido a que la pizza es un día festivo, la gente suele pedirla para el Año Nuevo. El equipo está preocupado, el producto está preocupado, pero estamos lanzando la nueva versión solo en enero.

Tuvimos la suerte de que la solución fue escrita y solo podía probarse. En otro escenario, podrían pasar meses buscando causas y corrigiéndolas.



A veces es difícil transmitir la importancia de una tarea técnica a una empresa: no hay métricas, la importancia no está clara, el peligro no se predice. Las empresas pueden resolver el problema de diferentes maneras: así es como pintamos bellas imágenes, en lugar de acelerar la aplicación. Pero el rendimiento es importante para cada usuario. Afecta mucho:

  • Esperando Si la aplicación comienza por mucho tiempo, ¿cuánto tiempo tomarán pizza?
  • El placer de usar. ¿Por qué estúpido en cada pantalla?
  • E incluso por la estabilidad. “¡La aplicación no se está ejecutando! Desarrolladores, ¿prueban allí? ”(C).

Y omita los marcos Dip, Swinject y otros que funcionan con contenedores en tiempo real si tiene un proyecto grande y muchas dependencias.
Para no perderse el siguiente artículo, suscríbase al canal Dodo Pizza Mobile.

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


All Articles