16 केबी वाले पेज साइज़ के साथ काम करना

Historically, Android has only supported 4 KB memory page sizes, which has optimized system memory performance for the average amount of total memory that Android devices have typically had. Beginning with Android 15, AOSP supports devices that are configured to use a page size of 16 KB (16 KB devices). If your app uses any NDK libraries, either directly or indirectly through an SDK, then you will need to rebuild your app for it to work on these 16 KB devices.

As device manufacturers continue to build devices with larger amounts of physical memory (RAM), many of these devices will adopt 16 KB (and eventually greater) page sizes to optimize the device's performance. Adding support for 16 KB page size devices enables your app to run on these devices and helps your app benefit from the associated performance improvements. Without recompiling, apps won't work on 16 KB devices in future Android releases.

To help you add support for your app, we've provided guidance on how to check if your app is impacted, how to rebuild your app (if applicable), and how to test your app in a 16 KB environment using emulators (including Android 15 system images for the Android Emulator).

Google Play के साथ काम करने की ज़रूरी शर्तें

Google Play पर मौजूद, Android 15 (एपीआई लेवल 35) या इसके बाद के वर्शन को टारगेट करने वाले सभी ऐप्लिकेशन को 16 केबी मेमोरी वाले पेज साइज़ के साथ काम करना होगा. ऐसा इसलिए, ताकि Android के नए वर्शन पर आपका ऐप्लिकेशन ठीक से काम करे. साथ ही, 64-बिट डिवाइसों पर भी यह काम करे. अगर 1 फ़रवरी, 2027 से आपके ऐप्लिकेशन के अपडेट, 16 केबी मेमोरी वाले पेज साइज़ के साथ काम नहीं करते हैं, तो इन अपडेट को रिलीज़ नहीं किया जा सकेगा.

Google Play Console की चेतावनी: ऐप्लिकेशन के अपडेट, 1 फ़रवरी, 2027 तक 16 केबी मेमोरी वाले पेज साइज़ के साथ काम करने चाहिए
पहली इमेज. Google Play Console में, डिवाइस के साथ काम न करने की चेतावनी.

फ़ायदे और परफ़ॉर्मेंस में सुधार

Devices configured with 16 KB page sizes use slightly more memory on average, but also gain various performance improvements for both the system and apps:

  • Lower app launch times while the system is under memory pressure: 3.16% lower on average, with more significant improvements (up to 30%) for some apps that we tested
  • Reduced power draw during app launch: 4.56% reduction on average
  • Faster camera launch: 4.48% faster hot starts on average, and 6.60% faster cold starts on average
  • Improved system boot time: improved by 8% (approximately 950 milliseconds) on average

These improvements are based on our initial testing, and results on actual devices will likely differ. We'll provide additional analysis of potential gains for apps as we continue our testing.

देखें कि आपके ऐप्लिकेशन पर इसका असर पड़ा है या नहीं

If your app uses any native code, then you should rebuild your app with support for 16 KB devices. If you are unsure if your app uses native code, you can use the APK Analyzer to identify whether any native code is present and then check the alignment of ELF segments for any shared libraries that you find. Android Studio also provides features that help you to automatically detect alignment issues.

If your app only uses code written in the Java programming language or in Kotlin, including all libraries or SDKs, then your app already supports 16 KB devices. Nevertheless, we recommend that you test your app in a 16 KB environment to verify that there are no unexpected regressions in app behavior.

क्या आपका ऐप्लिकेशन, नेटिव कोड का इस्तेमाल करता है?

अगर आपके ऐप्लिकेशन में इनमें से कोई भी स्थिति लागू होती है, तो वह नेटिव कोड का इस्तेमाल करता है:

  • आपका ऐप्लिकेशन, C/C++ (नेटिव) कोड का इस्तेमाल करता है. अगर आपका ऐप्लिकेशन Android NDK का इस्तेमाल करता है, तो इसका मतलब है कि वह नेटिव कोड का इस्तेमाल करता है.
  • आपका ऐप्लिकेशन, तीसरे पक्ष की ऐसी नेटिव लाइब्रेरी या डिपेंडेंसी (जैसे, एसडीके) से लिंक होता है जो इनका इस्तेमाल करती हैं.
  • आपके ऐप्लिकेशन को तीसरे पक्ष के ऐप्लिकेशन बिल्डर ने बनाया है. यह बिल्डर, डिवाइस पर नेटिव लाइब्रेरी का इस्तेमाल करता है.

APK ऐनालाइज़र का इस्तेमाल करके नेटिव लाइब्रेरी की पहचान करना

APK Analyzer एक ऐसा टूल है जिसकी मदद से, बनाए गए APK के अलग-अलग पहलुओं का आकलन किया जा सकता है. यह देखने के लिए कि आपका ऐप्लिकेशन नेटिव कोड का इस्तेमाल करता है या नहीं (इससे कोई फ़र्क़ नहीं पड़ता कि यह 16 केबी वाले पेजों के साथ काम करता है या नहीं):

  1. Android Studio खोलें. इसके बाद, File > Open पर क्लिक करें और कोई प्रोजेक्ट चुनें.
  2. मेन्यू बार में जाकर, Build > Analyze APK... पर क्लिक करें

    APK ऐनालाइज़र लॉन्च करने के लिए, Studio के Build मेन्यू का विकल्प
  3. वह APK चुनें जिसका विश्लेषण करना है.

  4. lib फ़ोल्डर में देखें. अगर कोई शेयर किया गया ऑब्जेक्ट (.so) फ़ाइल मौजूद है, तो वह इसी फ़ोल्डर में होगी. अगर शेयर की गई कोई ऑब्जेक्ट फ़ाइल मौजूद है, तो आपका ऐप्लिकेशन नेटिव कोड का इस्तेमाल करता है. अलाइनमेंट कॉलम में, अलाइनमेंट से जुड़ी समस्याओं वाली फ़ाइलों के लिए चेतावनी वाले मैसेज दिखते हैं. अगर शेयर की गई कोई ऑब्जेक्ट फ़ाइल मौजूद नहीं है या कोई lib फ़ोल्डर नहीं है, तो इसका मतलब है कि आपका ऐप्लिकेशन नेटिव कोड का इस्तेमाल नहीं करता है.

    APK ऐनलिसिस व्यू में दिखाया गया है कि शेयर की गई ऑब्जेक्ट फ़ाइलें मौजूद हैं

