Cold Start — این چرخه کامل راهاندازی برنامه Android است که از وضعیت صفر شروع میشود، زمانی که فرایند برنامه در حافظه وجود ندارد و Activity ایجاد نشده است. سیستم یک فرایند جدید ایجاد میکند، کلاسها را بارگذاری میکند، Application را مقداردهی میکند، Activity ایجاد میکند و اولین رندر را انجام میدهد. به گزارش Google, 2024، راهاندازی سرد در دستگاههای رده متوسط میتواند از 1 تا 5 ثانیه طول بکشد و هر 100 میلیثانیه تاخیر احتمال حفظ کاربر را 3% کاهش میدهد.
نکات کلیدی
Cold Start (راهاندازی سرد) — سناریویی است که در آن برنامه Android از ابتداییترین وضعیت راه اندازی میشود: سیستم عامل یک فرایند جدید ایجاد میکند (fork از Zygote)، حافظه اختصاص میدهد، کد DEX را در ART بارگذاری میکند، کلاسها را مقداردهی میکند و نمونه Application و سپس اولین Activity را ایجاد میکند. قبل از شروع برنامه، هیچ دادهای درباره آن در حافظه دستگاه وجود ندارد، جز تصاویر کش شده کلاسها اگر Background Dexopt استفاده شود.
راهاندازی سرد در سه مورد رخ میدهد: در اولین راهاندازی پس از نصب برنامه، در راهاندازی پس از راهاندازی مجدد دستگاه، و در راهاندازی پس از آن که سیستم فرایند را به دلیل کمبود حافظه تخلیه کرد. در دستگاههای با 2–4 گیگابایت RAM، سیستم فرایندهای پسزمینه را بسیار فعال تخلیه میکند، بنابراین Cold Start میتواند در هر بازگشت به برنامه پس از چند ساعت بیفعالی اتفاق بیفتد. در Android 12+، سیستم میتواند فرایند یخ زده (freeze / cached) را حفظ کند، اما در صرفهجویی فعال حافظه (OOM-killer)، فرایند نابود خواهد شد.
به گزارش Google (Find My Device report, 2023)، 65% کاربران برنامه را میبندند اگر طی 3 ثانیه باز نشود. برای شبکههای اجتماعی و پیامرسانها، که کاربر دهها بار در روز برمیگردد، Cold Start مستقیماً بر retention تأثیر میگذارد. در Google Play Console، متریک Cold Start در بخش Android Vitals قرار دارد و به عنوان یکی از شاخصهای ANR و عملکرد نمایش داده میشود. برنامهای که از حد Cold Start «بد» (بیش از 5 ثانیه در 25% دستگاهها) تجاوز کند، در کنسول هشدار دریافت میکند و ممکن است در جستجو کاهش رتبه داشته باشد.
Android سه نوع راهاندازی برنامه را تشخیص میدهد، که هر کدام مدت زمان، تأثیر بر UX و رویکردهای بهینهسازی متفاوتی دارد. درک تفاوت برای انتخاب راهبرد مناسب پروفایلینگ ضروری است.
| نوع راهاندازی | وضعیت فرایند | Application.onCreate | زمان معمولی |
|---|---|---|---|
| Cold | بدون فرایند | اجرا میشود | 1–5 ثانیه |
| Warm | فرایند وجود دارد، Activity وجود ندارد | اجرا نمیشود | 200–600 ms |
| Hot | فرایند + Activity در حافظه | اجرا نمیشود | < 200 ms |
Warm Start زمانی اتفاق میافتد که فرایند برنامه از قبل در پسزمینه وجود داشته باشد، اما Activity نابود شده است (مثلاً، کاربر پس از مکث طولانی برگشته و سیستم حافظه Activity را آزاد کرده است). Hot Start — زمانی که کاربر برنامه را کوچک کرده و فوراً دوباره باز کند: Activity متوقف شده و بازیابی حداقل زمان را میطلبد. برای کاربر، Cold Start قابل توجهترین نوع راهاندازی است و دقیقاً بهینهسازی آن بیشترین افزایش را در UX ایجاد میکند.
Cold Start میتواند به Warm Start تبدیل شود پس از آن که برنامه حداقل یک بار راه اندازی شد — ART تصاویر کامپایل شده کلاسها (Image in Boot Profile) را کش میکند و بارگذاری مجدد DEX سریعتر انجام میشود. بنابراین دومین راهاندازی پس از اولین Cold Start معمولاً 20–40% سریعتر است. اگر برنامه از Baseline Profiles استفاده کند، پروفایلها در اولین راهاندازی بارگذاری میشوند و شروع دوم میتواند حتی سریعتر باشد: Google Play که Baseline Profiles را منتشر کرد، Cold Start را در دستگاههای Android 12+ تا 30% سریعتر کرد.
Cold Start از مراحل کاملاً مشخصی تشکیل شده است که هر کدام را میتوان به طور مستقل اندازهگیری و بهینهسازی کرد. شناخت مراحل کمک میکند تعیین کنید که برنامه در چه مرحلهای زمان از دست میدهد. Google چهار مرحله اصلی را مشخص میکند: ایجاد فرایند، مقداردهی Application، ایجاد Activity و اولین قاب.
سیستم Android (ActivityManagerService) با fork از فرایند Zygote یک فرایند جدید ایجاد میکند. Zygote یک فرایند از پیش بارگذاری شده با کلاسهای مشترک Android است. Fork در 30–80 ms اجرا میشود — این زمانی است که برنامه نمیتواند کنترل کند. پس از fork، ActivityThread راه اندازی میشود — نمونه حلقه اصلی برنامه. در این مرحله همچنین بارگذاری کلاسها از طریق ClassLoader انجام میشود و ART شروع به تفسیر اولین بایت-کد میکند. اگر برنامه از بسیاری مقداردهندههای ایستا استفاده کند، این مرحله میتواند طول بکشد.
بلافاصله پس از شروع ActivityThread، Application.onCreate فراخوانی میشود. اینجا توسعهدهنده بیشترین اشتباه را انجام میدهد — مقداردهی همه چیز در همان لحظه: Crashlytics، Firebase، مشتریان شبکه، پایگاههای داده، کامپوننتهای Dagger، کانتینرهای DI. هر چنین مقداردهی، زمانی است که در رشته اصلی مسدود شده است. اگر Application.onCreate 500 ms طول بکشد، تمام آن نیم ثانیه کاربر صفحه سفید (یا سیاه) را میبیند. مدت زمان بهینه برای این مرحله کمتر از 200 ms در یک دستگاه متوسط است.
پس از مقداردهی Application، نمونه Activity (MainActivity یا Launcher Activity) ایجاد میشود. Activity.onCreate فراخوانی میشود، که در آن setContentView، مقداردهی فرگمنتها، راهاندازی ViewModel، اشتراک LiveData/Flow انجام میشود. اگر onCreate بارگذاری داده (SharedPreferences، SQLite، API) را به صورت همزمان در رشته اصلی انجام دهد، مرحله طولانیتر میشود. هدف این است که onCreate در 200–400 ms در یک دستگاه متوسط جا بگیرد.
پس از پایان onCreate، اولین رندر شروع میشود: اندازهگیری، layout، draw. این لحظه TTFD (Time To First Draw) نامیده میشود. اگر برنامه از صفحه اسپلش (از طریق SplashScreen API در Android 12+ یا از طریق theme) استفاده کند، رندر ممکن است سریعتر اتفاق بیفتد، اما کاربر هنوز هم منتظر میماند تا اسپلش ناپدید شود. TTFD ایدهآل برای Cold Start کمتر از 1.5 ثانیه است.
اندازهگیری Cold Start به ابزارهای ویژهای نیاز دارد، زیرا ثبت معمولی (Log.d) تنها پس از ایجاد Application کار را شروع میکند و زمانبندی fork و بارگذاری کلاسها خارج از دسترس باقی میماند. Google سه روش را توصیه میکند: دستورات ADB، Android Vitals و ماکروهای سفارشی perf.
سادهترین و تکرارپذیرترین روش دستور adb shell am start -S -W است. کلید -S برنامه را قبل از راهاندازی مجبوراً متوقف میکند (Cold Start را تضمین میکند). دستور سه متریک را نمایش میدهد: ThisTime (زمان شروع Activity)، TotalTime (زمان کل با احتساب شروع فرایند) و WaitTime (زمان با احتساب تمام تاخیرهای Activity Manager). برای اندازهگیری خالی از نویز، 5–7 اندازهگیری انجام دهید و میانگین را بگیرید — اندازهگیریهای تک در معرض نویز هستند (CPU throttling، بار پسزمینه).
# اجباری Cold Start با اندازهگیری
$ adb shell am start -S -W \
com.example.app/.MainActivity
# خروجی دستور:
# ThisTime: 1842 ms
# TotalTime: 1842 ms
# WaitTime: 1855 ms
Google Play Console از همه دستگاههایی که برنامه روی آنها نصب شده، متریکهای ناشناس جمعآوری میکند. در بخش Android Vitals → Launch time، توزیع میانگین Cold Start بر اساس مدل دستگاه و نسخه Android نمایش داده میشود. این تنها راه دیدن شاخصهای واقعی در دستگاههای کاربران است، نه در دستگاههای آزمایشی. اگر در Redmi 9A (2 گیگابایت RAM) Cold Start از 5 ثانیه تجاوز کند و در Pixel 8 — 1.2 ثانیه باشد، مشکل در حافظه و تعداد کلاسهاست. Google همچنین تاخیر قابل درک کاربر (user-perceptible delay) را بر اساس 25 پرسنتایل نمایش میدهد.
Google Jetpack Macrobenchmark (کتابخانه androidx.benchmark) امکان نوشتن آزمونهای ابزاردهی راهاندازی برنامه را فراهم میکند. آزمون برنامه را نصب میکند، آن را در وضعیت سرد راه اندازی میکند و زمان تا اولین قاب را اندازهگیری میکند. Macrobenchmark به طور خودکار 20 بار اجرا میشود، مقادیر پرت را حذف میکند و پرسنتایلهای پایدار نشان میدهد. برای CI/CD میتوان baseline را با راهاندازی فعلی مقایسه کرد — اگر زمان افزایش یافته باشد، پایپلاین CI میتواند مشکل ایجاد کند.
بهینهسازی Cold Start یک کار سیستمی است که چند سطح برنامه را تحت تأثیر قرار میدهد: کد، منابع، تنظیمات ساخت و معماری مقداردهی. Google توصیه میکند از گرانترین شروع کنید — Application.onCreate — و به سمت جزئیات حرکت کنید.
تمام مقداردهیهایی را که در شروع نیاز نیست، از Application.onCreate به اولین نقطه استفاده منتقل کنید. Firebase، Crashlytics، analytics SDK، push-notifications، کامپوننتهای DI — همه را میتوان پس از رندر اولین صفحه مقداردهی کرد. از Lazy (by lazy) در Kotlin یا ContentProvider با فراخوانی صریح initialize(context) استفاده کنید. به گزارش Google (Android Performance, 2023)، مقداردهی تنبل Cold Start را برای برنامههایی که از 5+ SDK استفاده میکنند، 40–60% کاهش میدهد.
Baseline Profiles — کامپایل AOT کلاسها و روشهای بحرانی است که در شروع برنامه استفاده میشوند. بدون Baseline Profiles، ART کد DEX را تفسیر یا با JIT کامپایل میکند که زمان میبرد. با پروفایلها، ART روشهای مشخص شده را در زمان نصب برنامه به کد بومی (AOT) کامپایل میکند. Google ادعا میکند که Baseline Profiles Cold Start را در Android 9+ تا 15–40% و با بهینهسازیهای ART در Android 12+ تا 60% سریعتر میکند. برای ایجاد پروفایلها از افزونه androidx.benchmark:benchmark-baseline-profile-gradle-plugin استفاده کنید.
کتابخانه androidx.startup به شما امکان میدهد مقداردهی کامپوننتها را ساماندهی کرده و آن را در یک ContentProvider اجرا کنید. به جای چندین ContentProvider از کتابخانههای مختلف (هر کدام 1–2 ms به زمان شروع سرد اضافه میکند) App Startup آنها را در یک گراف وابستگی ترکیب میکند و فقط در صورت نیاز مقداردهی میکند. در شروع، تنها کامپوننتهایی با @Initializer که به عنوان ضروری برای صفحه اول علامت زده شدهاند، اجرا میشوند. برای بقیه، پرچم needEarlyInit = false قرار داده میشود — آنها پس از اولین رندر شروع میشوند.
// App Startup Initializer — مقداردهی پس از راهاندازی
class AnalyticsInitializer : Initializer<Unit> {
override fun create(context: Context) {
Analytics.init(context)
}
override fun dependencies() = listOf<Class<out Initializer<*>>>()
}
// در AndroidManifest.xml به عنوان اختیاری علامتگذاری میکنیم
// <meta-data android:name="AnalyticsInitializer"
// android:value="false" />
اندازه فایل DEX مستقیماً بر زمان بارگذاری آن توسط ART تأثیر میگذارد. از R8/ProGuard برای مبهمسازی و حذف کدهای مرده استفاده کنید (MinifyEnabled = true). android:extractNativeLibs="false" را در مانیفست فعال کنید تا APK فایلهای .so را در زمان نصب باز نکند. برای پروژههای با 10 Reference Tracking، startup-priority را فقط برای صفحه اول اضافه کنید. هر روش اضافی در DEX 0.5–2 ms به بارگذاری اضافه میکند، و برای برنامههای با 50k+ روش (multidex با primary dex) — تا 300 ms.
Android Vitals در Google Play Console (Launch time section) از همه دستگاههایی که برنامه روی آنها نصب شده داده جمعآوری میکند، مشروط بر این که کاربر با تشخیص ناشناس موافقت کرده باشد. متریکها به سه دسته تقسیم میشوند: «good» (خوب)، «moderate» (متوسط)، «bad» (بد)، بسته به زمان Cold Start.
Google «bad» Cold Start را زمانی تعریف میکند که از 5 ثانیه در هر دستگاهی تجاوز کند. اما در عمل، برای دستگاههای پرچمدار (Snapdragon 8 Gen) زمان خوب کمتر از 1.5 ثانیه، برای رده متوسط کمتر از 2.5 ثانیه، و برای رده اقتصادی کمتر از 4 ثانیه در نظر گرفته میشود. Android Vitals میانگین را برای هر device model نشان میدهد که به شما امکان میدهد بفهمید برنامه در کدام دستگاهها کند راه اندازی میشود. اگر Cold Start در دستگاههای Samsung A-series یا Xiaomi Redmi بد است، علت بیشتر حافظه flash ضعیف و حافظه کم است (سرعتتر شدن از طریق Baseline Profiles دقیقاً در چنین دستگاههایی بیشترین تأثیر را دارد).
علاوه بر نمایش در کنسول، متریک Cold Start بر ارزیابی کیفیت برنامه در Google Play Search تأثیر میگذارد. برنامههای با درصد بالای راهاندازی «بد» برچسب «Performance warning» را در صفحه نصب دریافت میکنند که نرخ تبدیل را کاهش میدهد. به گزارش Google (Android Performance Playbook, 2024)، برنامههایی که مشکلات Cold Start را برطرف کردهاند، به طور متوسط نرخ تبدیل نصب را 5% افزایش و شاخص retention (D1) را 3–7% بهبود میبخشند.
برای نظارت جزئیتر، از Firebase Performance Monitoring استفاده کنید. آن Cold Start را در سطح جلسه ردیابی میکند، بر اساس نسخه برنامه و نسخه Android تقسیم میکند. بر خلاف Android Vitals، Firebase نمودار trace زمان صرف شده را توسط مراحل نشان میدهد. به عنوان مثال، میتوان دید که در نسخه 3.2.0 Application.onCreate 800 ms (به دلیل کتابخانه جدید اعلانهای فوری) طول کشیده، در حالی که در نسخه 3.2.1 — 200 ms (پس از رفع).
در زیر دو نمونه عملی آورده شده است که مستقیماً Cold Start را سریعتر میکنند: انتقال مقداردهی SDK به بعد از شروع و استفاده از SplashScreen API.
یک اشتباه رایج — مقداردهی تمام SDKها در Application.onCreate. در زیر نشان داده شده است که چگونه مقداردهی غیر بحرانی را به یک کوروتین که پس از رندر اولین قاب شروع میشود منتقل کنیم. مهم: Firebase، Crashlytics و Crash Reporting SDK باید در شروع مقداردهی شوند — نمیتوان آنها را به تأخیر انداخت، زیرا در زمان مقداردهی سایر کامپوننتها کرش را میگیرند. برای بقیه از lifecycleScope در اولین Activity استفاده کنید.
// ❌ بد — تمام مقداردهی در Application.onCreate
class App : Application() {
override fun onCreate() {
super.onCreate()
Firebase.init(this) // بحرانی
Analytics.init(this) // میتواند بعداً
Database.init(this) // میتواند بعداً
ImageLoader.init(this) // میتواند بعداً
}
}
// ✅ خوب — Firebase در شروع، بقیه بعد از inflate
class App : Application() {
override fun onCreate() {
super.onCreate()
Firebase.init(this)
}
}
// در MainActivity پس از اولین قاب:
lifecycleScope.launchWhenResumed {
initializeNonCriticalSdks()
}
در Android 12+ از SplashScreen API رسمی استفاده کنید که بلافاصله پس از شروع فرایند، اسپلش سیستم (آیکون برنامه روی زمینه تیره/روشن) را نشان میدهد. این زمان مقداردهی را از کاربر پنهان میکند — او به جای صفحه سفید، اسپلش را میبیند. برای دستگاههای قدیمی، از theme-based splash (Theme.SplashScreen در استایلها) استفاده کنید. مهم: اسپلش نباید بیشتر از 300 ms طول بکشد — اگر تا آن زمان برنامه آماده نیست، یک اسکلت «دائمی» (shimmer) بکشید و پیشرفت بارگذاری را نشان دهید.
// SplashScreen API — Android 12+
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val splashScreen = installSplashScreen()
splashScreen.setKeepOnScreenCondition {
isReady.value == false
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
// Theme-based splash (Android 5-11)
// در themes.xml:
// <style name="Theme.App.Starting" parent="Theme.SplashScreen">
// <item name="windowSplashScreenBackground">@color/white</item>
// <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
// </style>
سوالات متداول
شبیهساز از یک کامپیوتر میزبان قدرتمند استفاده میکند و پردازنده را با شتابدهنده سختافزاری (HAXM / WHPX) شبیهسازی میکند. دستگاههای فیزیکی، به ویژه اقتصادی (حافظه eMMC به جای UFS)، I/O بسیار کندتری دارند. توصیه میشود Cold Start را در یک دستگاه فیزیکی رده متوسط اندازهگیری کنید تا دادههای واقعگرایانه به دست آورید.
بر اساس توصیههای Google، میانگین Cold Start باید در دستگاههای رده متوسط کمتر از 2 ثانیه باشد. برای پرچمداران — کمتر از 1.5 ثانیه. برای دستگاههای اقتصادی (2 گیگابایت RAM) تا 4 ثانیه مجاز است، اما توصیه میشود تا 3 ثانیه بهینهسازی شود. مقادیر بیش از 5 ثانیه بحرانی در نظر گرفته میشوند.
به صورت غیرمستقیم — بله. اگر در مانیفست آیکون برداری (AdaptiveIcon) مشخص شده باشد، باید در شروع به drawable کامپایل شود. اگر آیکون حاوی مسیرهای پیچیده (pathData با دهها منحنی) باشد، کامپایل 10–30 ms طول میکشد. از VectorDrawable با pathData بهینهشده (از طریق SVGOMG یا Android Studio Vector Asset) استفاده کنید.
بله، اگر Feature Module (Android App Bundle) به صورت درخواستی (on-demand) بارگذاری شود، Cold Start آن از لحظه کلیک روی ویژگی تا اولین قاب محاسبه میشود. ماژولهای on-demand از طریق Play Core Library بارگذاری میشوند و نصب آنها 500–3000 ms به زمان شروع اضافه میکند. کد ویژگی را مانند ماژول اصلی بهینهسازی کنید.
برنامههای با بیش از 64k روش نیاز به Multidex دارند. این بدان معناست که ART باید چندین فایل DEX بارگذاری کند که زمان Cold Start را 200–800 ms بسته به تعداد classes.dex افزایش میدهد. از minSdk 21+ (ART با پشتیبانی multidex بومی) استفاده کنید و primary dex را از طریق --main-dex-list پیکربندی کنید تا کلاسهای بحرانی در اولین فایل DEX باشند.
نتیجهگیری
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید