डिवाइस बूट होने के समय को ऑप्टिमाइज़ करें

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

Android 8.0 के साथ कई सुधार किए गए हैं, जिससे बूट के समय को कम किया जा सकता है कुछ चीज़ों का इस्तेमाल करते हैं. नीचे दी गई टेबल में इन परफ़ॉर्मेंस की खास जानकारी दी गई है सुधार (जैसा कि Google Pixel और Pixel XL डिवाइसों पर किया गया है).

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

बूटलोडर ऑप्टिमाइज़ करें

बूटलोडर को ऑप्टिमाइज़ करने के लिए:

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

I/O की परफ़ॉर्मेंस को ऑप्टिमाइज़ करें

बूट टाइम को तेज़ बनाने और रीडिंग लेने के लिए, I/O की क्षमता को बेहतर बनाना ज़रूरी है जो भी ज़रूरी नहीं है उसे बूट होने तक टाला जाए (Google Pixel पर, (बूट होने पर करीब 1.2 जीबी डेटा पढ़ा जाता है).

फ़ाइल सिस्टम को स्ट्रीम करें

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

आसानी से अपडेट (A/B) अपडेट की सुविधा वाले डिवाइसों को फ़ाइल सिस्टम से काफ़ी फ़ायदा मिलता है पहली बार बूट करने पर ट्यूनिंग (उदाहरण के लिए, Google Pixel पर 20 सेकंड). उदाहरण के लिए, हमने 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 है).
  • फ़ाइल सिस्टम की बेहतर स्थिरता के लिए और फ़ोर्स किए गए टेस्ट की प्रोसेस को बंद करने के लिए, हर बूट के लिए, TARGET_USES_MKE2FS को BoardConfig.mk.

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

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

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 सिस्टम-लेवल के ब्रेकडाउन की जानकारी देता है.

इसे ऑप्टिमाइज़ करें.*.rc

इनिट, कर्नेल से फ़्रेमवर्क तैयार होने तक पुल होता है, और डिवाइस आम तौर पर अलग-अलग स्टेज में कुछ सेकंड बिताते हैं.

टास्क को साथ-साथ चलाएं

जबकि मौजूदा Android init, एक या उससे कम थ्रेड वाली प्रोसेस है, लेकिन आपको साथ ही साथ कुछ काम अब भी कर सकते हैं.

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

    इस लॉग की समीक्षा करने से पता चलता है कि इसमें सुधार किए जा सकते हैं.

  • ज़रूरी पाथ पर, सेवाएं और सहायक डिवाइस (जैसे, कीबोर्ड, माउस, मॉनिटर, वेबकैम वगैरह) चालू करें. इसके लिए उदाहरण के लिए, कुछ एसओसी को शुरू करने से पहले सुरक्षा से जुड़ी सेवाएं शुरू करना ज़रूरी होता है SurfaceFlinger में है. जब ServiceManager "इंतज़ार करें" वापस आता है, तो सिस्टम लॉग की समीक्षा करें सेवा" — यह आम तौर पर एक संकेत है कि डिपेंडेंट सेवा को चालू किया जाना चाहिए चुनें.
  • init.*.rc में इस्तेमाल नहीं की जा रही सभी सेवाओं और कमांड को हटाएं. ऐसी कोई भी चीज़ जिसका इस्तेमाल न किया गया हो शुरुआती चरण में, बूट पूरा होने के लिए टाल दिया जाना चाहिए.

ध्यान दें: प्रॉपर्टी सेवा, इनइट प्रोसेस का हिस्सा है, इसलिए चालू होने के दौरान, setproperty को चालू होने में ज़्यादा समय लग सकता है. ऐसा तब होता है, जब init व्यस्त हो पहले से मौजूद निर्देश होते हैं.

शेड्यूलर ट्यूनिंग का इस्तेमाल करना

अपने-आप चालू होने की सुविधा को चालू करने के लिए, शेड्यूलर ट्यूनिंग का इस्तेमाल करें. Google Pixel से उदाहरण:

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
...

जायगोट को जल्दी शुरू करें

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

बैटरी सेव करने की सुविधा बंद करें

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

ध्यान दें: बैटरी सेव करने की सुविधा चालू होनी चाहिए चार्जर मोड का इस्तेमाल करें.

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}

बूट ऐनिमेशन ऑप्टिमाइज़ करें

बूट ऐनिमेशन को ऑप्टिमाइज़ करने के लिए, नीचे दी गई सलाह का इस्तेमाल करें.

रिलीज़ होने से पहले इस्तेमाल करने की सुविधा कॉन्फ़िगर करें

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

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

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

बूट एनिमेशन बहुत तेज़ी से (और एक निश्चित समय में) शुरू हो जाएगा, भले ही भाड़ में जाओ.

सफ़ाई पूरी करें

एग्ज़िट सिग्नल मिलने के बाद, बूटऐनिमेशन का आखिरी हिस्सा पूरा होता है, यानी कि जिससे बूटिंग में ज़्यादा समय लग सकता है. जो सिस्टम तुरंत चालू हो जाता है उसे लंबे समय तक इस्तेमाल करने की ज़रूरत नहीं होती ऐसे ऐनिमेशन जो किए गए किसी भी सुधार को असरदार तरीके से छिपा सकते हैं. हमारा सुझाव है कि आप: इससे दोहराए जाने वाले लूप और फ़िनाले, दोनों को छोटा करके दिखाया जा सकता है.

SELinux को ऑप्टिमाइज़ करें

बेहतर बूट समय के लिए SELinux को ऑप्टिमाइज़ करने के लिए निम्न सुझावों का उपयोग करें.

  • साफ़ रेगुलर एक्सप्रेशन का इस्तेमाल करें. खराब तरीके से बनाया गया रेगुलर एक्सप्रेशन SELinux नीति का मिलान करने पर बहुत से ओवरहेड हो सकता है file_contexts में sys/devices. उदाहरण के लिए, /sys/devices/.*abc.*(/.*)? गलती से सभी यूआरएल को स्कैन कर लेता है "abc" वाली /sys/devices सबडायरेक्ट्री, जिनसे मिलते-जुलते वीडियो खोजे जा सकते हैं /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. $ANDROID_BUILD_TOP/system/core/init/grab-bootchart.sh का मैंडेट अपडेट हो रहा है pybootchartgui की स्थानीय कॉपी पर ले जाने के लिए (~/Documents/bootchart/pybootchartgui.py पर स्थित)

सिस्ट्रेस

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

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

  • 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 से जुड़ी ज़्यादा जानकारी का विश्लेषण करने के लिए, block और 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