アプリのモジュール化後に参照されるメソッドの数が増える


16

AS:3.5.3; Android Gradleプラグイン:3.5.0; Gradle:5.6.2;

「app」モジュールをいくつかの小さなモジュールに分割した後、アプリで参照されるメソッドの数が大幅に増加することがわかりました。しかし奇妙なことに、各クラスによる参照メソッドの追加は、Android Apkアナライザツールで述べた合計よりも少ないということです。

テストのために、WebActivity.classを「app」モジュールから「adapters」モジュールに移動し、参照されるメソッドの数を181メソッド増やしました。

要約する:

app / WebActivity = 63546実際の参照メソッドですが、65394メソッドが表示されてます。adapter / WebActivity = 63543実際の参照メソッドですが、65575メソッドを表示しています。

4つの新しいモジュールを追加または分割した後、「参照されるメソッドの数」がほぼ10k増加したことが確認されています。

正確な問題は何ですか?

アプリのモジュール化によって、参照されるメソッドの数が大幅に増加する方法を教えてください。

以下は、私が撮った2つの異なるAPKのみのスクリーンショットです。WebActivityが「app」モジュールから「adapter」モジュールに移動し、181の参照メソッドが増加しています。

「app」モジュールのWebActivity ここに画像の説明を入力してください

WebActivityを「アダプター」モジュールに移動 ここに画像の説明を入力してください

スクリーンショットで、各クラスによる参照メソッドの追加(赤色でマーク)が、Apkアナライザーで与えられた合計と等しくないのはなぜですか?


問題を作成しました。ここで追跡できますissuetracker.google.com/issues/146957168
Rohit Surwase

回答:


9

私はコードのパフォーマンスとパラメーターの調整について長い間読んでいます。確かに、Androidプログラムは私の焦点の1つです。

最初に、ソリューションの実現に役立つ基本的または最も重要な概念を紹介しましょう。

Androidの開発者は述べています

モジュールは個別に構築、テスト、デバッグできます

したがって、モジュールには独自のGradle&Dependenciesがあり、プロジェクトでそれを探索できますHierarchy Viewer

実際のところ、モジュール化ではメンテナンスが重要視されます。Performance Mattersとは異なり、モジュール化には次の重要な影響があります。

  • 継承の深さを増やす

これは、明確にするためにプロットした図です。ご覧のとおり、ディスクリートモジュールを使用しているときに、メソッドAを呼び出すために、ディスクリートモジュール2N micro secsN micro secsない場合と比較しています。

ここに画像の説明を入力してください

この質問は、参照メソッドが継承の深さに関連するものを数えることをあなたに思い浮かびますか?

答えは次のとおりです。モジュール化を使用するとReferenced Methods.butが増加しますが、実際にはアプリのパフォーマンスに影響はなく、主な問題は、ほとんどの場合無視できる継承の深さです

モジュール化における参照メソッドの増加は、各モジュールのGradleと依存関係によるものであることを強調します

アプリのモジュール化によって、参照されるメソッドの数が大幅に増加する方法を教えてください。

APKアナライザーに重要な参照メソッドに影響を与える条件

また、ソースコードがコンパイルされた後、縮小とコードの縮小はそれぞれDEXファイルの内容を大幅に変更する可能性があることにも注意してください。

上記の公式ステートメントに加えて、次のようなAPKアナライザーに影響を与える別の条件を追加したいと思います。

開発者はモジュール化でどれくらいの経験がありますか?

モジュール化は、建築(開発者)がどこにキッチン、どこにトイレ、どこにトイレがあるかを定義する家のようなものです。 建築物がトイレとキッチンを組み合わせることに決めた場合はどうなりますか?ええ、これは災害です。

これは、開発者があまり経験がない場合、モジュール化中に発生する可能性があります。


追加情報に加えて、OPの質問への回答

ここでコメントのopの質問に答えます

分離したGradleが参照されるメソッド数に追加されるのはなぜですか?個別の依存関係の場合、最終結果が単一のAPKである場合、「アプリ」での依存関係の重複は考えられず、機能モジュールが参照されるメソッドの数に追加することになります。

