سرعت ساخت خود را بهینه کنید

زمان ساخت طولانی روند توسعه شما را کند می کند. این صفحه تکنیک هایی را برای کمک به رفع تنگناهای ایجاد سرعت ارائه می دهد.

روند کلی بهبود سرعت ساخت اپلیکیشن به شرح زیر است:

  1. با انجام چند مرحله که فوراً به نفع اکثر پروژه های Android Studio است ، پیکربندی ساخت خود را بهینه کنید .
  2. برای شناسایی و تشخیص برخی از تنگناهای پیچیده‌تر که ممکن است مختص پروژه یا ایستگاه کاری شما باشد، ساخت خود را نمایه کنید .

هنگام توسعه برنامه خود، در صورت امکان روی دستگاهی با Android نسخه 7.0 (سطح API 24) یا بالاتر نصب کنید. نسخه‌های جدیدتر پلت‌فرم Android، مکانیزم‌های بهتری را برای ارسال به‌روزرسانی‌ها به برنامه‌تان اجرا می‌کنند، مانند Android Runtime (ART) و پشتیبانی بومی از چندین فایل DEX .

توجه: پس از اولین ساخت تمیز، ممکن است متوجه شوید که ساخت‌های بعدی، چه تمیز و چه تدریجی، حتی بدون استفاده از هیچ یک از بهینه‌سازی‌های توضیح داده شده در این صفحه، بسیار سریع‌تر عمل می‌کنند. این به این دلیل است که دیمون Gradle یک دوره "گرم کردن" افزایش عملکرد دارد - مشابه سایر فرآیندهای JVM.

پیکربندی ساخت خود را بهینه کنید

برای بهبود سرعت ساخت پروژه Android Studio خود، این نکات را دنبال کنید.

ابزارهای خود را به روز نگه دارید

ابزارهای اندروید تقریباً با هر به روز رسانی بهینه سازی ساخت و ویژگی های جدید را دریافت می کنند. برخی نکات در این صفحه فرض می‌کنند که از آخرین نسخه استفاده می‌کنید. برای بهره مندی از آخرین بهینه سازی ها، موارد زیر را به روز نگه دارید:

به جای kapt از KSP استفاده کنید

ابزار پردازش حاشیه نویسی Kotlin (kapt) به طور قابل توجهی کندتر از پردازشگر نماد Kotlin (KSP) است. اگر منبع Kotlin مشروح می نویسید و از ابزاری استفاده می کنید که حاشیه نویسی ها را پردازش می کند (مانند اتاق ) که از KSP پشتیبانی می کند، باید به KSP مهاجرت کنید .

از جمع آوری منابع غیر ضروری خودداری کنید

از جمع‌آوری و بسته‌بندی منابعی که آزمایش نمی‌کنید، مانند محلی‌سازی زبان اضافی و منابع با چگالی صفحه، خودداری کنید. در عوض، همانطور که در نمونه زیر نشان داده شده است، فقط یک منبع زبان و تراکم صفحه نمایش را برای طعم "dev" خود مشخص کنید:

شیار

android {
    ...
    productFlavors {
        dev {
            ...
            // The following configuration limits the "dev" flavor to using
            // English stringresources and xxhdpi screen-density resources.
            resourceConfigurations "en", "xxhdpi"
        }
        ...
    }
}

کاتلین

android {
    ...
    productFlavors {
        create("dev") {
            ...
            // The following configuration limits the "dev" flavor to using
            // English stringresources and xxhdpi screen-density resources.
            resourceConfigurations("en", "xxhdpi")
        }
        ...
    }
}

آخرین بار قرار دادن پلاگین Gradle را آزمایش کنید

در اندروید، تمامی پلاگین ها در مخازن google() و mavenCentral() یافت می شوند. با این حال، ساخت شما ممکن است به پلاگین های شخص ثالث نیاز داشته باشد که با استفاده از سرویس gradlePluginPortal() حل شوند.

