Количество ссылочных методов увеличилось после модуляции приложения

16

AS: 3,5,3; Плагин Android Gradle: 3.5.0; Gradle: 5.6.2;

Мы наблюдали резкое увеличение числа методов, на которые ссылается наше приложение, после разделения модуля app на несколько небольших модулей. Но странно то, что добавление ссылочных методов каждым классом меньше, чем упомянутое общее количество в Android Apk Analyzer Tool.

В целях тестирования я переместил WebActivity.class из модуля «приложение» в модуль «адаптеры», и число ссылок на методы увеличилось на 181 метод.

Обобщить:

app / WebActivity = 63546 Фактические методы, на которые ссылаются, но показывающие 65394 метода. adapter / WebActivity = 63543 фактические методы, на которые имеются ссылки, но показывающие 65575 методов.

Мы наблюдали, как количество добавленных методов увеличилось почти на 10 тыс. После добавления / разделения 4 новых модулей.

Какова точная проблема?

Каким образом модульность приложения может так сильно увеличить количество ссылочных методов?

Ниже приведены скриншоты, которые я сделал для двух разных различий в APK-файлах: WebActivity перемещена из модуля «приложение» в модуль «адаптер» и увеличено 181 упоминание методов:

WebActivity в модуле «приложение» введите описание изображения здесь

Перенес WebActivity в модуль «адаптер» введите описание изображения здесь

На скриншотах, почему добавление ссылочных методов каждым классом (отмечено красным цветом) не равно общему количеству, указанному в Apk Analyzer?

Рохит Сурвасе
источник
Я создал проблему, вы можете отследить ее здесь issetracker.google.com/issues/146957168
Rohit Surwase

Ответы:

9

Я давно читаю о производительности кода и настройке параметров. На самом деле, программы Android - одна из моих задач.

Давайте сначала познакомимся с основными или наиболее важными концепциями, в которых мы можем найти решение.

Как заявил разработчик Android

модуль может быть независимо собран, протестирован и отлажен

Поэтому модули имеют свои собственные Gradle & Dependencies. И вы можете изучить их в проекте Hierarchy Viewer.

На самом деле, упор на модульность делает упор на техническое обслуживание . В отличие от Performance Matters. Потому что модульность имеет такое важное влияние:

  • Увеличение глубины наследования

Вот диаграмма, которую я сделал, чтобы прояснить это. Как вы можете видеть, при использовании дискретного модуля, для вызова метода A проводится 2N micro secsсравнение с использованием N micro secsбез дискретного модуля.

введите описание изображения здесь

Этот вопрос мне приходит в голову, что Referenced Methods считает то, что связано с глубиной наследования?

Ответ таков: хотя использование модульности увеличивает Referenced Methods.but, но на самом деле это не влияет на производительность приложения, и основной возможной проблемой является глубина наследования, при которой в большинстве случаев игнорируется .

Я подчеркиваю, что увеличение ссылочных методов в модульности связано с каждым модулем Gradle & Dependencies

Каким образом модульность приложения может так сильно увеличить количество ссылочных методов?

Условия, в которых влияют APK анализатор важно ссылки методы

Также обратите внимание, что минификация и сжатие кода могут также значительно изменить содержимое файла DEX после компиляции исходного кода.

В дополнение к приведенному выше официальному заявлению, я хочу добавить еще одно условие, в котором анализатор воздействия APK это:

Насколько опытен разработчик в модульности?

Модульность подобна дому, в котором архитектура (разработчик) определяет, где должна быть кухня, а где должна быть комната отдыха, а где должен быть туалет. Что если архитектура решит объединить WC и Kitchen? Да, это катастрофа.

Это может произойти во время модульности, если разработчик не очень опытен.


Ответы на вопросы ОП в дополнение к дополнительной информации

Здесь я отвечу на оп заданные вопросы в комментариях

Зачем отдельному Gradle добавлять к количеству ссылочных методов? И для отдельной зависимости, если конечный результат - один APK, то я не думаю, что дублированные зависимости в «app» и модуле функций добавят к количеству ссылочных методов.

Поскольку модули могут быть собраны, протестированы и отлажены, они ДОЛЖНЫ иметь свои собственные Gradle & Dependencies.