モジュールはビルド、テスト、デバッグできるため、独自のGradleとDependencyが必要です。

マルチモジュールプロジェクトがコンパイルされている間、コンパイラは.dex以下を含むいくつかのファイルを生成します。

  • .dex総統合の依存関係のためのファイル
  • モジュール.dexs

依存関係.dexファイルはすべてのモジュールgradleの統合です

モジュールグラドルが最終的な参照方法数にどのように影響するか見てみましょう。

同じ結果の2つ APKのs がありますが、参照されるメソッドの数が異なります。

図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違いが参照メソッド数の違いを引き起こしました。

そして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')
}

主な懸念は、個別に参照されるメソッド数の追加が、Apkアナライザーでの参照されるメソッド総数と異なるのはなぜですか?

これはIDEフィルターであり、他には何もありません。確かに、.dexファイルのみを選択した場合、参照メソッド数は各行の参照されたメソッド数の合計に等しくなり.dexますが、ファイルを複数選択した場合、SUMと実際の数に違いが見られます。それらをフィルタリングします。

スクリーンショットで、複数の.dexファイルを選択してから、Analyzerフィルターの等価性を選択しました。

このプロジェクトでは、一元化されたdependency.gradleファイルを使用しているため、バージョンが異なる可能性はありません。それで、機能モジュールに依存関係とそのバージョンの同じ/正確なセットがある場合でも、参照されるメソッドの数が増えると思いますか?

理論的には、参照されるメソッドの数が増えることはありませんしかし、私はそれを説明したように、開発者の経験、高度に影響を与える最終的な結果。

Team Analyzerは、リリース前にパフォーマンスの問題をチェックして修正する必要があります

  • プロガードルール
  • 縮小されたリソース
  • androidManifest.xml
  • グラドル設定

次に、開発者エクスペリエンスとコード保守が最終結果にどのように影響するかを明確にしたいと思います。APKが一元化された依存関係を使用している場合でも

図3

上記の例では、i'vは増加5.1k数参照先のメソッドでEVEN IF私が持っていたの集中の依存関係を !!!!!

どのように可能ですか?

答えは:プロジェクトのディレクトリに役に立たない隠し.jarファイルを追加したところlibsです。あなたが見ることができるのと同じくらい簡単に、私は最終結果に影響を与えました。

ご覧のように、開発者エクスペリエンスは最終結果に影響します。その結果、実際には、参照されたメソッドは増加する可能性がありますが、理論的にはそうではありません

また、並列コンパイルを無効にして「app」モジュールのみをコンパイルしても、参照されるメソッドの数に違いがないのはなぜですか?'app'モジュールの依存関係のみが使用されていたので、減少しているはずですよね?

コンパイルは、参照されるメソッドcounts.itとは何の関係もありません。開発者がコンパイルしたいものに準拠しています。


結論

私は問題の周りのすべての可能性をカバーしました。実際、さまざまな状況から発生する可能性があり、このガイドラインを使用することで開発者は問題を修正できます。

  • 参照メソッドが増加した理由と、場合によっては大幅に増加した理由を見つけていただければ幸いです。
  • モジュールには、Gradle&Dependenciesとモジュール化増加モジュールがあります。したがって、これらのメソッド参照。
  • モジュール化は、実際には無視できるほどのアプリのパフォーマンスに影響を与えますが、アプリのメンテナンスを大幅に改善します。
  • モジュール化における開発者の経験も、最終結果に大きな影響を与えます。

重要な注意:ほとんどすべての記述は私の調査および研究です。実際、エラーや障害が発生する可能性があり、今後さらに多くの情報を追加するために更新されます。



AFさん、ありがとうございました。「この質問では、参照されたメソッドは継承の深さに関連するものを数えるという疑問が浮かびましたか?答えはです」と答えたが、あなたは答えなかった。継承の深さが参照メソッド数を増やす理由について詳しく説明していただけますか?私たちの場合と同様に、追加のレイヤーは追加していませんが、「app」モジュールを分割しています。機能モジュールが「app」モジュールを介して別の機能モジュールのメソッドにアクセスする場合、参照されるメソッドの数が増える可能性がありますが、これは理由ですか?
Rohit Surwase