Gradle مخازن را به ترتیبی که اعلام شده اند جستجو می کند، بنابراین اگر مخازن فهرست شده در ابتدا شامل بیشتر افزونه ها باشند، عملکرد ساخت بهبود می یابد. بنابراین، ورودی gradlePluginPortal() با قرار دادن آخرین آن در بلوک مخزن در فایل settings.gradle خود آزمایش کنید. در بیشتر موارد، این تعداد جستجوهای اضافی افزونه را به حداقل می رساند و سرعت ساخت شما را بهبود می بخشد.

برای اطلاعات بیشتر در مورد نحوه حرکت Gradle در چندین مخزن، به اعلام چندین مخزن در مستندات Gradle مراجعه کنید.

از مقادیر پیکربندی ساخت استاتیک با ساخت اشکال زدایی خود استفاده کنید

همیشه برای ویژگی هایی که در فایل مانیفست یا فایل های منبع برای نوع ساخت اشکال زدایی شما قرار می گیرند، از مقادیر استاتیک استفاده کنید.

استفاده از کدهای نسخه پویا، نام نسخه، منابع، یا هر منطق ساخت دیگری که فایل مانیفست را تغییر می‌دهد، هر بار که می‌خواهید تغییری را اجرا کنید، نیاز به ساخت کامل برنامه دارد، حتی اگر تغییر واقعی ممکن است در غیر این صورت فقط به یک تعویض داغ نیاز داشته باشد. اگر پیکربندی ساخت شما به چنین ویژگی‌های پویایی نیاز دارد، آن‌گونه که در نمونه زیر نشان داده شده است، آن ویژگی‌ها را در انواع نسخه‌های ساخت خود جدا کنید و مقادیر را برای ساخت‌های اشکال‌زدایی ثابت نگه دارید:

  ...
  // Use a filter to apply onVariants() to a subset of the variants.
  onVariants(selector().withBuildType("release")) { variant ->
      // Because an app module can have multiple outputs when using multi-APK, versionCode
      // is only available on the variant output.
      // Gather the output when we are in single mode and there is no multi-APK.
      val mainOutput = variant.outputs.single { it.outputType == OutputType.SINGLE }

      // Create the version code generating task.
      val versionCodeTask = project.tasks.register("computeVersionCodeFor${variant.name}", VersionCodeTask::class.java) {
          it.outputFile.set(project.layout.buildDirectory.file("versionCode${variant.name}.txt"))
      }

      // Wire the version code from the task output.
      // map will create a lazy Provider that:
      // 1. Runs just before the consumer(s), ensuring that the producer (VersionCodeTask) has run
      //    and therefore the file is created.
      // 2. Contains task dependency information so that the consumer(s) run after the producer.
      mainOutput.versionCode.set(versionCodeTask.flatMap { it.outputFile.map { it.asFile.readText().toInt() } })
  }
  ...

  abstract class VersionCodeTask : DefaultTask() {

    @get:OutputFile
    abstract val outputFile: RegularFileProperty

    @TaskAction
    fun action() {
        outputFile.get().asFile.writeText("1.1.1")
    }
  }

دستور setVersionsFromTask را در GitHub ببینید تا نحوه تنظیم کد نسخه پویا در پروژه خود را بیاموزید.

از نسخه های وابستگی استاتیک استفاده کنید

وقتی وابستگی‌ها را در فایل‌های build.gradle خود اعلام می‌کنید، از استفاده از شماره‌های نسخه پویا (آنهایی که در پایان علامت مثبت دارند، مانند 'com.android.tools.build:gradle:2.+' ) خودداری کنید. استفاده از شماره‌های نسخه پویا می‌تواند باعث به‌روزرسانی‌های غیرمنتظره نسخه، مشکل در حل تفاوت‌های نسخه‌ها و ساخت‌های کندتر ناشی از بررسی Gradle برای به‌روزرسانی شود. به جای آن از اعداد نسخه ثابت استفاده کنید.

ایجاد ماژول های کتابخانه

به دنبال کدی در برنامه خود بگردید که بتوانید آن را به ماژول کتابخانه اندروید تبدیل کنید. ماژولار کردن کد خود به این روش به سیستم ساخت اجازه می‌دهد فقط ماژول‌هایی را که شما اصلاح می‌کنید کامپایل کند و آن خروجی‌ها را برای ساخت‌های آینده ذخیره کند. زمانی که بهینه سازی را فعال می کنید، مدولارسازی اجرای پروژه موازی را موثرتر می کند.

