Artigo

Integracao de Dependencias iOS no LuizaLabs

Estudo comparativo entre Cocoapods, Swift Package Manager e Carthage no projeto SuperApp do LuizaLabs: tempo de build, indexacao, testes, tamanho do app e impacto no CI Bitrise.

Publicado originalmente em 26 de abril de 2022. ~7 min de leitura.

by Carlos Henriquecanvas

By: Carlos Henrique, Gabriel Beltrame, Rafael Valer

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

Launch Time entre as duas versões se mostra praticamente igual. (N=5)
  • 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

Geração do Projeto
  • 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.

Sobre esta versao

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.