Como aceleramos a inicialização do aplicativo Dropbox para Android em 30%

A inicialização do aplicativo é a primeira coisa que nossos usuários experimentam depois de instalar um aplicativo e, novamente, toda vez que o iniciam. Um aplicativo simples e rápido traz aos usuários muito mais alegria do que um aplicativo que tem muitos recursos, mas leva uma eternidade para carregar. Percebendo isso, a equipe do Dropbox Android investiu em medir, identificar e corrigir os problemas que afetavam o tempo de inicialização do nosso aplicativo. Acabamos melhorando o tempo de inicialização do nosso aplicativo em 30%, e esta é a história de como fizemos isso.

Escalada crescente

Historicamente, no Dropbox, monitoramos o início do aplicativo medindo quanto tempo levou desde o momento em que um usuário toca no ícone do aplicativo até o momento em que o aplicativo está totalmente carregado e pronto para as interações do usuário. 

Nós abstraímos a medição para a inicialização do aplicativo da seguinte maneira:

Sendo uma equipe orientada por dados, temos acompanhado e monitorado a inicialização do aplicativo com a ajuda de gráficos acessíveis a todos os engenheiros. O gráfico abaixo mostra as medições de p90 de inicialização do aplicativo do final de março ao início de abril de 2020.

medições de p90 de inicialização do aplicativo do final de março ao início de abril de 2020

Como você pode ver no gráfico, o tempo de inicialização do aplicativo não parece estar mudando muito. Pequenas flutuações na inicialização do aplicativo, que variam de alguns milissegundos, são esperadas em um aplicativo usado por milhões de usuários com uma variedade de dispositivos e versões de sistema operacional. 

No entanto, quando olhamos para o tempo de inicialização do aplicativo de dezembro de 2019 a abril de 2020, vimos uma imagem diferente. O tempo de inicialização do aplicativo vem aumentando há meses, conforme o aplicativo evoluiu e mais recursos foram adicionados. No entanto, como nossos gráficos estavam apenas nos mostrando as mudanças ao longo de um período de duas semanas, perdemos a lentidão do tempo de inicialização do aplicativo que estava acontecendo ao longo de vários meses.

tempo de inicialização do aplicativo android p90 de dezembro de 2019 a abril de 2020

Embora a descoberta do aumento lento do tempo de inicialização tenha sido acidental, ela nos levou a aprofundar os motivos, além de garantir que nossas ferramentas de monitoramento, alerta e gráficos estivessem dando uma olhada mais ampla e coesa em nossas métricas. 

Me dê mais números

Alguns recursos do aplicativo podem ser relativamente simples de medir, como quanto tempo leva uma chamada de API para o servidor. Enquanto outros recursos, como inicialização do aplicativo, são muito mais complicados de medir. A inicialização do aplicativo requer muitas etapas diferentes no dispositivo antes que a tela principal do aplicativo seja mostrada ao usuário e o aplicativo esteja pronto para interação com o usuário. Examinando nosso código de inicialização, identificamos os principais eventos que acontecem durante a inicialização do nosso aplicativo. Aqui estão alguns deles:

  1. Executar migrações
  2. Carregar serviços de aplicativo
  3. Carregar usuários iniciais

Começamos nossa investigação aproveitando as ferramentas de criação de perfil no Android Studio para medir o desempenho em nossos telefones de teste. O problema de traçar o perfil de desempenho com essa abordagem era que nossos telefones de teste não nos dariam uma amostra estatisticamente significativa de quão bem a inicialização do aplicativo está realmente indo. O aplicativo Dropbox para Android tem mais de 1 bilhão de instalações na Google Play Store, abrangendo vários tipos de dispositivos, alguns deles antigos Nexus 5s e outros os mais novos e melhores dispositivos do Google. Seria uma missão tola tentar traçar o perfil de tantas configurações. Portanto, decidimos medir as diferentes etapas de inicialização do aplicativo usando cenários e etapas de cenário na produção.

Aqui está o código de inicialização atualizado, onde adicionamos o registro para as três etapas mencionadas acima: 

Com as medições instrumentadas em código, pudemos entender quais etapas na inicialização do aplicativo estavam contribuindo mais para o aumento da inicialização do aplicativo.

Infratores de desempenho que encontramos

O gráfico abaixo mostra o tempo geral de inicialização do aplicativo de janeiro a outubro de 2020.

tempo de inicialização do aplicativo android p90 de janeiro a outubro de 2020

Em maio, introduzimos medidas para cada uma das etapas principais que acontecem durante a inicialização do aplicativo. Essas medições nos permitiram identificar e abordar os maiores infratores ao desempenho da inicialização do aplicativo. 

gráfico de dados mostrando cada uma das principais etapas que acontecem durante a inicialização do aplicativo Android

Os principais infratores na inicialização do aplicativo incluem a inicialização da biblioteca Firebase Performance, a migração de sinalizadores de recursos e o carregamento inicial do usuário.