Пока выполняется многомодульный проект, компилятор генерирует несколько .dexфайлов, в том числе:

  • .dexфайл для общих интегрированных зависимостей
  • модули .dexs

зависимости .dexФайл представляет собой объединение всех модулей Gradles.

Давайте посмотрим, как модуль Gradle влияет на окончательный счетчик ссылочных Mothods ?!

Есть 2 APK с одинаковым результатом, но разница в счетчиках ссылочных методов.

фигура 1 фигура 2

Они оба являются пустыми действиями, у которых 1.7kразница в количестве ссылок на методы, которая очень высока, зависит от их функциональности. Ключевая разница заключается в том, что на модуле Gradle один из них был настроен на

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

Еще один настроен на

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

Хотя они - просто пустые действия, но минимальная разница в Gradle вызвала 1.7k разницу в счетчиках ссылочных методов.

И приложение 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')
}

Основная проблема заключается в том, почему добавление индивидуально ссылочного количества методов отличается от общего количества ссылочных методов в Apk Analyzer?

Это просто фильтр IDE больше ничего. наверняка, если вы выберете только .dexфайл, то Reference Reference Counts равен SUM для каждой строки Referenced Method Count, но если вы выбрали несколько.dex файлов, вы увидите разницу в SUM и фактическом Count, что из-за равенства в ссылках, которые предпочитал Analyzer отфильтровать их.

на ваших скриншотах вы выбрали несколько .dex файлов, а затем анализатор равенства фильтров.

В нашем проекте мы используем централизованный файл dependencies.gradle, поэтому нет шансов на другую версию. Итак, как вы думаете, даже если у нас будет одинаковый / точный набор зависимостей и их версий в функциональных модулях, это увеличит количество ссылочных методов?

Теоретически это НЕ должно увеличивать количество ссылочных методов. НО , как я уже объяснил, опыт разработчика сильно влияет на конечный результат.

Team Analyzer должен проверять и исправлять проблемы с производительностью до выпуска, как

  • правила защиты
  • сокращенные и минимизированные ресурсы
  • AndroidManifest.xml
  • настройки gradle

Теперь я хочу уточнить, как опыт разработчика и сопровождение кода влияют на конечный результат. ДАЖЕ, если ваш APK использует централизованные зависимости

рисунок 3

в приведенном выше примере я увеличил количество 5.1kссылок на методы, даже если бы у меня были централизованные зависимости !!!!!

Как это возможно?

Ответ: я только что добавил бесполезный и скрытый .jarфайл вlibs директорию проекта. так же легко, как вы можете видеть, я повлиял на конечный результат.

Как вы можете видеть опыт разработчика влияет на окончательный result.as результат, практически возможно , что упомянутые методы рассчитывают увеличить Хотя Теоретически РЕКОМЕНДУЕМЫЙ НЕ .

И почему нет разницы в количестве ссылок на методы, когда я компилирую только модуль 'app', отключив параллельную компиляцию? Он должен был уменьшиться, поскольку использовались бы только зависимости модуля «app», верно?

компиляция не имеет никакого отношения к ссылочным методам countts.it соответствует требованиям разработчика.


Вывод

Я рассмотрел все возможности вокруг проблемы. Действительно, это может быть вызвано различными ситуациями, и разработчик, используя это руководство, может решить эту проблему.

  • Я надеюсь, что вы узнали, почему ссылочные методы были увеличены и почему в некоторых случаях они могут быть резко увеличены.
  • Модули имеют свои модули Gradle & Dependencies и увеличения модульности. следовательно, эти ссылки на метод.
  • Модуляризация на самом деле влияет на производительность приложения, но делает обслуживание вашего приложения намного лучше.
  • Опыт разработчика в модульности также сильно влияет на конечный результат.

ВАЖНОЕ ПРИМЕЧАНИЕ: почти все утверждения являются моими исследованиями. действительно, могут быть ошибки и сбои, и они будут обновлены, чтобы добавить гораздо больше информации в будущем.


