Jumlah Metode yang Dirujuk Meningkat Setelah Modularisasi Aplikasi

16

AS: 3.5.3; Plugin Android Gradle: 3.5.0; Gradle: 5.6.2;

Kami mengamati peningkatan drastis dalam jumlah metode yang dirujuk dalam aplikasi kami setelah memecah modul 'aplikasi' menjadi beberapa modul kecil. Tetapi yang aneh adalah bahwa penambahan metode yang dirujuk oleh masing-masing kelas kurang dari total yang disebutkan di Android Apk Analyzer Tool.

Untuk tujuan pengujian, saya telah memindahkan WebActivity.class dari modul 'app' ke modul 'adapter' dan jumlah metode yang direferensikan meningkat sebanyak 181 metode.

Untuk meringkas:

app / WebActivity = 63546 Metode referensi aktual tetapi menunjukkan 65394 metode. adapter / WebActivity = 63543 Metode yang dirujuk aktual tetapi menunjukkan 65575 metode.

Kita punya mengamati 'penghitungan metode referensi' meningkat hampir 10k setelah menambahkan / membelah 4 modul baru.

Apa masalah sebenarnya?

Bagaimana modularisasi aplikasi dapat meningkatkan jumlah metode yang dirujuk secara drastis begitu tinggi?

Berikut ini adalah tangkapan layar yang saya ambil dari dua perbedaan yang berbeda-satunya APKs adalah WebActivity dipindahkan dari modul 'aplikasi' ke modul 'adaptor' dan 181 metode yang dirujuk meningkat:

WebActivity dalam modul 'aplikasi' masukkan deskripsi gambar di sini

Memindahkan modul WebActivity ke 'adaptor' masukkan deskripsi gambar di sini

Dalam tangkapan layar, mengapa penambahan metode yang dirujuk oleh masing-masing kelas (ditandai dengan warna merah) tidak sama dengan total yang diberikan dalam Apk Analyzer?

Rohit Surwase
sumber
Saya telah membuat masalah, Anda dapat melacaknya di sini issuetracker.google.com/issues/146957168
Rohit Surwase

Jawaban:

9

Saya sudah membaca tentang kinerja kode dan parameter penyetelan untuk waktu yang lama. Memang, program Android adalah salah satu fokus saya.

Mari kita intro pada awalnya konsep dasar atau paling penting yang membantu kita mencapai solusi.

Seperti yang dinyatakan Pengembang Android

modul dapat dibangun, diuji, dan disadap secara independen

Oleh karena itu, Modul memiliki Gradle & Dependensi mereka sendiri . Dan Anda dapat menjelajahinya dalam proyek Hierarchy Viewer.

Sebagai soal fakta, Modularisasi menekankan pada masalah Pemeliharaan . Berbeda dengan Performance Matters. Karena, Modularisasi memiliki dampak penting ini:

  • Meningkatkan Kedalaman pewarisan

Berikut adalah diagram yang saya plot untuk membuatnya jelas. Seperti yang Anda lihat. Ketika menggunakan modul diskrit, untuk memanggil Metode A ada 2N micro secsdibandingkan dengan N micro secstanpa modul diskrit.

masukkan deskripsi gambar di sini

Pertanyaan ini muncul di benak Anda bahwa Metode yang Dirujuk menghitung apa yang terkait dengan Kedalaman pewarisan?

Jawabannya adalah: Meskipun menggunakan modularisasi meningkatkan Metode yang Dirujuk. Tetapi, itu sebenarnya tidak mempengaruhi kinerja aplikasi dan masalah utama yang mungkin adalah Kedalaman pewarisan di mana dalam banyak kasus diabaikan. .

Saya menekankan bahwa peningkatan Metode yang Direferensikan dalam modularisasi disebabkan oleh masing-masing Tingkat Modul & Ketergantungan

Bagaimana modularisasi aplikasi dapat meningkatkan jumlah metode yang dirujuk secara drastis begitu tinggi?

Kondisi di mana dampak penganalisis APK penting Metode yang Dirujuk

Perhatikan juga bahwa minifikasi dan penyusutan kode masing-masing juga dapat secara signifikan mengubah isi file DEX setelah kode sumber dikompilasi.

Selain pernyataan resmi di atas, saya ingin menambahkan kondisi lain di mana penganalisa APK berdampak:

berapa banyak yang dialami pengembang dalam modularisasi?

modularisasi seperti rumah yang arsitektur (pengembang) menentukan di mana harus dapur dan di mana harus kamar kecil dan di mana harus WC. Bagaimana jika arsitektur memutuskan untuk menggabungkan WC & Kitchen?Ya ini bencana.

Ini dapat terjadi saat modularisasi jika pengembang tidak terlalu berpengalaman.


Menjawab pertanyaan OP di samping informasi tambahan

Di sini saya menjawab pertanyaan yang diajukan dalam komentar

Mengapa Gradle yang terpisah menambah jumlah metode yang dirujuk? Dan untuk dependensi terpisah, jika hasil akhirnya adalah APK tunggal maka saya tidak berpikir dependensi duplikat di 'app' dan modul fitur akan menambah jumlah metode yang direferensikan.

Karena modul dapat dibangun, diuji, dan di-debug maka mereka HARUS memiliki Gradle & Dependensi mereka sendiri.

Ketika proyek multi-modul sedang dipenuhi, kompiler menghasilkan beberapa .dexfile termasuk:

  • sebuah .dexfile untuk keseluruhan terintegrasi dependensi
  • modul .dexs

.dexFile dependensi adalah integrasi dari semua modul modul

Mari kita lihat bagaimana dampak bertahap modul modul Dirujuk Mothods Count ?!

ada 2 APK s dengan hasil yang sama tetapi perbedaan dalam penghitungan Metode yang Dirujuk.

Gambar 1 Gambar 2

Keduanya adalah aktivitas kosong yang memiliki 1.7kperbedaan dalam Jumlah Metode yang Dirujuk yang sangat tinggi tergantung pada fungsinya. Perbedaan utama mereka ada pada Gradle Modul mereka , salah satunya dikonfigurasikan

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

Satu lagi dikonfigurasi untuk

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

Meskipun mereka hanya kegiatan kosong tetapi perbedaan minimal di Gradle disebabkan 1.7k perbedaan dalam Jumlah Metode yang Dirujuk.

Dan App Gradle adalah

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')
}

Perhatian utama adalah mengapa penambahan jumlah metode yang dirujuk secara individual berbeda dari jumlah total metode yang direferensikan di Apk Analyzer?

Ini hanya tidak ada filter IDE. pasti, jika Anda hanya memilih .dexfile Metode Referensi Hitungan sama dengan SUM dari setiap baris Jumlah Metode yang Direferensikan tetapi jika Anda memilih banyak .dexfile, Anda akan melihat perbedaan dalam SUM dan Count aktual yang karena kesetaraan dalam Referensi yang disukai oleh Analyzer. saring mereka.

di tangkapan layar Anda, Anda telah memilih banyak .dexfile kemudian Analyzer menyaring kesetaraan.

dalam proyek kami, kami menggunakan file dependencies.gradle terpusat sehingga tidak ada peluang untuk versi yang berbeda. Jadi, apakah Anda berpikir bahkan jika kami memiliki set dependensi yang sama / tepat dan versinya dalam modul fitur, itu akan meningkatkan jumlah metode yang direferensikan?

Secara teoritis itu TIDAK harus meningkatkan jumlah metode yang dirujuk. NAMUN , Seperti yang saya jelaskan, Pengalaman Pengembang sangat memengaruhi hasil akhir.

Penganalisa Tim harus memeriksa dan memperbaiki masalah kinerja sebelum rilis seperti

  • aturan proguard
  • sumber daya menyusut & diperkecil
  • androidManifest.xml
  • pengaturan gradle

