Intro
Nós aqui do time de plataforma mobile iOS do LuizaLabs, resolvemos publicar um estudo que fizemos internamente com intuito de ajudar a comunidade e informar sobre integração de dependência. Hoje existem diferentes gerenciadores de dependências no mundo iOS, com isso, existe sempre a dúvida de qual poderia nos atender melhor, ser mais performático, mais escalável e etc. Resolvermos então por a mão na massa e levantar essa informação.
Recentemente, realizamos a migração do Buck pelo Tuist. Com isso, estamos buscando aperfeiçoar a performance do projeto durante o build e geração de projeto, o que nos faz ganharmos mais tempo para codar.
Um dos pontos impactantes neste processo é a maneira como integramos dependências externas ao projeto. Por este motivo, buscamos realizar alguns testes de outras duas formas bem famosas de integração: Carthage e Swift Package Manager (SPM), e comparar com a maneira hoje utilizada (Cocoapods).
Objetivos dos testes
- Analisar em detalhes os diferentes métodos de integração de dependências no SuperApp e colher resultados a cerca de diferentes aspectos performáticos.
- Auxiliar o time de plataforma mobile iOS na decisão de qual método utilizar para integrar dependências externas ao projeto.
Abordagem
A fim de testarmos os impactos e performance dos diferentes modos de integração de dependências existentes, realizamos testes para observar características relacionadas à compilação do projeto.
Como não foi possível migrar todo o conjunto de dependências externas para os dois gerenciadores de dependências analisados, uma comparação direta entre Carthage vs. SPM não pôde ser feita. Nesse caso, somente análises SPM vs. Cocoapods e Carthage vs. Cocoapods foram realizadas.
* Para cada métrica observada, realizamos N testes de coleta dos dados, o valor de N aparece junto aos resultados obtidos.
Dispositivos Utilizados
Cocoapods vs. SPM vs. Carthage — Aplicação
- Cold Make Project — Geração do projeto após execução de um clean. (N=5)
- Warm Make Project — Geração do projeto após já ter sido gerado anteriormente. (N=5)
- Cold Indexing — Indexação do projeto após execução de um clean. (N=3)
- Warm Indexing — Indexação do projeto após já ter sido indexado. (N=7)
- Cold Build — Build do projeto após execução de um clean. (N=3)
- Warm Build — 1º build do projeto após start project e sem ter tido suas dependências apagadas. (N=7)
- Incremental Build — Rebuild do projeto após mudança em arquivo. Neste caso editamos um método de um dos módulos. (N=7)
- Os testes foram realizados com as dependências já baixadas.
Análise dos Resultados
- SPM vs Cocoapods: aumento médio no tempo de Cold Make Project em ~61.2% utilizando SPM. Essa alta diferença durante o Cold Make Project se explica pelo fato de o SPM realizar a busca das dependências durante o step de make project. Aumento médio no tempo de Warm Make Project em ~5.4% utilizando SPM.
- Carthage vs Cocoapods: redução média no tempo de Cold Make Project em ~10.2% utilizando Carthage. Redução média no tempo de Warm Make Project em ~10.4% utilizando Carthage.
Indexação do Projeto
Apesar de o tempo de Cold Indexing ter apresentado uma redução média de ~9% ao comparar SPM com Cocoapods, e de ~8.9% ao usar Carthage, os tempos mensurados na máquina Macbook Pro i7 trazem resultados inesperados em relação à esta medida. Testes adicionais devem ser feitos no futuro para tirar conclusões mais assertivas.
Compilação do Projeto
- SPM vs. Cocoapods: redução média no tempo de Cold Build em ~47% utilizando SPM. Tempo de Warm Build inconclusivo. Tempo de Incremental Build com leve redução de ~5% utilizando SPM.
- Carthage vs Cocoapods: redução média no tempo de Cold Build em ~15% utilizando Carthage. Redução média no tempo de Warm Build em ~9%. Redução média no tempo de Incremental Build em ~12%.
Testes do Projeto
Fastlane Test: SPM aumentou ~2.5%. Carthage reduziu ~8.7%.
Warm Test Build: SPM reduziu ~3%. Carthage reduziu ~12%.
Incremental Test Build: SPM reduziu ~14%. Carthage reduziu ~22%.
Tempo no CI — Bitrise
Também foi notada uma redução no tempo total de duração dos testes no CI ao usar SPM/Carthage se comparado com Cocoapods.
- SPM: redução de ~3.1%
- Carthage: redução de ~4.6%
Tamanho do App
- Testflight: SPM reduziu em ~3.8% o tamanho do ZIP gerado em comparação ao Cocoapods. SPM reduziu em ~2.4% o tamanho do app instalado em devices. Carthage aumentou em ~6.7% o tamanho do ZIP gerado. Carthage aumentou em ~1.6% o tamanho do app instalado.
Conclusões
Com a substituição ferramental do Buck pelo Tuist para geração do projeto iOS, foi possível realizar este estudo. Seu objetivo principal visa o teste e comparação entre diferentes gerenciadores de dependências e seus distintos aspectos performáticos.
Dentre os principais resultados, podemos destacar:
Geração de Build:
- SPM — aumento no tempo de geração do projeto, tanto cold como warm, ~61.2% e ~5.4%, respectivamente. Isso pode ser facilmente explicado visto que o SPM realiza busca das dependências durante este step. Além disso, esse tempo pode ser reduzido através do uso da flag disablePackageVersionLocking (Config.swift | Tuist Documentation).
- Carthage — redução no tempo de geração do projeto, tanto cold como warm, ~10.2% e ~10.4%, respectivamente.
Indexação do Projeto:
- Ambos gerenciadores (SPM e Carthage) apresentaram resultados parciais com redução de cerca de 9% nos tempos de cold indexing.
Compilação do Projeto:
- SPM — redução nos tempos de cold build e incremental build, ~47% e ~5%, respectivamente. Tempo para warm build inconclusivo.
- Carthage — redução nos tempos de cold build, warm build e incremental build, ~15%, ~9% e ~12%, respectivamente.
Testes do Projeto:
- SPM — reduziu levemente o tempo da lane de testes em ~2.5%, o tempo de warm build dos testes em ~3% e o de build incremental em ~14%.
- Carthage — reduziu o tempo da lane de testes em ~8.7%, o tempo de warm build dos testes em ~12% e o de build incremental em ~22%.
Tempo no CI:
- Ambos gerenciadores (SPM e Carthage) apresentaram uma leve redução no tempo total de duração dos testes no CI, ~3.1% e ~4.6%, respectivamente.
Tamanho do Aplicativo:
- SPM — redução no tamanho do ZIP (~3.8%) e do tamanho do app instalado no device (~2.4%) para Testflight.
- Carthage — aumentou o tamanho do ZIP (~6.7%) e o tamanho do app instalado no device (~1.6%) para Testflight.
Essa redução no tamanho do binário final ao utilizar SPM também foi reportada em outros experimentos (What Adding Dependencies Will Do To Your App in 2020).
Outras Análises:
- Embora na maioria das medidas o Carthage tenha superado o SPM, como migramos um maior número de dependências para o Carthage do que para o SPM, essa diferença pode ter sido responsável por uma melhor performance do primeiro. Além disso, para usar o Carthage, devemos pré compilar as bibliotecas externas e alocá-las em um repositório próprio para que sejam baixadas conforme necessidade. Esse processo gera uma manutenção um pouco pesada, deixando a desejar se comparado ao processo fácil de integração via Pods/SPM.
- A comparação foi realizada com um número relativamente pequeno de dependências externas, deixando aberto uma margem de melhoria nas performances à medida que mais libs externas sejam migradas.
Nossa conclusão a partir deste levantamento é que a migração das dependências de Cocoapods para SPM irá resultar em uma série de benefícios ligados à performance de build e indexação, além de também reduzir o tamanho dos binários gerados nas versões de release.
Embora o Carthage também tenha demonstrado bons resultados, entendemos que sua aplicação necessitaria de muitos outros steps adicionais, elevando a complexidade e manutenção da plataforma. Além disso, pelo fato da própria Apple ser a detentora do Swift Package Manager, isso nos dá uma garantia de manutenção e eventuais melhorias no processo como é integrada a projetos nativos iOS. O Carthage também gera muita dor de cabeça para atualizar versões do Xcode e obriga que o time todo esteja sempre usando a mesma versão.
Por fim, vale destacar que a ferramenta usada atualmente para geração do projeto — Tuist — também oferece suporte ao SPM. Contando inclusive com um novo método para integração das dependências (atualmente em Alpha Version — Adding external dependencies | Tuist Documentation).
Esperamos que tenha curtido esse levantamento. Esses resultados são específicos para o nosso setup de projeto e isso não quer dizer que se repitam para outros projetos com diferentes configurações.
Caso tenha alguma dúvida, é só comentar.
Até a próxima pessoal.
Originalmente publicado no Medium
Este artigo foi publicado originalmente em 26 de abril de 2022. Esta versao no buildcomcarlos.com e a copia editorial integral mantida no meu site. Voce pode ler o original no Medium com formato original, claps e respostas.