আপনার বিল্ড প্রোফাইল করুন

বড় প্রোজেক্ট বা যেগুলি অনেক কাস্টম বিল্ড লজিক প্রয়োগ করে, সেগুলির ক্ষেত্রে বিল্ড প্রসেস আরও গভীরভাবে খতিয়ে দেখে সমস্যা খুঁজে বের করতে হতে পারে। বিল্ড লাইফসাইকেলের প্রতিটি পর্যায় এবং প্রতিটি বিল্ড টাস্ক সম্পূর্ণ করতে Gradle-এর কত সময় লাগে তা প্রোফাইল করে আপনি এটি করতে পারেন। যেমন, আপনার বিল্ড প্রোফাইল যদি দেখায় যে Gradle আপনার প্রোজেক্ট কনফিগার করতে অনেক বেশি সময় নিচ্ছে, তাহলে এটি সাজেস্ট করতে পারে যে আপনাকে কনফিগারেশন ফেজ থেকে কাস্টম বিল্ড লজিক সরাতে হবে। এছাড়াও, mergeDevDebugResources টাস্ক যদি বিল্ড টাইমের অনেকটা সময় নেয়, তাহলে বুঝতে হবে যে আপনাকে হয় ছবিগুলিকে WebP-তে কনভার্ট করতে হবে অথবা PNG ক্রাঞ্চিং বন্ধ করতে হবে।

আপনি Android Studio 4.0 বা তার পরবর্তী যেকোনও ভার্সন ব্যবহার করলে, বিল্ড পারফর্ম্যান্স সংক্রান্ত সমস্যা খতিয়ে দেখার সবচেয়ে ভালো উপায় হল বিল্ড অ্যানালাইজার ব্যবহার করা।

এছাড়াও, Android Studio-এর বাইরে আপনার বিল্ড প্রোফাইল করার জন্য দুটি বিকল্প আছে:

  1. স্ট্যান্ড-অ্যালোন gradle-profiler টুল, আপনার বিল্ডের গভীর বিশ্লেষণের জন্য একটি শক্তিশালী টুল।

  2. Gradle --profile বিকল্প, একটি সুবিধাজনক টুল যা Gradle কমান্ড লাইন থেকে উপলভ্য।

স্ট্যান্ডঅ্যালোন gradle-profiler টুল ব্যবহার করে

প্রোজেক্ট সেট-আপ খুঁজে পেতে, যা আপনাকে সেরা বিল্ড স্পিড প্রদান করে, আপনার Gradle প্রোফাইলার ব্যবহার করা উচিত, যা Gradle বিল্ডের জন্য প্রোফাইলিং এবং বেঞ্চমার্কিং তথ্য সংগ্রহ করার একটি টুল। Gradle প্রোফাইলার আপনাকে বিল্ড সিনারিও তৈরি করতে এবং সেগুলি একাধিকবার রান করতে দেয়, যার ফলে ফলাফলের মধ্যে উচ্চ বৈচিত্র্য রোধ করা যায় এবং ফলাফলের পুনরুৎপাদনযোগ্যতা নিশ্চিত করা যায়।

ক্লিন ও ইনক্রিমেন্টাল বিল্ড সম্পর্কে তথ্য সংগ্রহ করতে বেঞ্চমার্কিং মোড ব্যবহার করা উচিত, যদিও CPU স্ন্যাপশট সহ রান সম্পর্কে আরও বিস্তারিত তথ্য সংগ্রহ করতে প্রোফাইলিং মোড ব্যবহার করা যেতে পারে।

বেঞ্চমার্কিংয়ের জন্য প্রোজেক্ট সেট-আপ কনফিগারেশনের মধ্যে এগুলি অন্তর্ভুক্ত:

  • প্লাগ-ইন ভার্সন
  • Gradle ভার্সন
  • JVM সেটিংস (হিপ সাইজ, পার্মজেন সাইজ, গার্বেজ কালেকশন ইত্যাদি)
  • Gradle ওয়ার্কারের সংখ্যা (org.gradle.workers.max)
  • পারফর্ম্যান্স আরও অপ্টিমাইজ করার জন্য প্লাগ-ইন প্রতি বিকল্প

শুরু করা

  • এই নির্দেশাবলী অনুসরণ করে gradle-profiler ইনস্টল করুন
  • রান: gradle-profiler --benchmark --project-dir <root-project> :app:assembleDebug