@RohitSurwaseの答えはステートメントの残りです。継承の深さはメソッド参照を増加させません、モジュール化とそのモジュール化cuz継承の深さ。
AF氏

@RohitSurwase、別のモジュールの別の機能にアクセスする機能は、実際には参照されるメソッドの数を大幅に増やしません。参照されるメソッド数が増える主な理由は、各モジュールに必要なGradleとDependenciesです。
Mr.AF

@RohitSurwaseあなたはモジュール間の関係に関する良いヒントを指摘します。実際問題として、2つのモジュールのリレーションと参照メソッドが多すぎる場合は、パフォーマンスを向上させるためにそれらを組み合わせる必要があります。実際には、モジュールは用語と概念が独立している必要があります。
AF氏

1
@RohitSurwaseが言ったように、未使用のjarはあなたのケースではないかもしれません。つまり、私が意味するのは開発者の経験であり、それは可能です。可能性はさまざまなソースから浮かび上がる可能性があります。そして、私はあなたがそれを検索する必要があるすべての可能な情報源をリストしました
Mr.AF

2

ソリューションが私の心の中でクリックしただけで、自分の質問に答えますが、これは試されていませんが、間違いなくまたはおそらくは機能します。:) AF氏回答は、最終的な解決策を見つけるのに非常に役立ちました。それはなぜですか?しかし、それを回避する方法やそれを改善する方法はありません。

これは、元の/実際の参照メソッド数を戻す方法です -

アプリをモジュール化する方法に依存するのではなく、依存関係を追加する方法に依存します。「実装」を使用して依存関係を追加すると、その依存関係はモジュールに対して非公開のままとなり、他のモジュールはそれを使用できなくなります。そして、 ' api '(非推奨の 'compile'と同じ)を使用して同じ依存関係を追加すると、パブリックになり、他の依存モジュールがそれを使用できます。マルチモジュールプロジェクトの各モジュールに依存関係を追加するために「実装」を使用しているため、各モジュールには必要な依存関係がすべて自己完結型としてあり、これが個別にコンパイルできる理由です。これにより、変更されたモジュールのみをコンパイルできるため、ビルド/コンパイル時間が短縮されます。ただし、「実装」を使用すると、参照されるメソッドの数が増えます 重複した参照メソッドが非常に多いため。

したがって、ビルド時間が問題ではないが、参照されるメソッド数が問題である場合は、すべてのモジュールの依存関係ツリーを描画し、基本モジュールで「api」を使用することにより、重複する依存関係の追加回避できます。このようにして、最上位モジュールでさえ、基本モジュールによって追加された依存関係を使用して、重複を回避できます。これにより、ビルド時間が長くなることに注意してください。

デバッグとリリースビルドの依存関係を区別できれば、両方達成できます。デバッグビルドに'implementation'を使用してすべての依存関係を追加し、 'api'を使用してリリースビルドに必要で最適化された依存関係のみを追加します。この方法では、デバッグビルドが高速になり、リリースビルドが低速になります。

注:デバッグとリリースビルドに個別の依存関係を提供する方法を見つけたら、この回答を更新します。


私はそれが好きだった。良い材料。
Mr.AF

0

あなたの「com」パッケージのすべての違いがわかります。縮小されたクラスを正確に比較できます。最新のR8でビルドする場合、デフォルトで一部のコードを削除できます。一部のクラスをモジュール縮小プログラムに入れるとき、パブリッククラス/メソッドを削除できるかどうか、または別のモジュールで使用するためにとどまる必要があるかどうかはわかりません。 ここに画像の説明を入力してください


はい、「com」を含む各パッケージを展開して確認しました。主な懸念は、個別に参照されるメソッド数の追加が、Apkアナライザーでの合計参照メソッド数と異なるのはなぜですか?
Rohit Surwase
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.