अपने-आप होने वाली जांचों से, अलाइनमेंट से जुड़ी समस्याओं का पता लगाना

अगर आपकी प्रीबिल्ट लाइब्रेरी या APK, 16 केबी के साइज़ के मुताबिक नहीं हैं, तो Android Studio आपको पहले से ही इसकी सूचना दे देता है. APK Analyzer टूल का इस्तेमाल करके देखें कि किन लाइब्रेरी को अपडेट करने की ज़रूरत है या कोड में कोई बदलाव करना ज़रूरी है या नहीं.

किसी प्रोजेक्ट में अलाइनमेंट से जुड़ी समस्याओं के बारे में Studio की चेतावनियां

Android Studio में Lint, उन नेटिव लाइब्रेरी को भी हाइलाइट करता है जो 16 केबी के साथ अलाइन नहीं हैं.

Studio के लिंटर की चेतावनी, जो नेटिव लाइब्रेरी के अलाइन न होने के बारे में है

शेयर की गई लाइब्रेरी के लिए, ईएलएफ़ सेगमेंट के अलाइनमेंट की जांच करना

शेयर की गई किसी भी लाइब्रेरी के लिए, पुष्टि करें कि शेयर की गई लाइब्रेरी के ईएलएफ़ सेगमेंट, 16 केबी ईएलएफ़ अलाइनमेंट का इस्तेमाल करके सही तरीके से अलाइन किए गए हों. अगर Linux या macOS पर डेवलपमेंट किया जा रहा है, तो यहां दिए गए सेक्शन में बताए गए तरीके से check_elf_alignment.sh स्क्रिप्ट का इस्तेमाल किया जा सकता है. कमांड-लाइन टूल का सीधे तौर पर इस्तेमाल भी किया जा सकता है.

check_elf_alignment.sh स्क्रिप्ट का इस्तेमाल करें (Linux या macOS)

check_elf_alignment.sh स्क्रिप्ट का इस्तेमाल करके, ईएलएफ़ सेगमेंट के अलाइनमेंट की जांच करने के लिए, यह तरीका अपनाएं:

  1. check_elf_alignment.sh स्क्रिप्ट को किसी फ़ाइल में सेव करें.

  2. अपने ऐप्लिकेशन की APK फ़ाइल पर स्क्रिप्ट चलाएं:

    check_elf_alignment.sh APK_NAME.apk
    

    यह स्क्रिप्ट, शेयर की गई सभी arm64-v8a लाइब्रेरी के लिए ALIGNED या UNALIGNED आउटपुट देती है.

  3. अगर शेयर की गई कोई arm64-v8a या x86_64 लाइब्रेरी UNALIGNED है, तो आपको उन लाइब्रेरी के लिए पैकेजिंग अपडेट करनी होगी. इसके बाद, अपने ऐप्लिकेशन को फिर से कंपाइल करें और इस सेक्शन में दिए गए चरणों का पालन करके, फिर से जांच करें.

कमांड-लाइन टूल का सीधे तौर पर इस्तेमाल करना

कमांड-लाइन टूल का इस्तेमाल करके, सीधे तौर पर ईएलएफ़ सेगमेंट के अलाइनमेंट की जांच करने के लिए, यह तरीका अपनाएं:

  1. पक्का करें कि Android SDK बिल्ड-टूल का 35.0.0 या इसके बाद का वर्शन और Android NDK, दोनों इंस्टॉल हों. इसके लिए, Android Studio में एसडीके मैनेजर या sdkmanager कमांड-लाइन टूल का इस्तेमाल करें.
  2. अपने ऐप्लिकेशन की APK फ़ाइल निकालें:

    Linux या macOS

    unzip APK_NAME.apk -d /tmp/my_apk_out
    

    Windows (PowerShell)

    Expand-Archive -Path .\APK_NAME.apk -DestinationPath ~\tmp\my_apk_out
    
  3. आपने जिस अस्थायी डायरेक्ट्री में अपनी APK फ़ाइल को एक्सट्रैक्ट किया है उसमें, शेयर किए गए ऑब्जेक्ट (.so) फ़ाइलों के लिए lib डायरेक्ट्री का कॉन्टेंट देखें. ये वही शेयर की गई ऑब्जेक्ट फ़ाइलें हैं जो आपको APK Analyzer का इस्तेमाल करके नेटिव लाइब्रेरी की पहचान करने के दौरान दिखती हैं. हर शेयर की गई ऑब्जेक्ट फ़ाइल पर यह कमांड चलाएं:

    Linux या macOS

    SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-objdump -p SHARED_OBJECT_FILE.so | grep LOAD
    

    Windows (PowerShell)

    SDK_ROOT_LOCATION\Android\sdk\ndk\NDK_VERSION\toolchains\llvm\prebuilt\windows-x86_64\bin\llvm-objdump.exe -p SHARED_OBJECT_FILE.so | Select-String -Pattern "LOAD"
    

    यहां SDK_ROOT_LOCATION उस डायरेक्ट्री का पाथ है जहां आपने Android SDK इंस्टॉल किया है, SHARED_OBJECT_FILE उस शेयर की गई ऑब्जेक्ट फ़ाइल का नाम है जिसकी जांच की जा रही है, और NDK_VERSION Android NDK का वह वर्शन है जिसे आपने इंस्टॉल किया है. उदाहरण के लिए, 28.0.12433566. जांच की गई हर फ़ाइल के लिए, आउटपुट कुछ इस तरह दिखेगा:

    LOAD off    0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**14
    LOAD off    0x0000000000042a90 vaddr 0x0000000000043a90 paddr 0x0000000000043a90 align 2**14
    LOAD off    0x0000000000046230 vaddr 0x0000000000048230 paddr 0x0000000000048230 align 2**14
    
  4. आउटपुट लाइनों की जांच करें. इससे यह पक्का किया जा सकेगा कि लोड सेगमेंट में 2**14 से कम वैल्यू नहीं हैं. अगर लोड सेगमेंट 2**13, 2**12 या इससे कम वैल्यू वाले हैं, तो आपको उन लाइब्रेरी के लिए पैकेजिंग अपडेट करनी होगी. इसके बाद, अपने ऐप्लिकेशन को फिर से कंपाइल करें और इस सेक्शन में दिए गए चरणों का पालन करके, फिर से जांच करें.

  5. इसके बाद, अपने ऐप्लिकेशन की APK फ़ाइल पर zipalign कमांड-लाइन टूल चलाएं:

    Linux या macOS

    SDK_ROOT_LOCATION/Android/sdk/build-tools/35.0.0/zipalign -v -c -P 16 4 APK_NAME.apk
    

    Windows (PowerShell)

    SDK_ROOT_LOCATION\Android\sdk\build-tools\35.0.0\zipalign.exe -v -c -P 16 4 APK_NAME.apk
    

    यहां SDK_ROOT_LOCATION उस डायरेक्ट्री का पाथ है जहां आपने Android SDK इंस्टॉल किया है. साथ ही, APK_NAME आपके ऐप्लिकेशन की APK फ़ाइल का नाम है. अगर सभी शेयर की गई लाइब्रेरी सही तरीके से अलाइन की गई हैं, तो आउटपुट की आखिरी लाइन में "पुष्टि हो गई" लिखा होगा.

    अगर पुष्टि नहीं हो पाती है, तो शेयर की गई कुछ लाइब्रेरी को फिर से अलाइन करना होगा. इसलिए, आपको उन लाइब्रेरी के लिए पैकेजिंग अपडेट करनी होगी. इसके बाद, अपने ऐप्लिकेशन को फिर से कंपाइल करें और इस सेक्शन में दिए गए चरणों का पालन करके, फिर से जांच करें.