ایجاد وظایف برای منطق ساخت سفارشی

پس از ایجاد نمایه ساخت ، اگر نمایه ساخت نشان می‌دهد که بخش نسبتاً طولانی از زمان ساخت در مرحله **پیکربندی پروژه‌ها** سپری شده است، اسکریپت‌های build.gradle خود را بررسی کنید و به دنبال کدی باشید که در یک کار سفارشی Gradle گنجانده شود. . با انتقال مقداری از منطق ساخت به یک کار، به شما کمک می‌کنید تا مطمئن شوید که وظیفه فقط در صورت لزوم اجرا می‌شود، نتایج را می‌توان برای ساخت‌های بعدی ذخیره کرد، و اگر اجرای پروژه موازی را فعال کنید، منطق ساخت برای اجرای موازی واجد شرایط می‌شود. برای کسب اطلاعات بیشتر درباره تیک‌ها برای منطق ساخت سفارشی، اسناد رسمی Gradle را بخوانید.

نکته: اگر ساخت شما شامل تعداد زیادی کار سفارشی است، ممکن است بخواهید فایل های build.gradle خود را با ایجاد کلاس های وظیفه سفارشی شلوغ کنید. کلاس های خود را به پوشه project-root /buildSrc/src/main/groovy/ اضافه کنید. Gradle به طور خودکار آن کلاس ها را در مسیر کلاس برای همه فایل های build.gradle در پروژه شما شامل می شود.

تبدیل تصاویر به WebP

WebP یک فرمت فایل تصویری است که فشرده سازی با اتلاف (مانند JPEG) و همچنین شفافیت (مانند PNG) را فراهم می کند. WebP می تواند فشرده سازی بهتری نسبت به JPEG یا PNG ارائه دهد.

کاهش اندازه فایل های تصویری بدون نیاز به فشرده سازی در زمان ساخت می تواند سرعت ساخت شما را افزایش دهد، به خصوص اگر برنامه شما از منابع تصویر زیادی استفاده کند. با این حال، ممکن است در هنگام فشرده سازی تصاویر WebP، افزایش اندکی در استفاده از CPU دستگاه مشاهده کنید. از Android Studio برای تبدیل آسان تصاویر خود به WebP استفاده کنید.

Crunching PNG را غیرفعال کنید

اگر تصاویر PNG خود را به WebP تبدیل نمی کنید، همچنان می توانید با غیرفعال کردن فشرده سازی خودکار تصویر هر بار که برنامه خود را می سازید، سرعت ساخت خود را افزایش دهید.

اگر از افزونه Android Gradle نسخه 3.0.0 یا بالاتر استفاده می‌کنید، Crunching PNG به طور پیش‌فرض برای نوع ساخت «اشکال‌زدایی» غیرفعال است. برای غیرفعال کردن این بهینه سازی برای سایر انواع ساخت، موارد زیر را به فایل build.gradle خود اضافه کنید:

شیار

android {
    buildTypes {
        release {
            // Disables PNG crunching for the "release" build type.
            crunchPngs false
        }
    }
}

کاتلین

android {
    buildTypes {
        getByName("release") {
            // Disables PNG crunching for the "release" build type.
            isCrunchPngs = false
        }
    }
}

از آنجایی که انواع ساخت یا طعم‌های محصول این ویژگی را تعریف نمی‌کنند، باید هنگام ساختن نسخه انتشار برنامه خود، این ویژگی را به صورت دستی روی true تنظیم کنید.

با جمع کننده زباله موازی JVM آزمایش کنید

عملکرد ساخت را می توان با پیکربندی بهینه جمع آوری زباله JVM که توسط Gradle استفاده می شود، بهبود بخشید. در حالی که JDK 8 به طور پیش‌فرض برای استفاده از زباله‌گیر موازی پیکربندی شده است، JDK 9 و بالاتر برای استفاده از زباله‌گیر G1 پیکربندی شده است.