Biblioteca de desempenho do Firebase

A biblioteca Firebase Performance está incluída no pacote de produtos Firebase do Google para medir e enviar métricas sobre o desempenho dos aplicativos. Ele fornece funcionalidades úteis, como métricas para desempenho de método individual, bem como infraestrutura para monitorar e visualizar o desempenho de diferentes partes do aplicativo. Infelizmente, a biblioteca Firebase Performance também vem com alguns custos ocultos. Entre eles está um processo de inicialização caro e, como resultado, um aumento significativo nos tempos de construção. Em nossa depuração, descobrimos que a inicialização do pacote Firebase demorava sete vezes mais quando a ferramenta Firebase Performance estava habilitada. Para corrigir o problema de desempenho, optamos por remover a ferramenta Firebase Performance do aplicativo Android Dropbox.

Migrações

Existem várias migrações internas que são executadas sempre que o aplicativo Dropbox é iniciado. Isso pode incluir sinalizadores de recursos de atualização, migrações de banco de dados, etc. Infelizmente, descobrimos que algumas dessas migrações estavam em execução a cada inicialização do aplicativo. Não notamos o mau desempenho dessas migrações anteriormente, pois o aplicativo foi iniciado rapidamente nos dispositivos de desenvolvimento e teste. Infelizmente, esse código de migração teve um desempenho especialmente ruim em versões mais antigas do sistema operacional e dispositivos mais antigos, contribuindo para aumentar o tempo de inicialização. Para resolver o problema, começamos investigando quais migrações eram essenciais em cada lançamento e quais migrações agora podiam ser totalmente removidas do aplicativo. Encontramos e removemos pelo menos uma migração que era muito antiga e, portanto, não era mais necessária, ajudando a colocar o tempo de inicialização do nosso aplicativo de volta nos trilhos. 

Carregando os usuários

Na parte legada de nosso aplicativo, armazenamos metadados de contatos de usuários do Dropbox no dispositivo como blobs JSON. Em um mundo ideal, esses blobs JSON devem ser lidos e convertidos em objetos Java apenas uma vez. Infelizmente, o código para extrair usuários estava sendo chamado várias vezes de diferentes recursos legados do aplicativo e, a cada vez, o código executava uma análise JSON cara para converter blobs JSON do usuário em objetos Java. Armazenar contatos de usuário como JSON era um design muito desatualizado e uma parte de nosso código legado monolith. Para obter uma correção imediata para esse problema, adicionamos funcionalidade para armazenar em cache os objetos de usuário analisados ​​durante a inicialização. À medida que continuamos trabalhando para quebrar o código legado do monólito, uma solução mais eficiente e moderna para armazenamento de contato do usuário seria usar objetos de banco de dados Room e converter esses objetos em entidades de negócios.

E agora?

Como resultado da remoção da referência ao Firebase Performance, remoção de etapas de migração caras e armazenamento em cache do carregamento do usuário, melhoramos o desempenho de inicialização do aplicativo Dropbox para Android em 30%. Por meio desse trabalho, também criamos painéis que ajudarão a evitar a degradação do tempo de inicialização do aplicativo no futuro. 

Também adotamos várias práticas que, esperançosamente, nos impedirão de cometer os mesmos erros de desempenho. Aqui estão alguns deles:

Medir o impacto no desempenho de inicialização do aplicativo ao adicionar bibliotecas de terceiros

Com a descoberta de quanto a biblioteca Firebase Performance degradou a inicialização de nosso aplicativo, introduzimos um processo para adicionar bibliotecas de terceiros. Hoje, precisamos medir o tempo de inicialização do aplicativo, o tempo de construção e o tamanho do APK do aplicativo antes que a biblioteca possa ser adicionada e usada em nossa base de código. 

Armazenar todas as coisas em cache
Como dois dos principais responsáveis ​​pelo desempenho de inicialização do aplicativo estão relacionados ao armazenamento em cache, preferimos armazenar em cache cálculos caros, mesmo que isso torne o código um pouco mais complicado. Afinal, uma melhor experiência do usuário vale um pouco de manutenção extra. 

Conclusão

Com mais investimentos em análises confiáveis ​​e medição de desempenho, nos tornamos muito mais orientados por dados como uma equipe, o que nos permite fazer maiores investimentos em nossa base de código, como descontinuar o código C ++ legado , com muito mais confiança. Hoje, monitoramos vários painéis que nos fornecem insights sobre o desempenho das partes mais críticas de nossos aplicativos e temos processos em vigor para garantir que os aplicativos do Dropbox continuem a ser ágeis e um deleite para nossos usuários.

Solicite uma trial do Dropbox e conte sempre com o apoio da equipe Figo Sofware!

Facebook
Pinterest
Twitter
LinkedIn

Deixe uma resposta