RELRO के सुरक्षा फ़्लैग की जांच करना

सुरक्षा से जुड़ी कमियों को कम करने के लिए, आधुनिक लिंकर्स Relocation Read-Only (RELRO) फ़्लैग का इस्तेमाल करते हैं. इससे, शेयर की गई ऑब्जेक्ट फ़ाइल के रिलोकेशन सेक्शन को लोड करने के बाद, रीड-ओनली बनाया जा सकता है. अपने बिल्ड में RELRO फ़्लैग चालू करें.

अगर किसी RELRO सेक्शन का शुरुआती पता और सेगमेंट का साइज़ (MemSize), 16 केबी के साथ अलाइन नहीं किया गया है, तो रनटाइम के दौरान ऐप्लिकेशन क्रैश हो जाता है. ऐसा सेगमेंटेशन फ़ॉल्ट की वजह से होता है. ऐसा तब होता है, जब .so फ़ाइल को NDK टूल चेन r27 और उससे पहले के वर्शन के साथ बनाया गया हो. हालांकि, ऐसा ज़रूरी फ़्लैग चालू किए बिना किया गया हो.

शेयर की गई हर ऑब्जेक्ट फ़ाइल (Linux या macOS) पर यह कमांड चलाएं:

SDK_ROOT_LOCATION/Android/sdk/ndk/NDK_VERSION/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-readelf -Wl SHARED_OBJECT_FILE.so | grep 'RELRO\|Type'

अगर कोई RELRO सेगमेंट मौजूद है, तो GNU_RELRO स्ट्रिंग प्रिंट की जाती है.

इसके बाद, RELRO सेगमेंट के अलाइनमेंट की जांच करें. इसके लिए, इसके वर्चुअल ऑफ़सेट पते (VirtAddr) को सेगमेंट की मेमोरी साइज़ (MemSiz) के साथ जोड़ें और फिर 16 केबी (0x4000) से भाग दें. अगर शेषफल (मॉड्यूलो) शून्य है, तो RELRO सेगमेंट 16 केबी अलाइन किया गया है.

यहां अलाइन न की गई .so फ़ाइल का उदाहरण दिया गया है:

Type           Offset   VirtAddr           PhysAddr           FileSiz MemSiz  Flg Align  
GNU_RELRO      0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x01510 0x01510 R   0x1

फ़ॉर्मूला: (VirtAddr + MemSiz) % 0x4000 == 0

नतीजा: (0xdfaf0 + 0x01510) % 0x4000 = 0xE1000 % 0x4000 == 0x1000

0x1000 शून्य नहीं है. इसलिए, यह .so फ़ाइल 16 केबी के मुताबिक नहीं है. RELRO प्रोटेक्शन की रेंज DC000 (पिछला पेज ब्रेक) से E4000 तक सिर्फ़ पढ़ने के लिए होती है. हालांकि, Android Linker को E1000 से E4000 तक की सब-रेंज में लिखने की अनुमति चाहिए होती है. इस वजह से, सेगमेंटेशन फ़ॉल्ट होता है. इस मामले में, .so फ़ाइल को फिर से बनाएं. इसके लिए, 16 केबी ईएलएफ़ अलाइनमेंट का इस्तेमाल करके अपना ऐप्लिकेशन कंपाइल करें सेक्शन में दिया गया तरीका अपनाएं.

यहां अलाइन की गई .so फ़ाइल का उदाहरण दिया गया है. इसमें RELRO सेगमेंट शामिल है:

Type           Offset   VirtAddr           PhysAddr           FileSiz MemSiz  Flg Align
GNU_RELRO      0x0cfaf0 0x00000000000dfaf0 0x00000000000dfaf0 0x01510 0x00510 R   0x1  

