बूट टाइम्स का अनुकूलन

यह दस्तावेज़ विशिष्ट Android उपकरणों के लिए बूट समय में सुधार के लिए भागीदार मार्गदर्शन प्रदान करता है। बूट समय सिस्टम प्रदर्शन का एक महत्वपूर्ण घटक है क्योंकि उपयोगकर्ताओं को डिवाइस का उपयोग करने से पहले बूट पूरा होने तक इंतजार करना होगा। कारों जैसे उपकरणों के लिए जहां कोल्ड बूट-अप अधिक बार होता है, त्वरित बूट समय होना महत्वपूर्ण है (किसी को भी नेविगेशन गंतव्य पर इनपुट करने के लिए दर्जनों सेकंड तक इंतजार करना पसंद नहीं है)।

एंड्रॉइड 8.0 विभिन्न घटकों में कई सुधारों का समर्थन करके कम बूट समय की अनुमति देता है। निम्न तालिका इन प्रदर्शन सुधारों का सारांश प्रस्तुत करती है (जैसा कि Google Pixel और Pixel XL उपकरणों पर मापा गया है)।

अवयव सुधार
बूटलोडर
  • UART लॉग को हटाकर 1.6 सेकंड बचाया गया
  • GZIP से LZ4 में बदलकर 0.4s की बचत की
डिवाइस कर्नेल
  • अप्रयुक्त कर्नेल कॉन्फ़िगरेशन को हटाकर और ड्राइवर का आकार कम करके 0.3s बचाया गया
  • डीएम-वेरिटी प्रीफ़ेच ऑप्टिमाइज़ेशन के साथ 0.3 सेकंड बचाया गया
  • ड्राइवर में अनावश्यक प्रतीक्षा/परीक्षण को हटाने के लिए 0.15 सेकेंड बचाया गया
  • CONFIG_CC_OPTIMIZE_FOR_SIZE को हटाने के लिए 0.12s सहेजे गए
आई/ओ ट्यूनिंग
  • सामान्य बूट पर 2s सहेजे गए
  • पहले बूट पर 25 की बचत हुई
init.*.rc
  • init कमांड को समान्तर करके 1.5s की बचत की
  • जाइगोट को जल्दी शुरू करके 0.25 सेकेंड की बचत की
  • सीपीयूसेट ट्यून द्वारा 0.22 सेकंड बचाया गया
बूट एनीमेशन
  • बिना fsck ट्रिगर के बूट पर 2s पहले शुरू किया गया, fsck ट्रिगर बूट के साथ बूट पर बहुत बड़ा
  • बूट एनिमेशन को तत्काल बंद करके Pixel XL पर 5s सहेजा गया
SELinux नीति Genfscon द्वारा 0.2s बचाया गया

बूटलोडर का अनुकूलन

बेहतर बूट समय के लिए बूटलोडर को अनुकूलित करने के लिए:

  • लॉगिंग के लिए:
    • UART में लॉग लेखन अक्षम करें क्योंकि बहुत अधिक लॉगिंग के साथ इसमें लंबा समय लग सकता है। (Google Pixel उपकरणों पर, हमने पाया कि यह बूटलोडर 1.5s को धीमा कर देता है)।
    • केवल त्रुटि स्थितियों को लॉग करें और पुनर्प्राप्त करने के लिए एक अलग तंत्र के साथ अन्य जानकारी को मेमोरी में संग्रहीत करने पर विचार करें।
  • कर्नेल डीकंप्रेसन के लिए, GZIP (उदाहरण पैच ) के बजाय समकालीन हार्डवेयर के लिए LZ4 का उपयोग करने पर विचार करें। ध्यान रखें कि विभिन्न कर्नेल संपीड़न विकल्पों में अलग-अलग लोडिंग और डीकंप्रेसन समय हो सकता है, और कुछ विकल्प आपके विशिष्ट हार्डवेयर के लिए दूसरों की तुलना में बेहतर काम कर सकते हैं।
  • डिबाउंसिंग/विशेष मोड प्रविष्टि के लिए अनावश्यक प्रतीक्षा समय की जाँच करें और उन्हें कम करें।
  • बूटलोडर में बिताए गए बूट समय को सीएमडीलाइन के रूप में कर्नेल में पास करें।
  • सीपीयू घड़ी की जाँच करें और कर्नेल लोडिंग और I/O आरंभ करने के लिए समानांतरीकरण (मल्टी-कोर समर्थन की आवश्यकता) पर विचार करें।

I/O दक्षता का अनुकूलन

