Contagem de métodos referenciados aumentada após a modularização do aplicativo

16

AS: 3.5.3; Plug-in Android Gradle: 3.5.0; Gradle: 5.6.2;

Observamos um aumento drástico no número de métodos mencionados em nosso aplicativo após dividir o módulo 'app' em vários pequenos módulos. Mas o estranho é que a adição de métodos referenciados por cada classe é menor que o total mencionado no Android Apk Analyzer Tool.

Para fins de teste, mudei o WebActivity.class do módulo 'app' para o módulo 'adaptators' e a contagem de métodos referenciados aumentou em 181 métodos.

Para resumir:

app / WebActivity = 63546 Métodos reais referenciados, mas mostrando 65394 métodos. adapter / WebActivity = 63543 Métodos reais referenciados, mas mostrando 65575 métodos.

Temos observado 'contagem método referenciado' aumentou quase 10k após a adição / divisão 4 novos módulos.

Qual é o problema exato?

Como a modularização de aplicativos pode aumentar drasticamente a contagem de métodos referenciados?

A seguir, estão as capturas de tela que tirei de duas diferenças diferentes de apenas APKs: o WebActivity foi movido do módulo 'app' para o módulo 'adapter' e aumentaram os 181 métodos referenciados:

WebActivity no módulo 'app' insira a descrição da imagem aqui

Movido a WebActivity para o módulo 'adaptador' insira a descrição da imagem aqui

Nas capturas de tela, por que a adição de métodos referenciados por cada classe (marcada em vermelho) não é igual ao total fornecido no Apk Analyzer?

Rohit Surwase
fonte
Criei um problema, você pode acompanhá-lo aqui issuetracker.google.com/issues/146957168
Rohit Surwase

Respostas:

9

Estou lendo sobre o desempenho do código e os parâmetros de ajuste há muito tempo. Na verdade, os programas Android são um dos meus focos.

Vamos apresentar primeiro os conceitos básicos ou mais importantes nos quais nos ajudam a alcançar uma solução.

Como o desenvolvedor do Android declarou

O módulo pode ser construído, testado e depurado independentemente

Portanto, os módulos têm seu próprio Gradle & Dependencies . E você pode explorá-lo no projeto Hierarchy Viewer.

De fato, a ênfase da modularização em manutenção é importante. Ao contrário do Performance Matters, a modularização tem esse impacto importante:

  • Aumentar a profundidade da herança

Aqui está um diagrama que eu plotei para deixar claro. Como você pode ver, ao usar o módulo discreto, para invocar o Método A, ele é 2N micro secscomparado com o N micro secsmódulo discreto.

insira a descrição da imagem aqui

Esta questão me veio à sua mente que os métodos referenciados contam o que se refere à profundidade da herança?

A resposta é: Embora o uso da modularização aumente os Métodos referenciados, na verdade, ele não afeta o desempenho do aplicativo e o principal problema possível é Profundidade de herança, na qual na maioria dos casos é ignorável .

Eu enfatizo que o aumento de métodos referenciados na modularização é devido a cada módulo Gradle & Dependencies

Como a modularização de aplicativos pode aumentar drasticamente a contagem de métodos referenciados?

Condições em que o analisador de impacto APK é importante Métodos referenciados

Observe também que a redução e a redução do código também podem alterar consideravelmente o conteúdo de um arquivo DEX após a compilação do código-fonte.

Além da declaração oficial acima, quero adicionar outra condição na qual o analisador de impacto APK é:

quanto o desenvolvedor tem experiência em modularização?

a modularização é como uma casa que a arquitetura (desenvolvedor) define onde deve ser a cozinha e onde deve ser o banheiro e onde deve ser o banheiro. E se a arquitetura decidir combinar WC e cozinha? Sim, isso é um desastre.

Isso pode acontecer durante a modularização se o desenvolvedor não tiver muita experiência.


Respondendo às perguntas do OP, além de informações adicionais

Aqui eu respondo às perguntas mais frequentes nos comentários

Por que Gradle separado seria adicionado à contagem de métodos referenciados? E para dependências separadas, se o resultado final for um APK único, não creio que dependências duplicadas no 'app' e no módulo de recursos sejam adicionadas à contagem de métodos referenciados.

Como os módulos podem ser construídos, testados e depurados, DEVEM ter o seu próprio Gradle & Dependencies.

