Integração de Dependências iOS no LuizaLabs

Carlos Carmo
luizalabs
Published in
7 min readApr 26, 2022
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% utilizando Carthage.
    - Redução média no tempo de Incremental Build em ~12% utilizando Carthage.

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 em comparação ao Cocoapods.
    - Carthage aumentou em ~6.7% o tamanho do ZIP gerado em comparação ao Cocoapods.
    - Carthage aumentou em ~1.6% o tamanho do app instalado em devices em comparação ao Cocoapods.

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 — Obteve um aumento no tempo de geração do projeto, tanto cold como warm, ~61.2% e ~5.4%, respectivamente. No entanto, 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 tempo de cold indexing.

Compilação do Projeto:

  • SPM — Apresentou redução nos tempos de cold build e incremental build, ~47% e ~5%, respectivamente. Tempo para warm build inconclusivo.
  • Carthage — Apresentou 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%. Assim como o tempo de warm build dos teste em ~3%, e o de build incremental em ~14%.
  • Carthage — Reduziu o tempo da lane de testes em ~8.7%. Assim como o tempo de warm build dos teste 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 temanho 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 reportado em outros experimentos(What Adding Dependencies Will Do To Your App in 2020).

Outras Análises:

  • Embora na maioria das medidas extraídas 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 que possamos usar o Carthage, devemos pré compilar as bibliotecas externas e alocá-las em um repositório próprio para que seja baixada 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, isso deixa aberto uma margem de melhoria nas performances extraídas a medida que um maior número de 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 a 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 à 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 e atualize sempre junto.

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 (atulamente 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 os resultados vão se repetir para outros projetos com diferentes configurações.

Caso tenha alguma dúvida, é só comentar ;] .

Até a próxima pessoal.

--

--

Carlos Carmo
luizalabs

Tech Lead | Staff Engineer | iOS Specialist | iOS Teacher | Android | Platform Teams | Cocoaheads Co-organizer | Speaker in Meetups and Confs