यहां RELRO सेगमेंट के बिना .so फ़ाइल का एक उदाहरण दिया गया है:

Type           Offset   VirtAddr           PhysAddr           FileSiz MemSiz  Flg Align

यह 16 केबी के साथ काम करने वाली .so फ़ाइल है. इसमें कोई RELRO सेगमेंट नहीं है.

अपने ऐप्लिकेशन को 16 केबी मेमोरी वाले डिवाइसों के साथ काम करने के लिए बनाएं

अगर आपका ऐप्लिकेशन नेटिव कोड का इस्तेमाल करता है, तो पक्का करें कि आपका ऐप्लिकेशन 16 केबी डिवाइसों के साथ काम करता हो. इसके लिए, यहां दिए गए सेक्शन में बताया गया तरीका अपनाएं:

  1. शेयर की गई लाइब्रेरी के पैकेजिंग को अपडेट करना
  2. अपने ऐप्लिकेशन को 16 केबी ईएलएफ़ अलाइनमेंट का इस्तेमाल करके कंपाइल करें
  3. कोड ठीक करना और रनटाइम से जुड़ी समस्याएं हल करना
  4. कस्टम मेमोरी ऐलोकेटर को ऑप्टिमाइज़ करना (अगर लागू हो)
  5. एसडीके टूल की जांच करके पता लगाएं कि वे 16 केबी वाले पेज साइज़ के साथ काम करते हैं या नहीं

शेयर की गई लाइब्रेरी के पैकेजिंग को अपडेट करना

AGP के वर्शन 8.5.1 या इसके बाद वाले वर्शन पर अपग्रेड करें. साथ ही, बिना कंप्रेस की गई शेयर की गई लाइब्रेरी का इस्तेमाल करें.

ज़िप अलाइनमेंट की पुष्टि करने के लिए, bundletool का इस्तेमाल करना

अपने बंडल का अलाइनमेंट देखने के लिए, इसका इस्तेमाल करें:

bundletool dump config --bundle=<my .aab>  | grep alignment

अगर आपको PAGE_ALIGNMENT_16K दिखता है, तो इसका मतलब है कि आपके बंडल के लिए 16 केबी ज़िप अलाइनमेंट की ज़रूरत है. अगर आपको PAGE_ALIGNMENT_4K दिखता है, तो इसका मतलब है कि इस AAB से बनाए गए APK में, zip फ़ाइल में 4 केबी वाली अलाइन की गई .so फ़ाइलें होंगी.

AGP का 8.5.1 या इसके बाद का वर्शन

16 केबी वाले डिवाइसों के लिए, कंप्रेस न की गई शेयर की गई लाइब्रेरी के साथ शिप किए गए ऐप्लिकेशन को, उन्हें 16 केबी वाले ज़िप-अलाइन किए गए बाउंड्री पर अलाइन करना होगा. इसके लिए, आपको Android Gradle प्लगिन (AGP) को 8.5.1 या इसके बाद के वर्शन पर अपग्रेड करना होगा. अपग्रेड करने की प्रोसेस के बारे में जानने के लिए, Android Gradle प्लगिन अपग्रेड असिस्टेंट सेक्शन देखें.

AGP का 8.5 या इससे पहले का वर्शन

अगर AGP को 8.5.1 या इसके बाद के वर्शन पर अपग्रेड नहीं किया जा सकता, तो कंप्रेस की गई शेयर की गई लाइब्रेरी का इस्तेमाल करें. अपने Gradle कॉन्फ़िगरेशन को अपडेट करें, ताकि Gradle आपके ऐप्लिकेशन को पैकेज करते समय शेयर की गई लाइब्रेरी को कंप्रेस कर सके. इससे, अलाइन न की गई शेयर की गई लाइब्रेरी की वजह से, ऐप्लिकेशन इंस्टॉल करने में आने वाली समस्याओं से बचा जा सकेगा.

Groovy

अपनी build.gradle फ़ाइल में, यह विकल्प जोड़ें:

android {
  ...
  packagingOptions {
      jniLibs {
        useLegacyPackaging true
      }
  }
}

Kotlin

अपनी build.gradle.kts फ़ाइल में, यह विकल्प जोड़ें:

android {
  ...
  packagingOptions {
      jniLibs {
        useLegacyPackaging = true
      }
  }
}
AGP का 8.0 या इससे पहले का वर्शन

अगर AGP का वर्शन 8.0 या इससे पहले का है, तो आपको gradle.properties फ़ाइल में जाकर, ऐप्लिकेशन बंडलों के लिए बिना कंप्रेस की गई नेटिव लाइब्रेरी का विकल्प भी बंद करना होगा:

android.bundle.enableUncompressedNativeLibs=false

अपने ऐप्लिकेशन को 16 केबी ईएलएफ़ अलाइनमेंट का इस्तेमाल करके कंपाइल करें

16 केबी वाले डिवाइसों पर, आपके ऐप्लिकेशन को चलाने के लिए, शेयर की गई लाइब्रेरी के ईएलएफ़ सेगमेंट को 16 केबी ईएलएफ़ अलाइनमेंट का इस्तेमाल करके सही तरीके से अलाइन करना ज़रूरी है.

अगर आपका गेम Unity गेम इंजन पर चलता है, तो गेम डेवलपर के लिए Unity गाइड देखें. अगर आपका गेम, Unreal गेम इंजन पर चलता है, तो Unreal गाइड देखें.नेटिव गेम इंजन के लिए, इस गाइड को पढ़ना जारी रखें.

अपने ऐप्लिकेशन को 16 केबी ईएलएफ़ अलाइनमेंट का इस्तेमाल करके कंपाइल करने के लिए, यहां दिए गए सेक्शन में से किसी एक में दिया गया तरीका अपनाएं. यह तरीका, Android एनडीके के उस वर्शन के हिसाब से चुनें जिसका इस्तेमाल किया जा रहा है.

Android NDK r28 और इसके बाद के वर्शन