Enquanto o projeto de vários módulos estiver sendo cumprido, o compilador gera vários .dexarquivos, incluindo:

  • um .dexarquivo para dependências totalmente integradas
  • módulos .dexs

.dexarquivo de dependências é uma integração de todos os módulos gradles

Vejamos como um gradle de módulo afeta a contagem final de Mothods referenciados ?!

existem 2 APK s com o mesmo resultado, mas a diferença na contagem de métodos referenciados.

figura 1 Figura 2

Ambas são atividades vazias com 1.7kdiferença na Contagem de Métodos Referenciados muito alta, dependendo de sua funcionalidade. A principal diferença está no Gradle de seu módulo, um deles foi configurado para

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
}

Outro configurado para

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.2.0-alpha01'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
}

Embora sejam apenas atividades vazias, uma diferença mínima em Gradle causou 1.7kdiferença nas contagens de métodos referenciados.

E App Gradle é

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation project(path: ':module')
}

A principal preocupação é por que a adição da contagem de métodos referenciados individualmente é diferente da contagem total de métodos referenciados no Apk Analyzer?

Este é apenas o filtro IDE, nada mais. com certeza, se você selecionar apenas um .dexarquivo Contagens de método de referência é igual a SOMA de cada linha Contagens de métodos referenciados, mas se selecionar vários .dexarquivos, verá uma diferença em SUM e na contagem real devido à igualdade nas referências que o Analyzer preferiu filtrá-los.

nas capturas de tela, você selecionou vários .dexarquivos e, em seguida, o Analyzer filtra a igualdade.

em nosso projeto, estamos usando o arquivo dependencies.gradle centralizado, para que não haja chance de versão diferente. Então, você acha que, mesmo que tenhamos o mesmo / exato conjunto de dependências e suas versões nos módulos de recursos, isso aumentará a contagem de métodos referenciados?

Teoricamente, NÃO deve aumentar a contagem de métodos referenciados. MAS , como expliquei, a Experiência do desenvolvedor afeta fortemente o resultado final.

O Team Analyzer deve verificar e corrigir problemas de desempenho antes do lançamento, como

  • regras de proguard
  • recursos reduzidos e diminuídos
  • androidManifest.xml
  • configurações gradle

Agora, quero esclarecer como a Experiência do desenvolvedor e a manutenção do código afetam o resultado final. MESMO se o seu APK usar dependências centralizadas

Figura 3

no exemplo acima, eu aumentei a 5.1kcontagem de métodos referenciados, mesmo que eu tivesse dependências centralizadas !!!!!

Como é possível ?

A resposta é: acabei de adicionar um .jararquivo inútil e oculto no libsdiretório do projeto. tão fácil quanto você pode ver, eu afetei o resultado final.

Como você pode ver Desenvolvedor Experiência afeta result.as finais resultado, Praticamente é possível que métodos referenciados contagens de ser aumentado Embora Teoricamente Should NÃO .

E por que não há diferença na contagem de métodos referenciados quando eu compilo apenas o módulo 'app' desativando a compilação paralela? Deveria ter diminuído, pois apenas as dependências do módulo 'app' teriam sido usadas, certo?

compilação não tem nenhuma relação com os métodos referenciados count.it está de acordo com o que o desenvolvedor deseja cumprir.


Conclusão

Eu cobri todas as possibilidades em torno da questão. De fato, pode surgir de diferentes situações e um desenvolvedor, usando essa diretriz, pode corrigir o problema.

  • Eu espero que você descubra por que os métodos referenciados foram aumentados e por que, em alguns casos, pode ser drasticamente aumentado.
  • Módulos possui seus módulos Gradle & Dependencies e aumento de modularização. portanto, essas referências de método.
  • A modularização realmente afeta o desempenho do aplicativo ignorável, mas torna a manutenção do aplicativo muito melhor.
  • A experiência do desenvolvedor em modularização também afeta muito o resultado final.

NOTA IMPORTANTE: quase todas as declarações são de minha investigação e pesquisa. de fato, pode haver erros e falhas e será atualizado para adicionar muito mais informações no futuro.