Mr.AF
источник
Спасибо, г-н А.Ф., я надеялся получить ответ после того, как «Вам приходит в голову, что подсчитанные методы относятся к тому, что относится к глубине наследования? Ответ есть», но вы не ответили на это. Не могли бы вы пояснить, почему глубина наследования увеличивает количество ссылочных методов? Как и в нашем случае, мы не добавили никакого дополнительного слоя, а просто разбили модуль 'app'. Существует вероятность увеличения количества ссылочных методов в случае, если функциональный модуль обращается к методам другого функционального модуля через модуль 'app', это причина?
Rohit Surwase
Ответ @RohitSurwase - остальная часть утверждения. Глубина наследования не увеличивает ссылки на методы, это делает модульность и модульность, потому что глубина наследования.
А.Ф.
@RohitSurwase, функция, обращающаяся к другой функции в другом модуле, фактически не увеличивает количество ссылочных методов. основной причиной увеличения количества ссылок на методы является Gradle & Dependencies, в котором нуждается каждый модуль.
А.Ф.
@RohitSurwase вы указываете хорошие советы о связи модуля с модулем. на самом деле, если 2 модуля имеют слишком много связей и методов, на которые ссылаются, то их следует объединить для лучшей производительности. на самом деле модуль должен быть независимым в терминах и понятиях.
А.Ф.
1
@ RohitSurwase, как я уже говорил, неиспользованная банка может не подходить для вас. Что-то, что я имею в виду, это опыт разработчика, и возможно, что такая возможность может быть получена из разных источников. и я перечислил все возможные источники, которые вам нужны для поиска
Mr.AF
2

Отвечая на мой собственный вопрос, как решение просто щелкнуло в моей голове, хотя это не пробовал, но будет работать, определенно или наиболее вероятно. :) Ответ, данный Mr.AF был очень полезен для достижения окончательного решения. Это говорит о том, почему? но не как этого избежать или как улучшить это.

Вот способ вернуть счетчик исходных / фактических ссылок на метод -

Это зависит не от того, как мы модулируем приложение, а от того, как мы добавляем зависимости. Если мы добавим зависимость, используя « реализацию », то эта зависимость останется закрытой для модуля, и никакой другой модуль не сможет ее использовать. И если мы добавим ту же зависимость, используя ' api ' (равнозначен устаревшей 'compile'), она станет общедоступной, и другие зависимые модули смогут ее использовать. Поскольку мы используем «реализацию» для добавления зависимостей в каждый модуль в многомодульном проекте, каждый модуль имеет все необходимые зависимости как автономные, поэтому его можно скомпилировать по отдельности. Это приводит к уменьшению времени сборки / компиляции, поскольку могут быть скомпилированы только измененные модули. Но использование так 'реализации' увеличивает количество ссылочных методовтак как есть много повторяющихся методов.

Таким образом, если время сборки не является вашим вопросом, а количество методов, на которые ссылаются, то вы можете нарисовать дерево зависимостей всех модулей и избежать добавления дублирующихся зависимостей, используя 'api' в базовом модуле. Таким образом, даже верхний модуль может использовать зависимости, добавленные базовым модулем, что позволит избежать дублирования. Помните, это увеличит время сборки.

Мы можем достичь и того, и другого, если сможем различать зависимости для отладки и сборки выпуска . Добавьте все зависимости, используя «реализацию» для отладочной сборки, и добавьте только обязательные и оптимизированные зависимости для сборки выпуска с помощью «api» . Таким образом, отладочная сборка будет быстрее, а сборка выпуска будет медленнее, что доступно.

Примечание. Я бы обновил этот ответ, как только выясню, как предоставить отдельные зависимости для отладки и сборки выпуска.

Рохит Сурвасе
источник
Мне понравилось. Хорошие материалы.
Mr.AF
0

Я вижу всю разницу в вашем 'ком' пакете. Вы можете расширить и сравнить, какие именно классы были сокращены. Если вы используете последнюю версию R8, она может удалить некоторый код по умолчанию. Когда вы помещаете некоторые классы в модуль сжатия, не знаете, могут ли публичные классы / методы быть удалены или должны оставаться для использования в другом модуле. введите описание изображения здесь

Дмитрий Самойленко
источник
Да, я развернул и проверил каждый пакет, включая «com». Основная проблема заключается в том, почему добавление индивидуально ссылочного количества методов отличается от общего количества ссылочных методов в Apk Analyzer?
Rohit Surwase