Sekarang saya ingin menjelaskan bagaimana Pengalaman Pengembang dan pemeliharaan kode mempengaruhi hasil akhir. BAHKAN jika APK Anda menggunakan Dependensi Terpusat

gambar 3

dalam contoh di atas, saya akan meningkat 5.1kdalam Metode yang Dirujuk Hitung BAHKAN JIKA saya telah Ketergantungan Terpusat !!!!!

Bagaimana mungkin ?

Jawabannya adalah: saya baru saja menambahkan file yang tidak berguna dan tersembunyi .jardalam libsdirektori proyek. semudah yang Anda lihat saya mempengaruhi hasil akhir.

Seperti yang Anda lihat Pengalaman Pengembang mempengaruhi result.as akhir Akibatnya, Praktis itu mungkin bahwa metode direferensikan jumlah ditingkatkan Meskipun teori Haruskah TIDAK .

Dan mengapa tidak ada perbedaan dalam penghitungan metode yang direferensikan ketika saya hanya mengkompilasi modul 'aplikasi' dengan menonaktifkan kompilasi paralel? Seharusnya berkurang karena hanya dependensi modul 'aplikasi' yang akan digunakan, kan?

kompilasi tidak ada kaitannya dengan metode yang dirujuk, dihitung. Itu sesuai dengan apa yang ingin dipatuhi pengembang.


Kesimpulan

Saya telah membahas semua kemungkinan seputar masalah ini. Memang, itu bisa muncul dari situasi yang berbeda dan pengembang dengan menggunakan pedoman ini dapat memperbaiki masalah ini.

  • Saya berharap Anda menemukan mengapa Metode yang Dirujuk ditingkatkan dan mengapa dalam beberapa kasus mungkin meningkat secara drastis.
  • Modul memiliki Gradle & Dependency dan modul peningkatan modularisasi mereka. oleh karena itu, Referensi Metode ini.
  • Modularisasi sebenarnya berdampak pada kinerja aplikasi yang diabaikan tetapi membuat pemeliharaan aplikasi Anda menjadi lebih baik.
  • Pengalaman pengembang dalam modularisasi juga sangat memengaruhi hasil akhir.

CATATAN PENTING: hampir semua pernyataan adalah investigasi & penelitian saya. memang, mungkin ada kesalahan dan kesalahan dan akan diperbarui untuk menambahkan lebih banyak informasi di masa depan.


Mr.AF
sumber
Terima kasih Mr.AF, saya berharap mendapatkan jawabannya setelah "Pertanyaan ini muncul di benak Anda bahwa Metode yang Dirujuk menghitung apa yang terkait dengan Kedalaman pewarisan? Jawabannya adalah," tetapi Anda tidak menjawabnya. Bisakah Anda jelaskan mengapa kedalaman warisan meningkatkan metode referensi? Seperti dalam kasus kami, kami belum menambahkan lapisan tambahan tetapi hanya membagi modul 'aplikasi'. Ada kemungkinan peningkatan dalam penghitungan metode yang dirujuk jika modul fitur mengakses metode modul fitur lain melalui modul 'app', apakah ini alasannya?
Rohit Surwase
@RohitSurwase jawaban adalah sisa pernyataan. Ketinggalan warisan tidak meningkatkan Referensi Metode, modularisasi melakukan itu dan modularisasi cuz Kedalaman pewarisan.
Mr.AF
@RohitSurwase, sebuah fitur yang mengakses fitur lain dalam modul lain sebenarnya tidak meningkatkan metode yang dirujuk. alasan utama peningkatan jumlah metode yang direferensikan adalah Gradle & Dependencies yang dibutuhkan setiap modul.
Mr.AF
@RohitSurwase Anda menunjukkan kiat-kiat bagus tentang hubungan modul ke modul. Faktanya, jika 2 modul memiliki terlalu banyak hubungan dan metode yang dirujuk maka mereka harus dikombinasikan untuk kinerja yang lebih baik. sebenarnya modul harus independen dalam hal & konsep.
Mr.AF
1
@RohitSurwase seperti yang saya saied, jar yang tidak terpakai mungkin bukan kasus Anda. Sesuatu yang saya maksud adalah pengalaman pengembang dan itu mungkin, kemungkinan dapat muncul dari sumber yang berbeda. dan saya mencantumkan semua sumber yang mungkin Anda perlu mencarinya
Mr.AF
2