এটি সম্পূর্ণ আপ-টু-ডেট বিল্ডের বেঞ্চমার্ক করবে কারণ --benchmark মাঝে প্রোজেক্ট পরিবর্তন না করেই একাধিকবার টাস্ক রান করে। তারপর এটি profile-out/ ডিরেক্টরির অধীনে একটি HTML রিপোর্ট তৈরি করবে যা আপনাকে বিল্ড টাইম দেখাবে।

অন্যান্য পরিস্থিতি আছে যা বেঞ্চমার্কের জন্য আরও উপযোগী হতে পারে:

  • আপনি যেখানে বেশিরভাগ কাজ করেন সেখানে কোনও ক্লাসের মেথড বডিতে কোড পরিবর্তন করা।
  • আপনার প্রোজেক্ট জুড়ে ব্যবহার করা হয় এমন মডিউলে API পরিবর্তন। আপনার নিজের কোডে পরিবর্তন করার চেয়ে কম ঘন ঘন হলেও, এর প্রভাব অনেক বেশি এবং এটি পরিমাপ করা উপযোগী।
  • UI-তে কাজ করার সময় বারবার চেষ্টা করার জন্য লেআউট এডিট করা।
  • অনুবাদ সংক্রান্ত কাজের সাথে ডিল করার জন্য স্ট্রিং এডিট।
  • বিল্ডে পরিবর্তন সিমুলেট করার জন্য ক্লিন বিল্ড (যেমন, Android Gradle প্লাগ-ইন আপডেট, Gradle আপডেট অথবা buildSrc-এর অধীনে আপনার নিজস্ব বিল্ড কোডে এডিট)।

এইসব ব্যবহারের ক্ষেত্রে বেঞ্চমার্ক করতে, আপনি এমন একটি পরিস্থিতি তৈরি করতে পারেন যা gradle-profiler এক্সিকিউশন চালাতে ব্যবহার করা হবে এবং যা আপনার সোর্সে উপযুক্ত পরিবর্তন প্রয়োগ করে। নিম্নলিখিত বিভাগে কিছু সাধারণ পরিস্থিতি বর্ণনা করা হয়েছে।

বিভিন্ন মেমরি/সিপিইউ সেটিংস প্রোফাইল করা

বিভিন্ন মেমরি ও CPU সেটিংসের বেঞ্চমার্ক করতে, আপনি একাধিক পরিস্থিতি তৈরি করতে পারেন যেখানে org.gradle.jvmargs-এর জন্য বিভিন্ন ভ্যালু ব্যবহার করা হয়। যেমন, আপনি পরিস্থিতি তৈরি করতে পারেন:

# <root-project>/scenarios.txt
clean_build_2gb_4workers {
    tasks = [":app:assembleDebug"]
    gradle-args = ["--max-workers=4"]
    jvm-args = ["-Xmx2048m"]
    cleanup-tasks = ["clean"]
}
clean_build_parallelGC {
    tasks = [":app:assembleDebug"]
    jvm-args = ["-XX:+UseParallelGC"]
    cleanup-tasks = ["clean"]
}

clean_build_G1GC_4gb {
    tasks = [":app:assembleDebug"]
    jvm-args = ["-Xmx4096m", "-XX:+UseG1GC"]
    cleanup-tasks = ["clean"]
}

gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt রান করলে তিনটি সিনারিও রান করবে এবং আপনি তুলনা করতে পারবেন যে এই প্রতিটি সেট-আপের জন্য :app:assembleDebug কত সময় নেয়।

বিভিন্ন Gradle প্লাগ-ইন ভার্সন প্রোফাইল করা

Gradle প্লাগ-ইনের ভার্সন পরিবর্তন করলে বিল্ড টাইমের উপর কী প্রভাব পড়ে তা জানতে, বেঞ্চমার্কিংয়ের জন্য একটি সিনারিও তৈরি করুন। This requires some preparation to make the plugin version injectable from the scenario. আপনার রুট build.gradle পরিবর্তন করুন:

# <root-project>/build.gradle
buildscript {
    def agpVersion = providers.systemProperty("agpVersion").forUseAtConfigurationTime().orNull ?: '4.1.0'

    ext.kotlin = providers.systemProperty('kotlinVersion').forUseAtConfigurationTime().orNull ?: '1.4.0'

    dependencies {
        classpath "com.android.tools.build:gradle:$agpVersion"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin"
    }
}