बूट समय को तेज़ बनाने के लिए I/O दक्षता में सुधार करना महत्वपूर्ण है, और कुछ भी अनावश्यक पढ़ना बूट के बाद तक स्थगित कर दिया जाना चाहिए (Google पिक्सेल पर, बूट पर लगभग 1.2GB डेटा पढ़ा जाता है)।

फ़ाइल सिस्टम को ट्यून करना

जब किसी फ़ाइल को शुरुआत से पढ़ा जाता है या जब ब्लॉक को क्रमिक रूप से पढ़ा जाता है, तो लिनक्स कर्नेल रीड अहेड किक करता है, जिससे विशेष रूप से बूटिंग के लिए I/O शेड्यूलर पैरामीटर को ट्यून करना आवश्यक हो जाता है (जिसमें सामान्य अनुप्रयोगों की तुलना में एक अलग वर्कलोड लक्षण वर्णन होता है)।

जो डिवाइस निर्बाध (ए/बी) अपडेट का समर्थन करते हैं, वे पहली बार बूट पर फ़ाइल सिस्टम ट्यूनिंग से बहुत लाभान्वित होते हैं (उदाहरण के लिए Google Pixel पर 20s)। एक उदाहरण के रूप में, हमने Google Pixel के लिए निम्नलिखित मापदंडों को ट्यून किया है:

on late-fs
  # boot time fs tune
    # boot time fs tune
    write /sys/block/sda/queue/iostats 0
    write /sys/block/sda/queue/scheduler cfq
    write /sys/block/sda/queue/iosched/slice_idle 0
    write /sys/block/sda/queue/read_ahead_kb 2048
    write /sys/block/sda/queue/nr_requests 256
    write /sys/block/dm-0/queue/read_ahead_kb 2048
    write /sys/block/dm-1/queue/read_ahead_kb 2048

on property:sys.boot_completed=1
    # end boot time fs tune
    write /sys/block/sda/queue/read_ahead_kb 512
    ...

मिश्रित

  • कर्नेल कॉन्फ़िगरेशन DM_VERITY_HASH_PREFETCH_MIN_SIZE (डिफ़ॉल्ट आकार 128 है) का उपयोग करके डीएम-वेरिटी हैश प्रीफ़ेच आकार चालू करें।
  • बेहतर फ़ाइल सिस्टम स्थिरता और हर बूट पर होने वाली फ़ोर्स्ड चेक के लिए, BoardConfig.mk में TARGET_USES_MKE2FS सेट करके नए ext4 जेनरेशन टूल का उपयोग करें।

I/O का विश्लेषण

बूट के दौरान I/O गतिविधियों को समझने के लिए, कर्नेल फ़ट्रेस डेटा का उपयोग करें (सिस्ट्रेस द्वारा भी उपयोग किया जाता है):

trace_event=block,ext4 in BOARD_KERNEL_CMDLINE

प्रत्येक फ़ाइल के लिए फ़ाइल पहुंच को तोड़ने के लिए, कर्नेल में निम्नलिखित परिवर्तन करें (केवल विकास कर्नेल; उत्पादन कर्नेल में उपयोग न करें):

diff --git a/fs/open.c b/fs/open.c
index 1651f35..a808093 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -981,6 +981,25 @@
 }
 EXPORT_SYMBOL(file_open_root);
 