एनडीके के r28 और इसके बाद के वर्शन, डिफ़ॉल्ट रूप से 16 केबी के हिसाब से अलाइन किए जाते हैं.

Android NDK r27 और इससे पहले के वर्शन

Android NDK के r27 या इससे पुराने वर्शन के साथ, 16 केबी अलाइन की गई शेयर की गई लाइब्रेरी को कंपाइल करने के लिए, इन लिंकर फ़्लैग का इस्तेमाल करें:

-Wl,-z,max-page-size=16384
-Wl,-z,common-page-size=16384

यहां अपने बिल्ड सिस्टम की कॉन्फ़िगरेशन फ़ाइलों को अपडेट करने का तरीका बताया गया है:

ndk-build

अगर ndk-build का इस्तेमाल किया जा रहा है, तो 16 केबी ईएलएफ़ अलाइनमेंट की सुविधा चालू करने के लिए, Android.mk को अपडेट करें:

LOCAL_LDFLAGS += -Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384

CMake

अगर CMake का इस्तेमाल किया जा रहा है, तो 16 केबी ईएलएफ़ अलाइनमेंट चालू करने के लिए, CMakeLists.txt को अपडेट करें:

target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
    "-Wl,-z,max-page-size=16384"
    "-Wl,-z,common-page-size=16384"
)

कोड ठीक करना और रनटाइम से जुड़ी समस्याएं हल करना

अगर आपका ऐप्लिकेशन 16 केबी वाले पेज साइज़ के साथ काम करता है, तब भी उसमें गड़बड़ियां हो सकती हैं. ऐसा तब होता है, जब आपके कोड में यह अनुमान लगाया गया हो कि डिवाइस में किसी खास साइज़ का पेज इस्तेमाल किया जा रहा है. इससे बचने के लिए, यह तरीका अपनाएं:

  1. अपने कोड लॉजिक से, PAGE_SIZE कॉन्सटेंट या इंस्टेंस को रेफ़र करने वाली किसी भी हार्ड-कोडेड डिपेंडेंसी को हटाएं. साथ ही, ऐसे इंस्टेंस को भी हटाएं जो यह मानते हैं कि डिवाइस का पेज साइज़ 4 केबी (4096) है.

    इसके बजाय, getpagesize() या sysconf(_SC_PAGESIZE) का इस्तेमाल करें.

  2. mmap() और अन्य ऐसे एपीआई के इस्तेमाल का पता लगाएं जिनके लिए पेज के साथ अलाइन किए गए आर्ग्युमेंट की ज़रूरत होती है. साथ ही, जहां ज़रूरी हो वहां उन्हें विकल्पों से बदलें.

कुछ मामलों में, अगर आपका ऐप्लिकेशन PAGE_SIZE का इस्तेमाल ऐसी वैल्यू के तौर पर करता है जो पेज साइज़ से जुड़ी नहीं है, तो 16 केबी मोड में इस्तेमाल करने पर, आपका ऐप्लिकेशन काम करना बंद नहीं करेगा. हालांकि, अगर इस वैल्यू को MAP_FIXED के बिना mmap के साथ कर्नल को पास किया जाता है, तो कर्नल अब भी पूरे पेज का इस्तेमाल करता है. इससे कुछ मेमोरी बर्बाद हो जाती है. इन वजहों से, NDK r27 और इसके बाद के वर्शन पर 16 केबी मोड चालू होने पर, PAGE_SIZE को तय नहीं किया जाता.

अगर आपका ऐप्लिकेशन PAGE_SIZE का इस्तेमाल इस तरह से करता है और इस वैल्यू को कभी भी सीधे तौर पर कर्नल को नहीं भेजता है, तो PAGE_SIZE का इस्तेमाल करने के बजाय, एक नया वैरिएबल बनाएं. इसका नाम ऐसा रखें जिससे पता चले कि इसका इस्तेमाल अन्य कामों के लिए किया जाता है और यह असली मेमोरी पेज को नहीं दिखाता है.

कस्टम मेमोरी ऐलोकेटर को ऑप्टिमाइज़ करना

16 केबी वाले सिस्टम पर, ऑपरेटिंग सिस्टम जिस फ़िज़िकल मेमोरी को सबसे छोटी यूनिट के तौर पर असाइन करता है वह 4 केबी वाले सिस्टम की तुलना में चार गुना बड़ी होती है. अगर कस्टम ऐलोकेटर को 4 केबी के हिसाब से डिज़ाइन किया गया है, तो यह छोटे ऑब्जेक्ट को कई 16 केबी पेजों में बिखेर सकता है. साथ ही, बेवजह खाली मेमोरी को बनाए रख सकता है. इससे, फ़िज़िकल मेमोरी (आरएसएस) का इस्तेमाल काफ़ी बढ़ सकता है. साथ ही, कंप्रेस की गई स्वैप मेमोरी (ज़ेडआरएएम) की परफ़ॉर्मेंस खराब हो सकती है.

अगर आपका कोड अपने मेमोरी पूल मैनेज करता है, तो इन सुझावों का पालन करें:

1. मेमोरी खाली करने के लिए, बाइट थ्रेशोल्ड को हार्ड-कोड करने से बचें

कई ऐलोकेटर, मेमोरी को ओएस को वापस रिलीज़ करने के लिए, बाइट की तय सीमा का इस्तेमाल करते हैं. इसके लिए, वे madvise(MADV_DONTNEED) का इस्तेमाल करते हैं. उदाहरण के लिए, मेमोरी को सिर्फ़ तब रिलीज़ करें, जब चालू ऑब्जेक्ट 8 केबी से कम जगह लेते हों.

16 केबी वाले सिस्टम पर, 16 बाइट का एक लाइव ऑब्जेक्ट भी पूरे 16 केबी पेज को पिन करता है. यह 8 केबी से ज़्यादा है. इस वजह से, रिलीज़ थ्रेशोल्ड कभी पूरा नहीं होता. साथ ही, ऐलोकेटर कभी भी इस्तेमाल नहीं की गई आस-पास की मेमोरी को कर्नल को वापस नहीं देता.

