धीमा ऐप — मुख्य कारण है जिससे उपयोगकर्ता प्रोग्राम डिलीट कर देते हैं। स्टार्टअप या सूची स्क्रॉल करते समय सेकंड के अंश का विलंब रिटेंशन को दसियों प्रतिशत तक कम कर देता है। प्रदर्शन (performance) — केवल गति नहीं है, बल्कि स्थिरता भी है: ANR, क्रैश और मेमोरी लीक का अभाव। इस लेख में हम प्रदर्शन के सभी पहलुओं को कवर करेंगे: मेमोरी प्रबंधन (GC, ARC) से लेकर टूल्स के साथ प्रोफाइलिंग तक। अधिक जानकारी — आधिकारिक Android Performance गाइड में।
मुख्य बातें
ऐप का प्रदर्शन सीधे जैंक (jank) से जुड़ा है — उपयोगकर्ता की कार्रवाई और UI प्रतिक्रिया के बीच ध्यान देने योग्य देरी। मुख्य कारण: मेन थ्रेड ब्लॉकिंग (UI थ्रेड पर भारी संचालन), बार-बार लेआउट रीड्रा (overdraw), मेमोरी लीक (बार-बार GC), गैर-इष्टतम एल्गोरिदम (बड़े डेटा पर O(n²))। फ्रेम रेट (FPS) — प्रति सेकंड फ्रेम की संख्या। आरामदायक अनुभव के लिए स्थिर 60 FPS (Android) या 120 FPS (iPhone Pro, iPad Pro) चाहिए। VSync — स्क्रीन रीफ्रेश दर के साथ रेंडरिंग को सिंक्रोनाइज़ करता है।
जैंक तब होता है जब एक फ्रेम का रेंडरिंग 16.6 ms (60 FPS के लिए) या 8.3 ms (120 FPS के लिए) से अधिक हो जाता है। GPU प्रोफाइलिंग (Android पर Profile GPU Rendering, iOS पर Core Animation) दिखाता है कि रेंडरिंग के कौन से चरण सबसे अधिक समय लेते हैं। मुख्य चरण: Layout (तत्वों की व्यवस्था), Draw (ड्राइंग), Display (फ्रेम बफर में स्थानांतरण)। सबसे आम समस्या XML में लेआउट इन्फ्लेशन है, विशेष रूप से जटिल नेस्टेड ConstraintLayout का उपयोग करते समय।
टाइम-टू-इंटरैक्टिव (TTI) — वह समय जिसमें ऐप इंटरैक्शन के लिए पूरी तरह तैयार हो जाता है। TTI में कोल्ड स्टार्ट, डेटा लोडिंग और लाइब्रेरी इनिशियलाइज़ेशन शामिल है। Google TTI को 5 सेकंड से कम, Apple — मुख्य स्क्रीन के लिए 2 सेकंड से कम रखने की सलाह देता है। लेज़ी लोडिंग — सामग्री और लाइब्रेरी के विलंबित लोडिंग की तकनीक, TTI में सुधार के लिए महत्वपूर्ण। IT Sectr में हम सभी प्रोजेक्ट्स में डिफ़ॉल्ट रूप से आलसी आरंभीकरण का उपयोग करते हैं।
ANR और क्रैश — मोबाइल ऐप प्रदर्शन के मुख्य दुश्मन। ANR (Application Not Responding) — Android पर दिखने वाला डायलॉग बॉक्स जो तब प्रकट होता है जब मेन थ्रेड 5 सेकंड से अधिक समय तक ब्लॉक रहता है। कारण: UI थ्रेड पर सिंक्रोनस नेटवर्क अनुरोध, कोरूटीन के बिना डेटाबेस के साथ काम, डाउनसैंपलिंग के बिना बड़ा बिटमैप डिकोड, मेन थ्रेड पर डेडलॉक। ANR कॉल स्टैक /data/anr/traces.txt में सहेजा जाता है और सटीक ब्लॉकिंग स्थान निर्धारित करने की अनुमति देता है।
क्रैश — ऐप का अप्रत्याशित समाप्ति। Android पर — Exception (Java/Kotlin) या Signal (नेटिव कोड)। iOS पर — NSException या सिग्नल (EXC_BAD_ACCESS — मुक्त की गई मेमोरी तक पहुँच)। क्रैश रिपोर्टिंग टूल्स: Firebase Crashlytics, Sentry, BugSnag। ये स्टैकट्रेस, डिवाइस डेटा और पुनरुत्पादन चरण एकत्र करते हैं। स्टैक ओवरफ़्लो — अनंत पुनरावृत्ति के कारण कॉल स्टैक ओवरफ़्लो। OutOfMemoryError — जब हीप भर जाती है।
StrictMode — थ्रेड सुरक्षा उल्लंघनों का पता लगाने के लिए Android टूल। यह नियम सेट करने की अनुमति देता है: ThreadPolicy (मेन थ्रेड पर डिस्क/नेटवर्क प्रतिबंधित करें), VmPolicy (Activity, SQLite, CloseGuard लीक का पता लगाएं)। StrictMode को केवल डीबग बिल्ड में सक्षम करने की अनुशंसा की जाती है — रिलीज़ में इसे काम नहीं करना चाहिए। iOS पर समकक्ष Main Thread Checker (Xcode) है, जो स्वचालित रूप से मेन थ्रेड पर नहीं होने वाले UIKit कॉल का पता लगाता है।
मेमोरी लीक — वह स्थिति जब कोई ऑब्जेक्ट मेमोरी में बना रहता है, भले ही ऐप उसका उपयोग नहीं कर रहा हो। यह सीधे ऐप के प्रदर्शन को कम करता है। Android पर, GC (Garbage Collection) किसी ऑब्जेक्ट को एकत्र नहीं कर सकता यदि उस पर एक मजबूत संदर्भ (strong reference) है। विशिष्ट कारण: Activity के लिए स्थिर संदर्भ, साफ़ न किए गए कॉलबैक/पर्यवेक्षक, बाहरी वर्ग के लिए अंतर्निहित संदर्भ वाले आंतरिक वर्ग, साफ़ न किए गए संदेशों वाला Handler। LeakCanary — स्वचालित लीक पहचान के लिए लाइब्रेरी।
ARC (Automatic Reference Counting) — iOS में मेमोरी प्रबंधन मॉडल। प्रत्येक ऑब्जेक्ट में एक संदर्भ गणना (retain count) होती है। गणना शून्य होने पर मेमोरी मुक्त हो जाती है। रिटेन साइकिल तब होती है जब दो ऑब्जेक्ट एक-दूसरे के लिए मजबूत संदर्भ रखते हैं (A → B और B → A)। ARC कभी भी गणनाओं को शून्य नहीं करेगा। समाधान: कमज़ोर (weak) या अनाउंड (unowned) संदर्भ। Weak ऑब्जेक्ट मुक्त होने पर स्वचालित रूप से nil हो जाता है। Unowned nil नहीं होता लेकिन गारंटी देता है कि ऑब्जेक्ट जीवित है।
GC (Garbage Collection) Android (Java/Kotlin) पर चलता है। GC अप्राप्य ऑब्जेक्ट्स को खोजने और मुक्त करने के लिए समय-समय पर निष्पादन को रोकता है (Stop-the-World pause)। GC ट्रिगर: जब हीप एक निश्चित प्रतिशत तक भर जाती है। ARC iOS (Swift/Objective-C) पर चलता है और इसमें कोई रुकावट नहीं है — प्रत्येक असाइनमेंट पर काउंटर परमाणु रूप से अपडेट होते हैं। ARC अधिक पूर्वानुमानित है लेकिन उच्च असाइनमेंट आवृत्ति पर अत्यधिक retain/release संचालन जमा कर सकता है।
कमज़ोर संदर्भ (Weak Reference) और मजबूत संदर्भ (Strong Reference) — संदर्भ का प्रकार यह निर्धारित करता है कि क्या GC/ARC ऑब्जेक्ट को मुक्त कर सकता है। Strong Reference — जब तक यह संदर्भ मौजूद है, ऑब्जेक्ट एकत्र नहीं किया जाएगा। Weak Reference — GC/ARC ऑब्जेक्ट को एकत्र कर सकता है; कमज़ोर संदर्भ nil हो जाता है (Swift/Java WeakReference में)। Unowned Reference (Swift) — मुक्त होने पर nil नहीं होता; ऑब्जेक्ट के मृत होने के बाद उस तक पहुँचने पर क्रैश होता है। Android पर कमज़ोर संदर्भों के लिए java.lang.ref.WeakReference का उपयोग किया जाता है।
LeakCanary का उपयोग करके Android पर लीक का पता लगाने का उदाहरण:
// Утечка: анонимный класс держит ссылку на Activity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val handler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
// Используем `this@MainActivity`, сохраняя ссылку на Activity
Log.d("TAG", "Handler received message")
}
}
handler.sendEmptyMessageDelayed(0, 60000)
}
}
// Исправление: статический Handler + WeakReference
class SafeHandler(activity: MainActivity) : Handler() {
private val weakActivity =
WeakReference(activity)
override fun handleMessage(msg: Message) {
weakActivity.get() ?: return
Log.d("TAG", "Handler received message")
}
}
प्रोफाइलिंग — ऐप के प्रदर्शन को मापने की प्रक्रिया: CPU, मेमोरी, नेटवर्क, ऊर्जा खपत। प्रोफाइलिंग के बिना, अंधा अनुकूलन बेकार है — आपको पता नहीं चलेगा कि कोड का कौन सा हिस्सा वास्तव में धीमा है।
| उपकरण | प्लेटफ़ॉर्म | मापता है | कब उपयोग करें |
|---|---|---|---|
| Instruments (Time Profiler) | iOS | CPU, फ़ंक्शन कॉल, निष्पादन समय | एल्गोरिदम अनुकूलन, अड़चन खोज |
| Instruments (Allocations) | iOS | मेमोरी, ऑब्जेक्ट गणना, retain counts | लीक और अत्यधिक मेमोरी खपत खोजना |
| Instruments (Leaks) | iOS | रिटेन साइकिल, मेमोरी लीक | रिलीज़ से पहले नियमित जाँच |
| Android Profiler (CPU) | Android | CPU उपयोग, थ्रेड गतिविधि, traces | मेन थ्रेड ब्लॉकिंग खोजना |
| Android Profiler (Memory) | Android | हीप डंप, आवंटन ट्रैकिंग | लीक खोजना, ऑब्जेक्ट विश्लेषण |
| Android Profiler (Network) | Android | ट्रैफ़िक, गति, अनुरोध समय | नेटवर्क कॉल अनुकूलन |
| LeakCanary | Android | स्वचालित मेमोरी लीक पहचान | सभी विकास चरणों में |
| StrictMode | Android | मेन थ्रेड पर डिस्क/नेटवर्क, लीक | डीबग बिल्ड |
| Traceview / Systrace | Android | मेथड ट्रेसिंग, सिस्टम इवेंट | गहराई से विलंबता विश्लेषण |
Instruments (Xcode) — iOS के लिए सबसे शक्तिशाली उपकरण। Time Profiler दिखाता है कि कौन से फ़ंक्शन सबसे अधिक CPU का उपभोग करते हैं। Allocations ऑब्जेक्ट निर्माण और मुक्ति को ट्रैक करता है। Leaks स्वचालित रूप से रिटेन साइकिल ढूँढता है। प्रोफाइलिंग चरण: (1) Instruments लॉन्च करें; (2) टेम्पलेट चुनें (CPU के लिए Time Profiler); (3) समस्या वाला परिदृश्य चलाएँ; (4) कॉल स्टैक का विश्लेषण करें — सबसे चौड़ा कॉलम सबसे "हॉट" फ़ंक्शन है।
Android Profiler Android Studio में निर्मित है (View → Tool Windows → Profiler)। CPU Profiler प्रत्येक थ्रेड का लोड दिखाता है। Memory Profiler — हीप डंप और आवंटन ट्रैकिंग। Network Profiler — समय सहित सभी HTTP अनुरोध। Energy Profiler — ऊर्जा खपत: WakeLock, Location, Network। विस्तृत ट्रेसिंग के लिए Systrace (Android 10+) या Perfetto का उपयोग किया जाता है — माइक्रोसेकंड सटीकता के साथ सिस्टम ट्रेसिंग।
ऐप स्टार्टअप — प्रदर्शन के प्रमुख संकेतकों में से एक है। यह तीन प्रकारों में विभाजित है: कोल्ड स्टार्ट — ऐप शून्य से शुरू होता है: प्रक्रिया बनाई जाती है, Application.onCreate (Android) / AppDelegate.applicationDidFinishLaunching (iOS), क्लास लोडिंग, लाइब्रेरी इनिशियलाइज़ेशन। वार्म स्टार्ट — प्रक्रिया मौजूद है, लेकिन Activity/ViewController नष्ट हो गया है (उदाहरण के लिए, स्क्रीन घुमाने या मेमोरी से वापस आने पर)। हॉट स्टार्ट — Activity/ViewController मेमोरी में है, ऐप बस प्रदर्शित होता है (दूसरे ऐप से स्विच करना)।
कोल्ड स्टार्ट सबसे महत्वपूर्ण मीट्रिक है। Android पर इसमें शामिल है: (1) लॉन्च Activity — XML लोडिंग, View इनिशियलाइज़ेशन; (2) पहला फ्रेम — पहले रेंडर तक का समय। Google अनुशंसा करता है: लॉन्च Activity < 200 ms, पहला फ्रेम < 500 ms, TTI < 5 सेकंड। कोल्ड स्टार्ट अनुकूलन: Application.onCreate कम करें (आलसी आरंभीकरण के लिए कोरूटीन), SplashScreen API (Android 12+) का उपयोग करें, लाइब्रेरी इनिशियलाइज़ेशन स्थगित करें (WorkManager, DI), अनावश्यक ContentProviders हटाएँ।
iOS पर, कोल्ड स्टार्ट में शामिल है: Mach-O बाइनरी लोडिंग, dyld (डायनामिक लिंकर), Objective-C रनटाइम इनिशियलाइज़ेशन, एप्लिकेशन डेलिगेट, पहला कंट्रोलर। Chrome Custom Tabs (Android) और Universal Links (iOS) — पूर्ण कोल्ड स्टार्ट के बिना ऐप में बाहरी सामग्री को जल्दी से खोलने की तकनीकें। मिड-रेंज वास्तविक उपकरणों पर कोल्ड स्टार्ट का परीक्षण करने की अनुशंसा की जाती है।
ऐप का आकार — स्थापना और अपडेट के लिए प्रदर्शन कारक है। यह रूपांतरण को प्रभावित करता है: प्रत्येक 10 MB रूपांतरण को 1% कम करता है। Google Play अनुशंसा करता है APK का आकार 150 MB से कम; App Store — 200 MB से कम (सेलुलर नेटवर्क — 100 MB)। मुख्य अनुकूलन विधियाँ: छवि संपीड़न (PNG के बजाय WebP 25-35% बचाता है), वेक्टराइज़ेशन (Android पर VectorDrawable, iOS पर SF Symbols), अप्रयुक्त कोड हटाना (R8/ProGuard), अप्रयुक्त संसाधन हटाना (lint → unused resources)।
App Bundle (Android) — एक प्रकाशन प्रारूप जिसमें Google Play प्रत्येक डिवाइस के लिए अनुकूलित APK उत्पन्न करता है। App Bundle डाउनलोड आकार को 20-40% कम करता है। Dynamic Delivery — माँग पर डाउनलोड किए जाने वाले मॉड्यूल (on-demand feature modules)। iOS पर समकक्ष On-Demand Resources (ODR) है: पहले लॉन्च के बाद डाउनलोड किए जाने वाले संसाधन (गेम लेवल, वीडियो)।
लेज़ी लोडिंग — एक तकनीक जिसमें मॉड्यूल और लाइब्रेरी स्टार्टअप पर लोड नहीं होते बल्कि आवश्यकतानुसार लोड होते हैं। Split APK (Android) और App Slicing (iOS) — ऐप को आर्किटेक्चर स्लॉट में विभाजित करना: arm64-v8a, x86_64। ऐप आकार अनुकूलन — एक सतत प्रक्रिया: APK संरचना का विश्लेषण करें (Android Studio में Analyze APK), डुप्लिकेट आइकन हटाएँ, कई PNG घनत्वों के बजाय SVG का उपयोग करें। IT Sectr में हम प्रत्येक MR के लिए CI/CD में बिल्ड आकार जाँच शामिल करते हैं।
अक्सर पूछे जाने वाले प्रश्न
ANR (Application Not Responding) — एक डायलॉग जो Android पर तब दिखाई देता है जब मेन थ्रेड 5 सेकंड से अधिक समय तक ब्लॉक रहता है। ANR से बचने के लिए, सभी भारी संचालन (नेटवर्क, डेटाबेस, फ़ाइल प्रोसेसिंग) को बैकग्राउंड थ्रेड्स पर ले जाएँ। iOS पर समकक्ष — frozen UI, जब ऐप स्पर्शों पर प्रतिक्रिया देना बंद कर देता है।
मेमोरी लीक — जब कोई ऑब्जेक्ट मुक्त नहीं किया जा सकता क्योंकि उसके संदर्भ मौजूद हैं। रिटेन साइकिल — iOS/Objective-C में स्थिति जहाँ दो ऑब्जेक्ट एक-दूसरे को संदर्भित करते हैं (A → B → A) और ARC किसी को भी मुक्त नहीं कर सकता। समाधान: weak/unowned संदर्भ और समय पर कॉलबैक सफाई।
iOS के लिए: Instruments (Time Profiler, Allocations, Leaks)। Android के लिए: Android Profiler (CPU, Memory, Network), LeakCanary (मेमोरी लीक), StrictMode (थ्रेड उल्लंघन)। विकास और एकीकरण के दौरान प्रोफाइलिंग को संयोजित करने की अनुशंसा की जाती है।
कोल्ड स्टार्ट — ऐप शून्य से शुरू होता है: प्रक्रिया बनाई जाती है, कक्षाएँ लोड की जाती हैं, Application.onCreate चलता है। वार्म स्टार्ट — प्रक्रिया मौजूद है लेकिन Activity/ViewController पुनः बनाया जाता है। हॉट स्टार्ट — Activity/ViewController पहले से मेमोरी में है, बस प्रदर्शित होता है। कोल्ड स्टार्ट सबसे धीमा है (1-5 सेकंड) और उपयोगकर्ता अनुभव के लिए महत्वपूर्ण है।
मुख्य विधियाँ: अप्रयुक्त संसाधन और कोड हटाएँ (R8/ProGuard का उपयोग करें), छवियों को वेक्टराइज़ करें (VectorDrawable, SF Symbols), PNG/WebP संपीड़ित करें (Android), APK के बजाय App Bundle का उपयोग करें, अनावश्यक लाइब्रेरी हटाएँ, मॉड्यूल के लिए लेज़ी लोडिंग का उपयोग करें। आकार अनुकूलन APK को 40-60% तक कम कर सकता है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।