Mr.AF
fonte
Obrigado Mr.AF, eu esperava obter a resposta depois de "Esta pergunta me veio à mente que os métodos referenciados contam o que está relacionado à profundidade da herança? A resposta é", mas você não respondeu. Você pode explicar por que a profundidade da herança aumenta a contagem de métodos referenciados? Como no nosso caso, não adicionamos nenhuma camada extra, apenas dividimos o módulo 'app'. Há uma chance de aumento na contagem de métodos referenciados, caso um módulo de recurso acesse métodos de outro módulo de recurso através do módulo 'app', é esse o motivo?
Rohit Surwase
A resposta do @RohitSurwase é o restante da declaração. A profundidade da herança não aumenta as referências de método, a modularização fazendo isso e a modularização porque a profundidade da herança.
Mr.AF
@RohitSurwase, um recurso que acessa outro recurso em outro módulo, na verdade, não aumenta a contagem de métodos referenciados. a principal razão para aumentar a contagem de métodos referenciados é Gradle & Dependencies, que cada módulo precisa.
Mr.AF
@RohitSurwase você aponta boas dicas sobre a relação módulo a módulo. de fato, se 2 módulos tiver muitas relações e métodos referenciados, eles deverão ser combinados para obter melhor desempenho. Na verdade, o módulo precisa ser independente em termos e conceitos.
Mr.AF
11
@RohitSurwase como eu disse, o jar não utilizado pode não ser o seu caso. Algo que eu quero dizer é experiência do desenvolvedor e é possível, a possibilidade pode surgir de diferentes fontes. e listei todas as fontes possíveis que você precisa pesquisar
Mr.AF
2

Respondendo à minha própria pergunta, a solução acabou de aparecer em minha mente, embora isso não seja tentado, mas funcionaria, definitivamente ou muito provavelmente. :) A resposta dada por Mr.AF foi muito útil para chegar a uma solução final. Ele fala sobre o porquê? mas não como evitá-lo ou como melhorar isso.

Aqui está uma maneira de recuperar a contagem de métodos referenciados original / real -

Não depende de como modularizamos o aplicativo, mas de como adicionamos dependências. Se adicionarmos uma dependência usando ' implementação ', essa dependência permanecerá privada no módulo e nenhum outro módulo poderá usá-lo. E se adicionarmos a mesma dependência usando ' api ' (igual a 'compilação' obsoleta), ela se tornará pública e outros módulos dependentes poderão usá-la. Como estamos usando 'implementação' para adicionar dependências em cada módulo em um projeto de vários módulos, cada módulo possui todas as dependências necessárias como independentes, e é por isso que ele pode ser compilado individualmente. Isso resulta em menor tempo de compilação / compilação, pois apenas módulos modificados podem ser compilados. Mas, o uso de 'implementação' aumenta a contagem de métodos referenciados pois existem muitos métodos referenciados duplicados.

Portanto, se o tempo de construção não é da sua conta, mas a contagem de métodos referenciados é possível, você pode desenhar a árvore de dependências de todos os módulos e evitar adicionar dependência duplicada usando 'api' no módulo base. Dessa forma, mesmo o módulo superior pode usar a dependência adicionada pelo módulo base, o que evitará duplicatas. Lembre-se de que isso aumentaria o tempo de construção.

Podemos alcançar ambos se pudermos distinguir dependências para depuração e versão de compilação . Adicione todas as dependências usando 'implementação' para compilação de depuração e adicione apenas dependências necessárias e otimizadas para compilação de versão usando 'api' . Dessa forma, a compilação de depuração será mais rápida e a compilação de versão será mais lenta e acessível.

Nota: Eu atualizaria esta resposta assim que descobrir como fornecer dependências separadas para depuração e versão de compilação.

Rohit Surwase
fonte
Eu gostei. bons materiais.
Mr.AF 28/01
0

Eu vejo toda a diferença no seu pacote 'com'. Você pode expandir e comparar quais classes exatas foram reduzidas. Se você criar com o R8 mais recente, poderá remover algum código por padrão. Quando você coloca algumas classes no encolhedor de módulos, não sabe se as classes / métodos públicos podem ser removidos ou devem permanecer para uso em outro módulo. insira a descrição da imagem aqui

Dmitry Samoylenko
fonte
Sim, eu expandi e verifiquei cada pacote, incluindo 'com'. A principal preocupação é por que a adição da contagem de métodos referenciada individualmente é diferente da contagem total de métodos referenciados no Apk Analyzer?
Rohit Surwase