क्या करना है: पेज रिलीज़ करने के लिए, हार्ड-कोड किए गए बाइट कॉन्स्टेंट का कभी इस्तेमाल न करें. sysconf(_SC_PAGESIZE) का इस्तेमाल करके, पेज के असल साइज़ के आधार पर रनटाइम में, रिलीज़ थ्रेशोल्ड को डाइनैमिक तौर पर स्केल करें.

2. पहले से इस्तेमाल किए जा रहे पेजों को पहले भरें (डेंस-फ़र्स्ट ऐलोकेशन)

अगर कोई ऐलोकेटर, मेमोरी को फ़र्स्ट-इन-फ़र्स्ट-आउट (FIFO) या राउंड-रॉबिन क्रम में बांटता है, तो नए ऐलोकेशन, 16 केबी के कई ऐसे पेजों में बिखर जाते हैं जिनमें कुछ डेटा पहले से मौजूद होता है. पेज पर मौजूद कोई एक ऑब्जेक्ट, फ़िज़िकल रैम में मौजूद सभी 16 केबी को सेव रखता है.

क्या करें: खाली या कम इस्तेमाल किए गए पेजों को छूने से पहले, हमेशा सबसे ज़्यादा भरे हुए (डेंस) पेज या स्लैब से नए ऑब्जेक्ट असाइन करें. पहले से इस्तेमाल किए जा रहे पेजों पर नए एलॉकेशन को फ़ोकस करने से, कम इस्तेमाल किए जाने वाले पेजों में मौजूद सभी ऑब्जेक्ट अपने-आप हट जाते हैं. इससे पूरे 16 केबी पेज को ओएस के लिए रिलीज़ किया जा सकता है.

3. मेमोरी पूल को 16 केबी पर अलाइन करें और पूल के साइज़ को मॉडरेट रखें

4 केबी सिस्टम के लिए डिज़ाइन किए गए मल्टी-पेज स्पैन, 16 केबी कर्नेल पर ज़्यादा अनरिलीज़ की गई मेमोरी स्लैक को सेव कर सकते हैं. इसके अलावा, जिन साइज़ क्लास को 16 केबी में बराबर नहीं बांटा जा सकता वे हर पेज के आखिर में फ़्रैगमेंटेशन की वजह बनती हैं.

क्या करें:

  • पक्का करें कि सभी मेमोरी पूल, स्लैब बाउंड्री, और बफ़र अलाइनमेंट, रनटाइम पेज के साइज़ के सटीक मल्टीपल हों.
  • छोटे ऑब्जेक्ट क्लास के लिए, एक से ज़्यादा पेजों वाले स्पैन के साइज़ का फिर से आकलन करें. इससे, बहुत बड़े स्लैब असाइन करने से बचा जा सकेगा. ये स्लैब, इस्तेमाल न की गई मेमोरी को लॉक कर देते हैं.

4. कैश किए गए बड़े बफ़र के लिए, फ़िज़िकल मेमोरी को तुरंत रिलीज़ करें

कस्टम ऐलोकेटर, अक्सर बड़े बफ़र (> 64 केबी) को इन-मेमोरी पूल में कैश मेमोरी में सेव करते हैं, ताकि उन्हें mmap या munmap सिस्टम कॉल के ओवरहेड के बिना फिर से इस्तेमाल किया जा सके. हालांकि, मेमोरी में इन गंदे बफ़र को बनाए रखने से, इविक्शन टाइमर के इंतज़ार के दौरान कई मेगाबाइट फ़िज़िकल रैम बर्बाद हो जाती है.

क्या करना है: वर्चुअल मेमोरी के पते की रेंज को तेज़ी से फिर से इस्तेमाल करने के लिए रिज़र्व रखें. हालांकि, बफ़र को कैश मेमोरी में वापस भेजते समय, madvise(..., MADV_DONTNEED) या madvise(..., MADV_FREE) को तुरंत कॉल करें. ऑपरेटिंग सिस्टम, फ़िज़िकल रैम को तुरंत वापस ले लेता है. हालांकि, आपका ऐप्लिकेशन वर्चुअल पते का फिर से इस्तेमाल कर सकता है. इसके लिए, उसे फिर से मेमोरी आवंटित करने की ज़रूरत नहीं होती.

5. ZRAM कंप्रेशन के लिए मेमोरी को असाइन करने के बजाय, उसे खाली करें

Android, कंप्रेस किए गए स्वैप (ZRAM) का इस्तेमाल करता है, ताकि बैकग्राउंड में चल रहे ऐप्लिकेशन को मेमोरी में रखा जा सके. अगर 16 केबी वाले डिवाइसों पर किसी पेज में एक भी लाइव ऑब्जेक्ट मौजूद है, तो पूरा 16 केबी वाला पेज मेमोरी में बना रहता है या उसे ZRAM में स्वैप कर दिया जाता है. पेज के उन हिस्सों पर बचा हुआ गार्बेज डेटा (जैसे कि पुराने पॉइंटर और स्ट्रिंग), जिन्हें पहले फ़्री किया गया था, ठीक से कंप्रेस नहीं होता.

अगर आपका ऐलोकेटर मेमोरी को शून्य पर सेट करता है (जैसे, सुरक्षा या शून्य पर सेट की गई मेमोरी के लिए), तो मेमोरी को ऐलोकेट करने के बजाय, उसे डीऐलोकेट करने पर शून्य पर सेट करें (free()):

  • पिन किए गए पेजों पर कम खर्च होता है: 16 केबी के आंशिक रूप से भरे गए पेजों पर मौजूद खाली मेमोरी, ZRAM में लगभग पूरी तरह से कंप्रेस हो जाती है. इसलिए, पिन किए गए पेज फ़िज़िकल स्वैप स्पेस को बर्बाद नहीं करते.
  • कैश मेमोरी का कम इस्तेमाल: free() को कॉल करने के समय, मेमोरी पहले से ही सीपीयू कैश मेमोरी में मौजूद होती है. इससे बाद में कैश मेमोरी के हिट न होने की समस्या से बचा जा सकता है.