Menjawab pertanyaan saya sendiri sebagai solusi yang baru saja diklik dalam pikiran saya, meskipun ini tidak dicoba tetapi akan berhasil, pasti atau paling mungkin. :) Jawaban yang diberikan oleh Mr.AF sangat berguna untuk mencapai solusi akhir. Ini berbicara tentang Mengapa? tetapi tidak bagaimana menghindarinya atau bagaimana memperbaikinya.

Berikut adalah cara untuk mendapatkan kembali jumlah metode referensi asli / aktual -

Itu tidak tergantung pada bagaimana kita membuat modular aplikasi tetapi pada bagaimana kita menambahkan dependensi. Jika kita menambahkan dependensi menggunakan ' implementasi ' maka dependensi itu tetap pribadi untuk modul dan tidak ada modul lain yang dapat menggunakannya. Dan jika kita menambahkan dependensi yang sama menggunakan ' api ' (sama dengan 'kompilasi' yang ditinggalkan) maka itu menjadi publik dan modul dependen lainnya dapat menggunakannya. Karena kami menggunakan 'implementasi' untuk menambahkan dependensi pada setiap modul dalam proyek multi-modul, setiap modul memiliki semua dependensi yang diperlukan sebagai mandiri, ini adalah alasan mengapa ia dapat dikompilasi secara individual. Ini menghasilkan penurunan waktu build / kompilasi karena hanya modul yang dimodifikasi yang dapat dikompilasi. Tapi, gunakan 'implementasi' meningkatkan jumlah metode yang dirujukkarena ada begitu banyak metode rujukan duplikat.

Jadi, jika waktu pembangunan bukan urusan Anda tetapi jumlah metode yang dirujuk adalah maka Anda dapat menggambar pohon dependensi dari semua modul dan menghindari menambahkan ketergantungan duplikat dengan menggunakan 'api' di modul dasar. Dengan cara ini, bahkan modul teratas dapat menggunakan dependensi yang ditambahkan oleh modul dasar yang akan menghindari duplikat. Ingat, ini akan menambah waktu pembuatan.

Kita dapat mencapai keduanya jika kita dapat membedakan dependensi untuk debug dan rilis build . Tambahkan semua dependensi menggunakan 'implementasi' untuk debug build dan tambahkan hanya dependensi yang diperlukan dan dioptimalkan untuk rilis build dengan menggunakan 'api' . Dengan cara ini debug build akan lebih cepat dan rilis build akan lebih lambat yang terjangkau.

Catatan: Saya akan memperbarui jawaban ini setelah saya mengetahui cara menyediakan dependensi terpisah untuk debug dan rilis build.

Rohit Surwase
sumber
Saya menyukainya. Bahan-bahan bagus.
Mr.AF
0

Saya melihat semua perbedaan dalam paket 'com' Anda. Anda dapat memperluas dan membandingkan kelas yang tepat yang menyusut. Jika Anda membangun dengan R8 terbaru, ia dapat menghapus beberapa kode secara default. Ketika Anda memasukkan beberapa kelas ke dalam modul shrinker, Anda tidak tahu apakah kelas / metode publik dapat dihapus atau harus tetap digunakan untuk modul lain. masukkan deskripsi gambar di sini

Dmitry Samoylenko
sumber
Ya saya memang mengembangkan dan memeriksa setiap paket termasuk 'com'. Perhatian utama adalah mengapa penambahan jumlah metode yang dirujuk secara individual berbeda dari jumlah total metode yang direferensikan di Apk Analyzer?
Rohit Surwase