यह दस्तावेज़ विशिष्ट Android उपकरणों के लिए बूट समय में सुधार के लिए भागीदार मार्गदर्शन प्रदान करता है। बूट समय सिस्टम प्रदर्शन का एक महत्वपूर्ण घटक है क्योंकि उपयोगकर्ताओं को डिवाइस का उपयोग करने से पहले बूट पूरा होने तक इंतजार करना होगा। कारों जैसे उपकरणों के लिए जहां कोल्ड बूट-अप अधिक बार होता है, त्वरित बूट समय होना महत्वपूर्ण है (किसी को भी नेविगेशन गंतव्य पर इनपुट करने के लिए दर्जनों सेकंड तक इंतजार करना पसंद नहीं है)।
एंड्रॉइड 8.0 विभिन्न घटकों में कई सुधारों का समर्थन करके कम बूट समय की अनुमति देता है। निम्न तालिका इन प्रदर्शन सुधारों का सारांश प्रस्तुत करती है (जैसा कि Google Pixel और Pixel XL उपकरणों पर मापा गया है)।
अवयव | सुधार |
---|---|
बूटलोडर |
|
डिवाइस कर्नेल |
|
आई/ओ ट्यूनिंग |
|
init.*.rc |
|
बूट एनीमेशन |
|
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
मौजूद नहीं है, तो निम्न कार्य करें:- निम्नलिखित कमांड चलाएँ:
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
-
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
- डिवाइस-विशिष्ट
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
यह ट्रेसिंग को सक्षम बनाता है (जो डिफ़ॉल्ट रूप से अक्षम है)।
विस्तृत I/O विश्लेषण के लिए, ब्लॉक और ext4 और f2fs भी जोड़ें।