सुझावों की खास जानकारी

जगह सुझाव अनुमानित असर
डेटा मिटाने के थ्रेशोल्ड sysconf(_SC_PAGESIZE) का इस्तेमाल करके, रिलीज़ के थ्रेशोल्ड को डाइनैमिक तरीके से स्केल करें. यह कुकी, रिलीज़ लॉजिक को हमेशा के लिए डेडलॉक होने से रोकती है.
एलॉकेशन ऑर्डर सबसे पहले, सबसे ज़्यादा (लगभग पूरी) जगह वाले पेज या स्लैब से जगह असाइन करें. इससे ऐक्टिव ऑब्जेक्ट को एक साथ पैक करके, रेज़िडेंट मेमोरी (आरएसएस) को कम किया जाता है.
स्पैन साइज़िंग साइज़ क्लास को 16 केबी के मल्टीपल के साथ अलाइन करें और बड़े स्लैब का इस्तेमाल न करें. इससे टेल-पेज फ़्रैगमेंटेशन की समस्या खत्म हो जाती है और मेमोरी स्लैक कम हो जाता है.
बफ़र कैश मेमोरी बड़े बफ़र को कैश मेमोरी में सेव करते समय, Call madvise(MADV_DONTNEED) को तुरंत कॉल करें. इससे, इस्तेमाल न की जा रही रैम का इस्तेमाल कम होता है. साथ ही, वर्चुअल रैम को तेज़ी से दोबारा इस्तेमाल किया जा सकता है.
स्वैप / ज़ेडआरएएम मेमोरी को ऐलोकेट करने के बजाय, free() पर मेमोरी को शून्य करें. इससे ZRAM के कंप्रेस करने के अनुपात बेहतर होते हैं, ताकि पिन किए गए पेजों पर कम खर्च हो.

देखें कि एसडीके, 16 केबी वाले पेज साइज़ के साथ काम करते हैं या नहीं

कई एसडीके, 16 केबी पेज साइज़ के साथ काम करते हैं. खास तौर पर, अगर आपने उन्हें खुद बनाया है या आपको हाल ही में प्रीबिल्ट एसडीके मिले हैं. हालांकि, कुछ एसडीके प्रीबिल्ट या एसडीके वर्शन 16 केबी के साथ काम नहीं करते. इसलिए, आपको एसडीके टूल की सेवा देने वाली हर कंपनी की वेबसाइट पर जाकर यह देखना चाहिए कि 16 केबी के साथ कौनसा वर्शन इस्तेमाल किया जा सकता है.

अपने ऐप्लिकेशन को उन डिवाइसों पर टेस्ट करें जो 16 केबी वाले पेज साइज़ पर काम करते हों

16 केबी मेमोरी वाले डिवाइसों के साथ काम करने वाला ऐप्लिकेशन बनाने के बाद, आपको उसे 16 केबी मेमोरी वाले डिवाइसों पर टेस्ट करना होगा. इससे यह पता चलेगा कि ऐप्लिकेशन में कोई रिग्रेशन तो नहीं हो रहा है. ऐसा करने के लिए, इन चरणों का अनुसरण करें:

  1. Android 15 SDK या इसके बाद का वर्शन सेट अप करें.

  2. इनमें से कोई एक टेस्टिंग एनवायरमेंट सेट अप करें:

  3. अपने टेस्ट डिवाइस को चालू करें. इसके बाद, यह पुष्टि करने के लिए कि यह 16 केबी वाले एनवायरमेंट का इस्तेमाल कर रहा है, यह कमांड चलाएं:

    adb shell getconf PAGE_SIZE
    

    इस कमांड से 16384 वैल्यू मिलनी चाहिए.

  4. यह पुष्टि करने के लिए कि आपका ऐप्लिकेशन 16 केबी के साथ अलाइन है, नीचे दी गई zipalign कमांड चलाएं. यहां APK_NAME, आपके ऐप्लिकेशन की APK फ़ाइल का नाम है:

    zipalign -c -P 16 -v 4 APK_NAME.apk
    
  5. अपने ऐप्लिकेशन की अच्छी तरह से जांच करें. साथ ही, उन सभी जगहों पर फ़ोकस करें जिन पर पेज के साइज़ के हिसाब से कोड इंस्टेंस में बदलाव करने का असर पड़ सकता है.

Android Emulator को 16 केबी वाली सिस्टम इमेज के साथ सेट अप करना

Android Emulator का इस्तेमाल करके, 16 केबी वाला एनवायरमेंट सेट अप करने के लिए, यह तरीका अपनाएं:

  1. Android Studio में, Tools > SDK Manager पर क्लिक करें.
  2. एसडीके प्लैटफ़ॉर्म टैब में, पैकेज की जानकारी दिखाएं को चुनें. इसके बाद, Android VanillaIceCream या उसके बाद के वर्शन वाले सेक्शन को बड़ा करें. इसके बाद, आपको जो वर्चुअल डिवाइस बनाने हैं उनके हिसाब से, नीचे दी गई एक या दोनों एम्युलेटर सिस्टम इमेज चुनें:

    • Google APIs Experimental 16 केबी पेज साइज़ ARM 64 v8a सिस्टम इमेज
    • Google APIs Experimental 16 KB Page Size Intel x86_64 Atom System Image
    Android Studio में एसडीके मैनेजर का इस्तेमाल करके, 16 केबी वाली एम्युलेटर सिस्टम इमेज डाउनलोड करना
  3. आपने जो सिस्टम इमेज चुनी हैं उन्हें डाउनलोड करने के लिए, लागू करें > ठीक है पर क्लिक करें.

  4. Android 15 के लिए वर्चुअल डिवाइस सेट अप करने का तरीका अपनाएं. इसके बाद, जब आपको सिस्टम इमेज चुनने के लिए कहा जाए, तब डाउनलोड की गई 16 केबी वाली सिस्टम इमेज चुनें. अगर सिस्टम इमेज अपने-आप नहीं दिखती है, तो 16 केबी की सिस्टम इमेज को अन्य इमेज टैब में जाकर देखा जा सकता है.

    'अन्य इमेज' टैब में जाकर, 16 केबी वाली एम्युलेटर इमेज ढूंढें