এখন আপনি সিনারিও ফাইল থেকে Android Gradle প্লাগ-ইন এবং Kotlin Gradle প্লাগ-ইন ভার্সন নির্দিষ্ট করতে পারবেন এবং সিনারিওতে সোর্স ফাইলে একটি নতুন পদ্ধতি যোগ করতে পারবেন:

# <root-project>/scenarios.txt
non_abi_change_agp4.1.0_kotlin1.4.10 {
    tasks = [":app:assembleDebug"]
    apply-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    System-properties {
      "agpVersion" = "4.1.0"
      "kotlinVersion" = "1.4.10"
}

non_abi_change_agp4.2.0_kotlin1.4.20 {
    tasks = [":app:assembleDebug"]
    apply-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    System-properties {
      "agpVersion" = "4.2.0-alpha16"
      "kotlinVersion" = "1.4.20"
}

ইনক্রিমেন্টাল বিল্ড প্রোফাইল করা হচ্ছে

বেশিরভাগ বিল্ড ইনক্রিমেন্টাল হয়, তাই এটি প্রোফাইল করার জন্য সবচেয়ে গুরুত্বপূর্ণ পরিস্থিতিগুলির মধ্যে একটি। Gradle প্রোফাইলার ইনক্রিমেন্টাল বিল্ড প্রোফাইলিং-এর জন্য ব্যাপক সহায়তা প্রদান করে। এটি কোনও মেথড বডি পরিবর্তন করে, নতুন মেথড যোগ করে অথবা লেআউট বা স্ট্রিং রিসোর্স পরিবর্তন করে অটোমেটিক সোর্স ফাইলে পরিবর্তন প্রয়োগ করতে পারে। যেমন, আপনি এই ধরনের ইনক্রিমেন্টাল সিনারিও তৈরি করতে পারেন:

# <root-project>/scenarios.txt
non_abi_change {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to = ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
}

abi_change {
    tasks = [":app:assembleDebug"]
    apply-abi-change-to = ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
}

layout_change {
    tasks = [":app:assembleDebug"]
    apply-android-layout-change-to = "app/src/main/res/your_layout_file.xml"
}
string_resource_change {
    tasks = [":app:assembleDebug"]
    apply-android-resource-value-change-to = "app/src/main/res/values/strings.xml"
}

gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt রান করলে বেঞ্চমার্কিং ডেটা সহ HTML রিপোর্ট তৈরি হবে।

আপনি ইনক্রিমেন্টাল সিনারিও অন্যান্য সেটিংসের সাথে একত্রিত করতে পারেন, যেমন হিপ সাইজ, কর্মীর সংখ্যা বা Gradle ভার্সন:

# <root-project>/scenarios.txt
non_abi_change_4g {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    jvm-args = ["-Xmx4096m"]
}

non_abi_change_4g_8workers {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    jvm-args = ["-Xmx4096m"]
    gradle-args = ["--max-workers=8"]
}

non_abi_change_3g_gradle67 {
    tasks = [":app:assembleDebug"]
    apply-non-abi-change-to ["app/src/main/java/com/example/your_app/your_code_file.java,
                              "app/src/main/java/com/example/your_app/your_code_file.kt"]
    jvm-args = ["-Xmx3072m"]
    version = ["6.7"]
}

ক্লিন বিল্ড প্রোফাইল করা হচ্ছে

ক্লিন বিল্ডের বেঞ্চমার্ক করতে, আপনি এমন একটি সিনারিও তৈরি করতে পারেন যা gradle-profiler এক্সিকিউশন ড্রাইভ করতে ব্যবহার করা হবে:

# <root-project>/scenarios.txt
clean_build {
    tasks = [":app:assembleDebug"]
    cleanup-tasks = ["clean"]
}

এই সিনারিও রান করতে, নিম্নলিখিত কমান্ড ব্যবহার করুন:

gradle-profiler --benchmark --project-dir <root-project> --scenario-file scenarios.txt

Gradle --profile বিকল্প ব্যবহার করা হচ্ছে

Gradle কমান্ড লাইন থেকে বিল্ড প্রোফাইল তৈরি করতে ও দেখতে, নিম্নলিখিত ধাপগুলি অনুসরণ করুন:

  1. আপনার প্রোজেক্টের রুটে কমান্ড-লাইন টার্মিনাল খুলুন।

  2. নিম্নলিখিত কমান্ড লিখে ক্লিন বিল্ড করুন। আপনার বিল্ড প্রোফাইল করার সময়, আপনার প্রোফাইল করা প্রতিটি বিল্ডের মধ্যে একটি ক্লিন বিল্ড পারফর্ম করা উচিত কারণ কোনও টাস্কের ইনপুট (যেমন সোর্স কোড) পরিবর্তন না হলে Gradle টাস্ক এড়িয়ে যায়। তাই, ইনপুট পরিবর্তন না করে দ্বিতীয়বার বিল্ড করলে তা সবসময় দ্রুত রান করে কারণ টাস্ক আবার রান করা হয় না। তাই আপনার বিল্ডের মধ্যে clean টাস্ক রান করলে, আপনি সম্পূর্ণ বিল্ড প্রসেস প্রোফাইল করতে পারবেন।

    // On Mac or Linux, run the Gradle wrapper using "./gradlew".
    gradlew clean
    
  3. আপনার প্রোডাক্ট ফ্লেভারের মধ্যে একটির ডিবাগ বিল্ড এক্সিকিউট করুন, যেমন "dev" ফ্লেভার, নিম্নলিখিত ফ্ল্যাগ সহ:

    gradlew --profile --offline --rerun-tasks assemble<var>Flavor</var>Debug
    
    • --profile: প্রোফাইলিং চালু করে।

    • --offline: অনলাইন ডিপেন্ডেন্সি ফেচ করা থেকে Gradle-কে বন্ধ করে। এটি নিশ্চিত করে যে Gradle আপনার ডিপেন্ডেন্সি আপডেট করার চেষ্টা করার কারণে কোনও বিলম্ব হলে তা আপনার প্রোফাইলিং ডেটাতে হস্তক্ষেপ করবে না। Gradle আপনার ডিপেন্ডেন্সি ডাউনলোড ও ক্যাশে করেছে কিনা তা নিশ্চিত করতে, আপনার প্রোজেক্ট আগে থেকেই তৈরি করে রাখতে হবে।

    • --rerun-tasks: Gradle-কে সব টাস্ক আবার রান করতে এবং টাস্ক অপ্টিমাইজেশন এড়িয়ে যেতে বাধ্য করে।

  4. বিল্ড সম্পূর্ণ হওয়ার পরে, প্রোজেক্ট উইন্ডো ব্যবহার করে project-root/build/reports/profile/ ডিরেক্টরিতে (ছবি ১-এ যেমন দেখানো হয়েছে) নেভিগেট করুন।

    Android Studio প্রোজেক্ট ভিউতে build/reports/profile-এর অধীনে জেনারেট করা HTML প্রোফাইল রিপোর্ট
      দেখাচ্ছে।
    ছবি ১. প্রোজেক্ট ভিউ থেকে প্রোফাইল রিপোর্টের লোকেশন সম্পর্কে জানা যায়।
  5. profile-timestamp.html ফাইলের উপর মাউস রেখে ডানদিকের বোতামে ক্লিক করুন এবং ব্রাউজারে খুলুন > ডিফল্ট বিকল্প বেছে নিন। রিপোর্টটি ছবি ২-এ দেখানো রিপোর্টের মতো দেখতে হবে। আপনার বিল্ড সম্পর্কে জানতে আপনি রিপোর্টের প্রতিটি ট্যাব পরীক্ষা করতে পারেন, যেমন টাস্ক এক্সিকিউশন ট্যাব যা দেখায় যে প্রতিটি বিল্ড টাস্ক এক্সিকিউট করতে Gradle কত সময় নিয়েছে।

    ব্রাউজারে প্রোফাইল রিপোর্ট তৈরি করুন যা ৪৬.৫৬৭ সেকেন্ডের বেসলাইন বিল্ড
      টাইম দেখায়।
    ছবি ২. ব্রাউজারে বিল্ড প্রোফাইল রিপোর্ট খোলে।
  6. ঐচ্ছিক: আপনার প্রোজেক্ট বা বিল্ড কনফিগারেশনে কোনও পরিবর্তন করার আগে, ৩ নম্বর ধাপের কমান্ডটি আবার চালান, তবে --rerun-tasks ফ্ল্যাগটি বাদ দিন। যেসব টাস্কের ইনপুট পরিবর্তন হয়নি সেগুলি আবার এক্সিকিউট না করে Gradle সময় বাঁচানোর চেষ্টা করে, তাই রিপোর্টের টাস্ক এক্সিকিউশন ট্যাবে অপরিবর্তিত টাস্কগুলিকে UP-TO-DATE হিসেবে চিহ্নিত করা হয়, যেমনটি চিত্র ৩-এ দেখানো হয়েছে। এটি আপনাকে কোন টাস্কগুলি কাজ করছে তা শনাক্ত করতে সাহায্য করে যখন সেগুলি করা উচিত নয়। যেমন, :app:processDevUniversalDebugManifest টাস্ক UP-TO-DATE হিসেবে চিহ্নিত না করা থাকলে, এটি ইঙ্গিত করতে পারে যে আপনার বিল্ড কনফিগারেশন প্রতিটি বিল্ডের সাথে ম্যানিফেস্টকে ডাইনামিকভাবে আপডেট করছে। তবে, প্রতিটি বিল্ডের সময় কিছু টাস্ক রান করতে হয়, যেমন :app:checkDevDebugManifest।

    বিল্ড প্রোফাইল রিপোর্টের টাস্ক এক্সিকিউশন ট্যাবে অ্যাপ টাস্ক দেখানো হচ্ছে
      যা আপ-টু-ডেট হিসেবে চিহ্নিত এবং মোট বিল্ড টাইম হল ০.২৮০ সেকেন্ড।
    ছবি ৩. টাস্ক এক্সিকিউশন ট্যাবে টাস্ক এক্সিকিউশনের ফলাফল দেখানো হয়।

এখন আপনার কাছে বিল্ড প্রোফাইল রিপোর্ট আছে, আপনি রিপোর্টের প্রতিটি ট্যাবে তথ্য পরীক্ষা করে অপ্টিমাইজেশনের সুযোগ খুঁজতে শুরু করতে পারেন। কিছু বিল্ড সেটিংসের জন্য পরীক্ষা-নিরীক্ষা প্রয়োজন কারণ প্রজেক্ট ও ওয়ার্কস্টেশনের মধ্যে সুবিধা আলাদা হতে পারে। যেমন, বড় কোডবেস সহ প্রোজেক্টের ক্ষেত্রে কোড সঙ্কুচিত করার সুবিধা পাওয়া যেতে পারে, যাতে অব্যবহৃত কোড সরিয়ে দেওয়া এবং অ্যাপের সাইজ ছোট করা যায়। তবে, ছোট প্রোজেক্টের ক্ষেত্রে কোড সঙ্কোচন সম্পূর্ণভাবে বন্ধ করে দিলে আরও সুবিধা হতে পারে। এছাড়াও, Gradle হিপ সাইজ ( org.gradle.jvmargs ব্যবহার করে) বাড়ালে তা কম মেমরির মেশিনে পারফর্ম্যান্সের উপর নেতিবাচক প্রভাব ফেলতে পারে।

আপনার বিল্ড কনফিগারেশনে পরিবর্তন করার পরে, পূর্ববর্তী ধাপগুলি পুনরাবৃত্তি করে এবং একটি নতুন বিল্ড প্রোফাইল তৈরি করে আপনার পরিবর্তনের ফলাফলগুলি পর্যবেক্ষণ করুন। যেমন, এই ডকুমেন্টে বর্ণিত কিছু প্রাথমিক অপ্টিমাইজেশন প্রয়োগ করার পরে একই স্যাম্পেল অ্যাপের জন্য রিপোর্ট ৪ নম্বর ছবিতে দেখানো হয়েছে।

বিল্ড প্রোফাইল রিপোর্টে ২৯.৬৬৮ সেকেন্ডের পোস্ট-অপ্টিমাইজেশন বিল্ড টাইম দেখানো হয়েছে,
      যা চিত্র ২-এ ৪৬.৫৬৭ সেকেন্ড থেকে কমেছে।
ছবি ৪. বিল্ড প্রোফাইল রিপোর্ট বিল্ড স্পিড অপ্টিমাইজ করার পরে আরও দ্রুত বিল্ড টাইম দেখায়।