برای بهبود بالقوه عملکرد ساخت، توصیه می‌کنیم ساخت‌های Gradle خود را با جمع‌کننده زباله موازی آزمایش کنید . در gradle.properties موارد زیر را تنظیم کنید:

org.gradle.jvmargs=-XX:+UseParallelGC

اگر گزینه های دیگری از قبل در این قسمت تنظیم شده است، یک گزینه جدید اضافه کنید:

org.gradle.jvmargs=-Xmx1536m -XX:+UseParallelGC

برای اندازه‌گیری سرعت ساخت با پیکربندی‌های مختلف، به نمایه ساخت خود مراجعه کنید.

اندازه پشته JVM را افزایش دهید

اگر ساخت‌های آهسته را مشاهده می‌کنید، و به ویژه جمع‌آوری زباله بیش از 15 درصد از زمان ساخت را در نتایج Build Analyzer شما می‌گیرد، باید اندازه پشته ماشین مجازی جاوا (JVM) را افزایش دهید. در فایل gradle.properties ، محدودیت را روی 4، 6 یا 8 گیگابایت تنظیم کنید، همانطور که در مثال زیر نشان داده شده است:

org.gradle.jvmargs=-Xmx6g

سپس برای بهبود سرعت ساخت تست کنید. ساده ترین راه برای تعیین اندازه بهینه هیپ این است که حد را به مقدار کمی افزایش دهید و سپس برای بهبود سرعت ساخت کافی آزمایش کنید.

اگر از جمع‌آوری زباله موازی JVM نیز استفاده می‌کنید، کل خط باید به شکل زیر باشد:

org.gradle.jvmargs=-Xmx6g -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g

با روشن کردن پرچم HeapDumpOnOutOfMemoryError می توانید خطاهای حافظه JVM را تجزیه و تحلیل کنید. با انجام این کار، JVM هنگامی که حافظه تمام می شود، یک heap dump ایجاد می کند.

از کلاس های R غیر گذرا استفاده کنید

از کلاس‌های R غیر گذرا برای داشتن ساخت‌های سریع‌تر برای برنامه‌های دارای چندین ماژول استفاده کنید. انجام این کار با حصول اطمینان از اینکه کلاس R هر ماژول فقط حاوی ارجاعاتی به منابع خود بدون خارج کردن ارجاعات از وابستگی هایش باشد، به جلوگیری از تکرار منابع کمک می کند. این منجر به ساخت سریعتر و مزایای مربوط به اجتناب از کامپایل می شود. این رفتار پیش‌فرض در افزونه Android Gradle نسخه 8.0.0 و بالاتر است.

با شروع Android Studio Bumblebee، کلاس‌های R غیر گذرا به‌طور پیش‌فرض برای پروژه‌های جدید روشن هستند. برای پروژه‌هایی که با نسخه‌های قبلی Android Studio ایجاد شده‌اند، با رفتن به Refactor > Migrate to Non-Transitive R Classs، آن‌ها را به‌روزرسانی کنید تا از کلاس‌های R غیر گذرا R کنند.

برای کسب اطلاعات بیشتر در مورد منابع برنامه و کلاس R ، به نمای کلی منابع برنامه مراجعه کنید.

از کلاس های R غیر ثابت استفاده کنید

از فیلدهای کلاس R غیر ثابت در برنامه‌ها و آزمایش‌ها استفاده کنید تا افزایش تدریجی کامپایل جاوا را بهبود ببخشید و امکان کاهش دقیق‌تر منابع را فراهم کنید. فیلدهای کلاس R همیشه برای کتابخانه‌ها ثابت نیستند، زیرا هنگام بسته‌بندی APK برای برنامه یا آزمایشی که به آن کتابخانه بستگی دارد، منابع شماره‌گذاری می‌شوند. این رفتار پیش‌فرض در پلاگین Android Gradle نسخه 8.0.0 و بالاتر است.

پرچم Jetifier را غیرفعال کنید

از آنجایی که بیشتر پروژه‌ها مستقیماً از کتابخانه‌های AndroidX استفاده می‌کنند، می‌توانید پرچم Jetifier را برای عملکرد ساخت بهتر حذف کنید. برای حذف پرچم Jetifier، android.enableJetifier=false را در فایل gradle.properties خود تنظیم کنید.