एम्युलेटर लॉन्च करना

Android Emulator और वर्चुअल डिवाइसों को सेट अप करने के बाद, टारगेट डिवाइस के मेन्यू से या कमांड लाइन से एम्युलेटर लॉन्च करें.

डेवलपर के लिए सेटिंग और टूल का इस्तेमाल करके, किसी डिवाइस पर 16 केबी मोड चालू करना

डिवाइस को 16 केबी मोड में बूट करने के लिए, डेवलपर विकल्प में जाकर 16 केबी पेज साइज़ के साथ बूट करें को टॉगल करें.

Android 15 के QPR वर्शन में, डेवलपर विकल्प का इस्तेमाल किया जा सकता है. यह विकल्प, कुछ डिवाइसों पर उपलब्ध होता है. इससे डिवाइस को 16 केबी मोड में बूट किया जा सकता है और डिवाइस पर टेस्टिंग की जा सकती है. डेवलपर के लिए सेटिंग और टूल का इस्तेमाल करने से पहले, सेटिंग > सिस्टम > सॉफ़्टवेयर अपडेट पर जाएं और उपलब्ध अपडेट लागू करें.

यह डेवलपर विकल्प, इन डिवाइसों पर उपलब्ध है:

  • Pixel 8 और 8 Pro (Android 15 QPR1 या उसके बाद के वर्शन के साथ)

  • Pixel 8a (Android 15 QPR1 या इसके बाद के वर्शन के साथ)

  • Pixel 9, 9 Pro, और 9 Pro XL (Android 15 QPR2 या इसके बाद के वर्शन के साथ)

  • Pixel 9a (Android 16 या इसके बाद के वर्शन के साथ)

16 केबी बैककॉम्पैट मोड

पेज साइज़ कंपैटबिलिटी मोड में चेतावनी

पेज साइज़ कंपैटबिलिटी मोड में चेतावनी

16 केबी वाला बैककंपैट विकल्प तब उपलब्ध होता है, जब डिवाइस 16 केबी कर्नेल के साथ चल रहा हो. पैकेज मैनेजर, ऐप्लिकेशन को 16 केबी वाले बैककंपैट मोड में तब चलाता है, जब ये शर्तें पूरी होती हैं:

  • अगर ऐप्लिकेशन में 4 केबी के LOAD सेगमेंट अलाइनमेंट वाली ELF फ़ाइलें (.so एक्सटेंशन वाली) हैं.
  • अगर ज़िप किए गए APK में, बिना कंप्रेस की गई ऐसी ELF फ़ाइलें हैं जिनका साइज़ 4 केबी है और जो ZIP अलाइन की गई हैं.

अगर पैकेज मैनेजर ने किसी ऐप्लिकेशन के लिए 16 केबी बैककंपैट मोड चालू किया है, तो ऐप्लिकेशन को पहली बार लॉन्च करने पर एक चेतावनी दिखती है. इसमें बताया जाता है कि ऐप्लिकेशन 16 केबी बैककंपैट मोड में चल रहा है.

16 केबी बैककॉम्पैट मोड की मदद से, कुछ ऐप्लिकेशन काम कर सकते हैं. हालांकि, बेहतर तरीके से काम करने और स्थिरता के लिए, ऐप्लिकेशन को 16 केबी के हिसाब से अलाइन किया जाना चाहिए.

ऐप्लिकेशन की जानकारी वाले पेज पर, ऐडवांस में जाकर, ऐप्लिकेशन को पेज साइज़ कंपैटबिलिटी मोड में चलाएं सेटिंग को टॉगल करें. इससे किसी ऐप्लिकेशन के लिए, 16 केबी वाला बैककंपैट मोड चालू या बंद किया जा सकता है. यह सेटिंग सिर्फ़ तब दिखती है, जब डिवाइस 16 केबी वाले पेज साइज़ पर चल रहा हो.

पेज साइज़ कंपैटबिलिटी मोड की सेटिंग

पेज साइज़ कंपैटबिलिटी मोड की सेटिंग

डिवाइस पर मौजूद हर ऐप्लिकेशन के लिए, 16 केबी वाले पेज साइज़ के साथ काम करने की सुविधा को डिफ़ॉल्ट रूप से चालू करने के लिए:

adb shell setprop bionic.linker.16kb.app_compat.enabled true
adb shell setprop pm.16kb.app_compat.disabled false

डिवाइस पर मौजूद हर ऐप्लिकेशन के लिए, 16 केबी वाले बैकवर्ड कंपैटिबिलिटी मोड को बंद करने के लिए:

adb shell setprop bionic.linker.16kb.app_compat.enabled false
adb shell setprop pm.16kb.app_compat.disabled true

Android 17 में, हर ऐप्लिकेशन के लिए 16 केबी बैककंपैट को बंद किया जा सकता है. साथ ही, किसी भी ऐसे बाइनरी को तुरंत बंद किया जा सकता है जो काम नहीं करता:

    adb shell setprop bionic.linker.16kb.app_compat.enabled fatal
    adb shell setprop pm.16kb.app_compat.disabled true

किसी ऐप्लिकेशन के AndroidManifest.xml में, बैककंपैट मोड को चालू या बंद करने के लिए, android:pageSizeCompat प्रॉपर्टी को चालू या बंद पर सेट करें. इस प्रॉपर्टी को सेट करने पर, ऐप्लिकेशन लॉन्च होने पर, बैककंपैट मोड की चेतावनियां नहीं दिखाएगा.