+static void _trace_do_sys_open(struct file *filp, int flags, int mode, long fd)
+{
+       char *buf;
+       char *fname;
+
+       buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!buf)
+               return;
+       fname = d_path(&filp-<f_path, buf, PAGE_SIZE);
+
+       if (IS_ERR(fname))
+               goto out;
+
+       trace_printk("%s: open(\"%s\", %d, %d) fd = %ld, inode = %ld\n",
+                     current-<comm, fname, flags, mode, fd, filp-<f_inode-<i_ino);
+out:
+       kfree(buf);
+}
+
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
 {
 	struct open_flags op;
@@ -1003,6 +1022,7 @@
 		} else {
 			fsnotify_open(f);
 			fd_install(fd, f);
+			_trace_do_sys_open(f, flags, mode, fd);

बूट प्रदर्शन का विश्लेषण करने में सहायता के लिए निम्नलिखित स्क्रिप्ट का उपयोग करें।

  • system/extras/boottime_tools/bootanalyze/bootanalyze.py बूट प्रक्रिया में महत्वपूर्ण चरणों के विवरण के साथ बूट समय को मापता है।
  • system/extras/boottime_tools/io_analysis/check_file_read.py boot_trace प्रत्येक फ़ाइल के लिए एक्सेस जानकारी प्रदान करता है।
  • system/extras/boottime_tools/io_analysis/check_io_trace_all.py boot_trace सिस्टम-स्तरीय ब्रेकडाउन देता है।

init.*.rc को अनुकूलित करना

Init कर्नेल से फ्रेमवर्क स्थापित होने तक का पुल है, और डिवाइस आमतौर पर विभिन्न init चरणों में कुछ सेकंड बिताते हैं।

कार्यों को समानांतर रूप से चलाना

हालाँकि वर्तमान Android init कमोबेश एकल थ्रेडेड प्रक्रिया है, फिर भी आप समानांतर में कुछ कार्य कर सकते हैं।

  • शेल स्क्रिप्ट सेवा में धीमी कमांड निष्पादित करें और बाद में विशिष्ट संपत्ति की प्रतीक्षा करके उसमें शामिल हों। एंड्रॉइड 8.0 एक नए wait_for_property कमांड के साथ इस उपयोग के मामले का समर्थन करता है।
  • Init में धीमे संचालन को पहचानें। सिस्टम init कमांड exec/wait_for_prop या लंबे समय तक चलने वाली किसी भी कार्रवाई को लॉग करता है (एंड्रॉइड 8.0 में, कोई भी कमांड 50 एमएस से अधिक लेता है)। उदाहरण के लिए:
    init: Command 'wait_for_coldboot_done' action=wait_for_coldboot_done returned 0 took 585.012ms

    इस लॉग की समीक्षा करने से सुधार के अवसर का संकेत मिल सकता है।

  • सेवाएँ प्रारंभ करें और परिधीय उपकरणों को महत्वपूर्ण पथ में शीघ्र सक्षम करें। उदाहरण के लिए, कुछ एसओसी को सरफेसफ्लिंगर शुरू करने से पहले सुरक्षा-संबंधी सेवाएं शुरू करने की आवश्यकता होती है। जब ServiceManager "सेवा की प्रतीक्षा करें" लौटाता है तो सिस्टम लॉग की समीक्षा करें - यह आमतौर पर एक संकेत है कि एक आश्रित सेवा को पहले शुरू किया जाना चाहिए।
  • init.*.rc में किसी भी अप्रयुक्त सेवा और कमांड को हटा दें। आरंभिक चरण में उपयोग नहीं की गई किसी भी चीज़ को बूट पूर्ण होने के लिए स्थगित कर दिया जाना चाहिए।

नोट: प्रॉपर्टी सेवा init प्रक्रिया का हिस्सा है, इसलिए यदि init बिल्टइन कमांड में व्यस्त है तो बूट के दौरान setproperty कॉल करने में लंबी देरी हो सकती है।

शेड्यूलर ट्यूनिंग का उपयोग करना

प्रारंभिक बूट के लिए शेड्यूलर ट्यूनिंग का उपयोग करें। Google पिक्सेल से उदाहरण:

on init
    # boottime stune
    write /dev/stune/schedtune.prefer_idle 1
    write /dev/stune/schedtune.boost 100
    on property:sys.boot_completed=1
    # reset stune
    write /dev/stune/schedtune.prefer_idle 0
    write /dev/stune/schedtune.boost 0

    # or just disable EAS during boot
    on init
    write /sys/kernel/debug/sched_features NO_ENERGY_AWARE
    on property:sys.boot_completed=1
    write /sys/kernel/debug/sched_features ENERGY_AWARE

कुछ सेवाओं को बूट के दौरान प्राथमिकता बढ़ाने की आवश्यकता हो सकती है। उदाहरण:

init.zygote64.rc:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
...

युग्मनज का जल्दी प्रारंभ होना

फ़ाइल-आधारित एन्क्रिप्शन वाले डिवाइस ज़ीगोट-स्टार्ट ट्रिगर पर ज़ीगोट को पहले शुरू कर सकते हैं (डिफ़ॉल्ट रूप से, ज़ीगोट को क्लास मेन पर लॉन्च किया जाता है, जो ज़ीगोट-स्टार्ट की तुलना में बहुत बाद में होता है)। ऐसा करते समय, सुनिश्चित करें कि ज़ीगोट को सभी सीपीयू में चलने की अनुमति दी जाए (क्योंकि गलत सीपीयूसेट सेटिंग ज़ीगोट को विशिष्ट सीपीयू में चलने के लिए मजबूर कर सकती है)।

बिजली बचत अक्षम करें

डिवाइस बूटिंग के दौरान, यूएफएस और/या सीपीयू गवर्नर जैसे घटकों के लिए पावर सेविंग सेटिंग को अक्षम किया जा सकता है।

सावधानी: दक्षता के लिए चार्जर मोड में पावर सेविंग सक्षम होनी चाहिए।

on init
    # Disable UFS powersaving
    write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 0
    write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 0
    write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 0
    write /sys/module/lpm_levels/parameters/sleep_disabled Y
on property:sys.boot_completed=1
    # Enable UFS powersaving
    write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 1
    write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 1
    write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 1
    write /sys/module/lpm_levels/parameters/sleep_disabled N
on charger
    # Enable UFS powersaving
    write /sys/devices/soc/${ro.boot.bootdevice}/clkscale_enable 1
    write /sys/devices/soc/${ro.boot.bootdevice}/clkgate_enable 1
    write /sys/devices/soc/${ro.boot.bootdevice}/hibern8_on_idle_enable 1
    write /sys/class/typec/port0/port_type sink
    write /sys/module/lpm_levels/parameters/sleep_disabled N

गैर-महत्वपूर्ण आरंभीकरण को स्थगित करें

ZRAM जैसे गैर-महत्वपूर्ण आरंभीकरण को Boot_complete के लिए स्थगित किया जा सकता है।

on property:sys.boot_completed=1
   # Enable ZRAM on boot_complete
   swapon_all /vendor/etc/fstab.${ro.hardware}

बूट एनीमेशन का अनुकूलन

बूट एनीमेशन को अनुकूलित करने के लिए निम्नलिखित युक्तियों का उपयोग करें।

शीघ्र प्रारंभ को कॉन्फ़िगर करना

एंड्रॉइड 8.0 यूजरडेटा विभाजन को माउंट करने से पहले बूट एनीमेशन शुरू करने में सक्षम बनाता है। हालाँकि, एंड्रॉइड 8.0 में नई ext4 टूल श्रृंखला का उपयोग करते समय भी, सुरक्षा कारणों से fsck अभी भी समय-समय पर चालू हो जाता है, जिससे बूटएनिमेशन सेवा शुरू करने में देरी होती है।

बूटएनिमेशन को जल्दी शुरू करने के लिए, fstab माउंट को दो चरणों में विभाजित करें:

  • प्रारंभिक चरण में, केवल विभाजन माउंट करें (जैसे system/ और vendor/ ) जिन्हें रन चेक की आवश्यकता नहीं है, फिर बूट एनीमेशन सेवाएं और इसकी निर्भरताएं (जैसे सर्विसमैनेजर और सरफेसफ्लिंगर) शुरू करें।
  • दूसरे चरण में, विभाजन माउंट करें (जैसे data/ ) जिसके लिए रन चेक की आवश्यकता होती है।

एफएससीके की परवाह किए बिना बूट एनीमेशन बहुत तेजी से (और निरंतर समय में) शुरू किया जाएगा।

स्वच्छ समापन

निकास संकेत प्राप्त करने के बाद, बूटएनीमेशन अंतिम भाग निभाता है, जिसकी लंबाई बूट समय को धीमा कर सकती है। एक सिस्टम जो तेजी से बूट होता है उसे लंबे एनिमेशन की कोई आवश्यकता नहीं होती है जो किए गए किसी भी सुधार को प्रभावी ढंग से छिपा सकता है। हम रिपीटिंग लूप और फिनाले दोनों को छोटा बनाने की सलाह देते हैं।

SELinux का अनुकूलन

बेहतर बूट समय के लिए SELinux को अनुकूलित करने के लिए निम्नलिखित युक्तियों का उपयोग करें।

  • स्वच्छ रेगुलर एक्सप्रेशन (रेगेक्स) का उपयोग करेंfile_contexts में sys/devices के लिए SELinux नीति का मिलान करते समय खराब रूप से निर्मित रेगेक्स बहुत अधिक ओवरहेड का कारण बन सकता है। उदाहरण के लिए, रेगेक्स /sys/devices/.*abc.*(/.*)? गलती से उन सभी /sys/devices उपनिर्देशिकाओं के स्कैन को बाध्य करता है जिनमें "abc" शामिल है, जिससे /sys/devices/abc और /sys/devices/xyz/abc दोनों के लिए मिलान सक्षम हो जाता है। इस रेगेक्स को /sys/devices/[^/]*abc[^/]*(/.*)? केवल /sys/devices/abc के लिए मिलान सक्षम करेगा।
  • लेबल को genfscon पर ले जाएँ । यह मौजूदा SELinux सुविधा फ़ाइल-मिलान उपसर्गों को SELinux बाइनरी में कर्नेल में भेजती है, जहां कर्नेल उन्हें कर्नेल-जनरेटेड फ़ाइल सिस्टम पर लागू करता है। यह गलत लेबल वाली कर्नेल-निर्मित फ़ाइलों को ठीक करने में भी मदद करता है, जिससे पुन: लेबलिंग होने से पहले इन फ़ाइलों तक पहुंचने का प्रयास करने वाली उपयोगकर्तास्पेस प्रक्रियाओं के बीच होने वाली दौड़ की स्थिति को रोका जा सकता है।

उपकरण एवं विधियाँ

अनुकूलन लक्ष्यों के लिए डेटा एकत्र करने में सहायता के लिए निम्नलिखित टूल का उपयोग करें।

बूटचार्ट

बूटचार्ट पूरे सिस्टम के लिए सभी प्रक्रियाओं का सीपीयू और I/O लोड ब्रेकडाउन प्रदान करता है। इसमें सिस्टम छवि के पुनर्निर्माण की आवश्यकता नहीं है और इसे सिस्ट्रेस में गोता लगाने से पहले त्वरित विवेक जांच के रूप में उपयोग किया जा सकता है।

बूटचार्ट सक्षम करने के लिए:

adb shell 'touch /data/bootchart/enabled'
adb reboot

बूट अप के बाद, बूट चार्ट प्राप्त करें:

$ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh

समाप्त होने पर, हर बार डेटा एकत्र करने से रोकने के लिए /data/bootchart/enabled हटा दें।

यदि बूटचार्ट काम नहीं करता है और आपको यह कहते हुए त्रुटि मिलती है कि bootchart.png मौजूद नहीं है, तो निम्न कार्य करें:
  1. निम्नलिखित कमांड चलाएँ:
          sudo apt install python-is-python3
          cd ~/Documents
          git clone https://github.com/xrmx/bootchart.git
          cd bootchart/pybootchartgui
          mv main.py.in main.py
        
  2. pybootchartgui की स्थानीय प्रतिलिपि को इंगित करने के लिए $ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh अपडेट करें ( ~/Documents/bootchart/pybootchartgui.py पर स्थित)

सिस्ट्रेस

सिस्ट्रेस बूट अप के दौरान कर्नेल और एंड्रॉइड दोनों ट्रेस एकत्र करने की अनुमति देता है। सिस्ट्रेस का विज़ुअलाइज़ेशन बूट-अप के दौरान विशिष्ट समस्या का विश्लेषण करने में मदद कर सकता है। (हालांकि, पूरे बूट के दौरान औसत संख्या या संचित संख्या की जांच करने के लिए, सीधे कर्नेल ट्रेस को देखना आसान है)।

बूट-अप के दौरान सिस्ट्रेस को सक्षम करने के लिए:

  • frameworks/native/cmds/atrace/atrace.rc में, बदलें:
      write /sys/kernel/debug/tracing/tracing_on 0
      write /sys/kernel/tracing/tracing_on 0

    को:

      #    write /sys/kernel/debug/tracing/tracing_on 0
      #    write /sys/kernel/tracing/tracing_on 0
  • यह ट्रेसिंग को सक्षम बनाता है (जो डिफ़ॉल्ट रूप से अक्षम है)।

  • device.mk फ़ाइल में, निम्न पंक्ति जोड़ें:
    PRODUCT_PROPERTY_OVERRIDES +=    debug.atrace.tags.enableflags=802922
    PRODUCT_PROPERTY_OVERRIDES +=    persist.traced.enable=0
  • डिवाइस BoardConfig.mk फ़ाइल में, निम्नलिखित जोड़ें:
    BOARD_KERNEL_CMDLINE := ... trace_buf_size=64M trace_event=sched_wakeup,sched_switch,sched_blocked_reason,sched_cpu_hotplug
  • विस्तृत I/O विश्लेषण के लिए, ब्लॉक और ext4 और f2fs भी जोड़ें।

  • डिवाइस-विशिष्ट init.rc फ़ाइल में, निम्नलिखित जोड़ें:
    on property:sys.boot_completed=1          // This stops tracing on boot complete
    write /d/tracing/tracing_on 0
    write /d/tracing/events/ext4/enable 0
    write /d/tracing/events/f2fs/enable 0
    write /d/tracing/events/block/enable 0
    
  • बूट अप के बाद, ट्रेस प्राप्त करें:

    adb root && adb shell atrace --async_stop -z -c -o /data/local/tmp/boot_trace
    adb pull /data/local/tmp/boot_trace
    $ANDROID_BUILD_TOP/external/chromium-trace/systrace.py --from-file=boot_trace