Build Analyzer می‌تواند بررسی کند که آیا پرچم را می‌توان با خیال راحت حذف کرد تا پروژه شما عملکرد ساخت بهتری داشته باشد و از کتابخانه‌های پشتیبانی‌نشده Android خارج شود. برای کسب اطلاعات بیشتر درباره Build Analyzer، به عیب‌یابی عملکرد ساخت مراجعه کنید.

از کش پیکربندی استفاده کنید

حافظه پنهان پیکربندی به Gradle اجازه می‌دهد اطلاعات مربوط به نمودار وظایف ساخت را ثبت کند و در ساخت‌های بعدی مجدداً از آن استفاده کند، بنابراین Gradle نیازی به پیکربندی مجدد کل بیلد ندارد.

برای فعال کردن کش پیکربندی، مراحل زیر را دنبال کنید:

  1. بررسی کنید که همه پلاگین های پروژه سازگار هستند.

    از Build Analyzer برای بررسی اینکه آیا پروژه شما با کش پیکربندی سازگار است یا خیر استفاده کنید. Build Analyzer دنباله‌ای از ساخت‌های آزمایشی را اجرا می‌کند تا مشخص کند آیا می‌توان این ویژگی را برای پروژه روشن کرد یا خیر. برای فهرستی از افزونه‌هایی که پشتیبانی می‌شوند ، شماره 13490 را ببینید.

  2. کد زیر را به فایل gradle.properties اضافه کنید:

      org.gradle.configuration-cache=true
      # Use this flag carefully, in case some of the plugins are not fully compatible.
      org.gradle.configuration-cache.problems=warn

وقتی حافظه پنهان پیکربندی فعال است، اولین باری که پروژه خود را اجرا می‌کنید، خروجی ساخت می‌گوید Calculating task graph as no configuration cache is available for tasks . در طول اجراهای بعدی، خروجی ساخت می گوید Reusing configuration cache .

برای کسب اطلاعات بیشتر در مورد حافظه پنهان پیکربندی، به پست وبلاگ Configuration cacheing deep dive و مستندات Gradle در مورد کش پیکربندی مراجعه کنید.

مشکلات مربوط به کش پیکربندی در Gradle 8.1 و Android Gradle Plugin 8.1 معرفی شده است.

کش پیکربندی در Gradle 8.1 پایدار شد و ردیابی API فایل را معرفی کرد. فراخوان هایی مانند File.exists() ، File.isDirectory() و File.list() توسط Gradle ضبط می شوند تا فایل های ورودی پیکربندی را ردیابی کنند.

افزونه Android Gradle (AGP) 8.1 از این APIهای File برای برخی از فایل‌ها استفاده می‌کند که Gradle نباید آن‌ها را به عنوان ورودی حافظه پنهان در نظر بگیرد. هنگامی که با Gradle 8.1 و بالاتر استفاده می‌شود، باطل کردن حافظه پنهان اضافی ایجاد می‌شود و عملکرد ساخت را کاهش می‌دهد. موارد زیر در AGP 8.1 به عنوان ورودی حافظه پنهان در نظر گرفته می شوند:

ورودی ردیاب مشکل ثابت در
$GRADLE_USER_HOME/android/FakeDependency.jar شماره ۲۸۹۲۳۲۰۵۴ AGP 8.2
خروجی cmake شماره ۲۸۷۶۷۶۰۷۷ AGP 8.2
$GRADLE_USER_HOME/.android/analytics.settings شماره ۲۷۸۷۶۷۳۲۸ AGP 8.3

اگر از این APIها یا افزونه‌هایی استفاده می‌کنید که از این APIها استفاده می‌کند، ممکن است در زمان ساخت خود دچار رگرسیون شوید، زیرا برخی از منطق ساخت با استفاده از این APIها می‌توانند باعث عدم اعتبار کش اضافی شوند. لطفاً برای بحث در مورد این الگوها و نحوه اصلاح منطق ساخت ، به بهبودها در ردیابی ورودی پیکربندی ساخت نگاه کنید، یا به طور موقت ردیابی API فایل را غیرفعال کنید.