यह पोस्ट, Chromium के योगदान देने वाले अहमद अलवासफी की है. इसमें उन्होंने बताया है कि Google Summer of Code की मदद से, वे कैसे योगदान देने वाले बने. साथ ही, सुलभता से जुड़ी परफ़ॉर्मेंस की उन समस्याओं के बारे में भी बताया है जिन्हें उन्होंने पहचाना और ठीक किया है.
जब मैं काइरो में जर्मन यूनिवर्सिटी में कंप्यूटर इंजीनियरिंग के आखिरी साल में थी, तब मैंने ओपन सोर्स में योगदान देने के अवसरों को एक्सप्लोर करने का फ़ैसला लिया. मैंने Chromium की, शुरुआती लोगों के लिए बनी समस्याओं की सूची को एक्सप्लोर करना शुरू किया. इसमें मुझे सुलभता से जुड़ी समस्याएं खास तौर पर दिलचस्प लगीं. दिशा-निर्देश पाने के लिए, मेरी मुलाकात ऐरोन लेवेंटल से हुई. उनकी विशेषज्ञता और मदद करने की इच्छा ने मुझे एक प्रोजेक्ट के लिए उनके साथ टीम बनाने के लिए प्रेरित किया. इस सहयोग ने मुझे Google Summer of Code का अनुभव दिया. यहां मुझे Chromium की सुलभता टीम के साथ काम करने का मौका मिला.
Google Summer of Code प्रोग्राम को पूरा करने के बाद, मैंने परफ़ॉर्मेंस को बेहतर बनाने के लिए, स्क्रोल करने से जुड़ी एक ऐसी समस्या को हल करना जारी रखा जिसे अब तक हल नहीं किया जा सका था. Google के OpenCollective प्रोग्राम से मिले दो अनुदानों की मदद से, मैंने इस प्रोजेक्ट पर काम जारी रखा. साथ ही, बेहतर परफ़ॉर्मेंस के लिए कोड को आसान बनाने के मकसद से, कुछ और काम भी किए.
इस ब्लॉग पोस्ट में, पिछले डेढ़ साल में Chromium के साथ मेरी यात्रा के बारे में बताया गया है. इसमें, हमने जो तकनीकी सुधार किए हैं उनके बारे में बताया गया है. खास तौर पर, परफ़ॉर्मेंस के क्षेत्र में किए गए सुधारों के बारे में बताया गया है.
सुलभता कोड का Chrome की परफ़ॉर्मेंस पर क्या असर पड़ता है
Chrome का सुलभता कोड, स्क्रीन रीडर जैसी सहायक तकनीकों को वेब ऐक्सेस करने में मदद करता है. हालांकि, इस सुविधा के चालू होने पर, ऐप्लिकेशन लोड होने में लगने वाले समय, परफ़ॉर्मेंस, और बैटरी लाइफ़ पर असर पड़ सकता है. इसलिए, अगर ज़रूरत न हो, तो परफ़ॉर्मेंस में कमी आने से बचने के लिए, यह कोड बंद रहता है. करीब 5 से 10% उपयोगकर्ताओं के डिवाइस पर, सुलभता कोड चालू होता है. ऐसा अक्सर पासवर्ड मैनेजर और एंटीवायरस सॉफ़्टवेयर जैसे टूल की वजह से होता है, जो प्लैटफ़ॉर्म के सुलभता एपीआई का इस्तेमाल करते हैं. ये टूल, पेज के कॉन्टेंट के साथ इंटरैक्ट करने और उसमें बदलाव करने के लिए, इन एपीआई पर निर्भर करते हैं. जैसे, पासवर्ड मैनेजर और फ़ॉर्म भरने वाले टूल के लिए पासवर्ड फ़ील्ड ढूंढना.
मुख्य मेट्रिक में हुई गिरावट की कुल संख्या अब तक पता नहीं है. हालांकि, हाल ही में किए गए एक एक्सपेरिमेंट से पता चला है कि यह संख्या काफ़ी ज़्यादा है. इस एक्सपेरिमेंट का नाम, 'सुविधा को अपने-आप बंद करना' है. इसमें, सुविधा का इस्तेमाल न होने पर उसे बंद कर दिया जाता है. यह समस्या, Chrome के सुलभता कोडबेस के दो मुख्य हिस्सों में बहुत ज़्यादा गिनती और कम्यूनिकेशन की वजह से होती है: रेंडरर और ब्राउज़र. रेंडरर, वेब कॉन्टेंट और कॉन्टेंट में हुए बदलावों के बारे में जानकारी इकट्ठा करता है. साथ ही, नोड के ट्री के लिए सुलभता प्रॉपर्टी का हिसाब लगाता है. इसके बाद, किसी भी गलत नोड को क्रम से लगाया जाता है और ब्राउज़र प्रोसेस के मुख्य यूज़र इंटरफ़ेस (यूआई) थ्रेड में भेजा जाता है. यह थ्रेड, इस जानकारी को नोड के एक जैसे ट्री में डिससिरियलाइज़ करता है और फिर आखिर में, इसे स्क्रीन रीडर जैसी तीसरे पक्ष की सहायक टेक्नोलॉजी के लिए सही फ़ॉर्मैट में बदल देता है.
Chromium की सुलभता सुविधाओं में सुधार
यहां दिए गए प्रोजेक्ट, Summer of Code के दौरान पूरे किए गए थे. इसके बाद, Google OpenCollective प्रोग्राम से इनके लिए फ़ंड उपलब्ध कराया गया था.
कैश मेमोरी में सुधार
Chrome में एक खास डेटा स्ट्रक्चर होता है, जिसे सुलभता ट्री कहा जाता है. यह डीओएम ट्री की तरह ही काम करता है. इसका इस्तेमाल, सहायक टेक्नोलॉजी को वेब कॉन्टेंट ऐक्सेस करने में मदद करने के लिए किया जाता है. कभी-कभी, जब किसी डिवाइस को इस ट्री से जानकारी की ज़रूरत होती है, तो हो सकता है कि वह जानकारी तैयार न हो. इसलिए, ब्राउज़र को उन अनुरोधों को बाद के लिए शेड्यूल करना पड़ता है.
पहले, शेड्यूलिंग को क्लोज़र नाम के तरीके का इस्तेमाल करके मैनेज किया जाता था. इसमें कॉलबैक को एक कतार में रखा जाता था. इस तरीके से, ज़्यादा काम करना पड़ता है, क्योंकि क्लोज़र को प्रोसेस करने का तरीका अलग होता है.
इसे बेहतर बनाने के लिए, हमने ऐसे सिस्टम का इस्तेमाल किया है जिसमें एनम का इस्तेमाल किया जाता है. हर टास्क को एक खास वैल्यू असाइन की जाती है. ऐक्सेसibiliti ट्री तैयार होने के बाद, उस टास्क के लिए सही तरीका लागू किया जाता है. इस बदलाव की वजह से, कोड को समझना आसान हो गया और परफ़ॉर्मेंस 20% से ज़्यादा बेहतर हुई.
स्क्रोल की परफ़ॉर्मेंस से जुड़ी समस्याओं का पता लगाना और उन्हें ठीक करना
इसके बाद, मैंने यह पता लगाया कि बॉउंडिंग बॉक्स को सीरियलाइज़ करने की सुविधा बंद करने पर, परफ़ॉर्मेंस कैसे बेहतर होती है. बाउंडिंग बॉक्स, वेब पेज पर एलिमेंट की पोज़िशन और साइज़ होते हैं. इनमें चौड़ाई, ऊंचाई, और पैरंट एलिमेंट के हिसाब से उनकी पोज़िशन जैसी जानकारी शामिल होती है.
इसकी जांच करने के लिए, हमने बॉउंडिंग बॉक्स को मैनेज करने वाले कोड को कुछ समय के लिए हटा दिया. साथ ही, इसका असर देखने के लिए परफ़ॉर्मेंस टेस्ट चलाए. focus-links.html के एक टेस्ट में, 1618% का ज़बरदस्त सुधार हुआ. इस खोज से, आगे के काम के लिए आधार मिला.
धीमी स्पीड की जांच करना
मैंने जांच करना शुरू किया कि बॉउंडिंग बॉक्स की मदद से, वह टेस्ट धीमा क्यों चल रहा था. इस जांच में, एक के बाद एक कई लिंक पर फ़ोकस किया गया. इसलिए, मुख्य समस्या एलिमेंट पर फ़ोकस करने या फ़ोकस ऐक्शन के साथ होने वाली स्क्रोलिंग में से कोई एक होनी चाहिए. इसकी जांच करने के लिए, मैंने परफ़ॉर्मेंस टेस्ट में focus()
कॉल में {preventScroll: true}
जोड़ा और स्क्रोलिंग को रोक दिया.
स्क्रोलिंग बंद होने पर, बॉउंडिंग बॉक्स की गणना चालू होने पर, टेस्ट का समय 1.2 मिलीसेकंड तक कम हो गया. इससे पता चला कि स्क्रोल करने में समस्या थी.
मैंने focus-links टेस्ट को दोहराने के लिए, scroll-in-page.html नाम का एक नया टेस्ट बनाया है. हालांकि, फ़ोकस का इस्तेमाल करने के बजाय, यह scrollIntoView()
की मदद से एलिमेंट को स्क्रोल करता है. मैंने स्मूद और इंस्टैंट स्क्रोलिंग, दोनों की जांच की है. इसमें मैंने बॉउंडिंग बॉक्स की गणना के साथ और उसके बिना, दोनों तरह से जांच की है.
नतीजों से पता चला कि इंस्टैंट स्क्रोलिंग और बॉउंडिंग बॉक्स की मदद से, प्रोसेस को करीब 66 मिलीसेकंड लगे. आसानी से स्क्रोल करने की सुविधा का इस्तेमाल करने पर, यह समय 124 मिलीसेकंड तक पहुंच गया. जब हमने बाउंडिंग बॉक्स बंद किए, तो इसमें कोई समय नहीं लगा, क्योंकि कोई इवेंट ट्रिगर नहीं हुआ.
हमें इसकी जानकारी थी, लेकिन ऐसा क्यों हो रहा था?
अब हमें पता चला है कि ऐक्सेसibiliy सीरियलाइज़ेशन में बहुत धीमे होने की वजह स्क्रॉल करना है. हालांकि, हमें अब भी इसकी वजह पता करनी थी. इसका विश्लेषण करने के लिए, ब्राउज़र प्रोसेस में किए गए काम को अलग-अलग हिस्सों में बांटने के लिए, perf और pprof नाम के दो टूल का इस्तेमाल किया गया. आम तौर पर, C++ में प्रोफ़ाइलिंग के लिए इन टूल का इस्तेमाल किया जाता है. नीचे दिए गए ग्राफ़ में, दिलचस्प हिस्से की झलक दिखाई गई है.
जांच करने के बाद, हमें पता चला कि समस्या डेसीरियलाइज़ेशन कोड में नहीं थी, बल्कि उस पर कॉल की फ़्रीक्वेंसी में थी. इसे समझने के लिए, हमें यह देखना होगा कि सुलभता से जुड़े अपडेट, Chromium में कैसे काम करते हैं. अपडेट अलग-अलग नहीं भेजे जाते. इसके बजाय, AXObjectCache
नाम की एक मुख्य जगह होती है, जहां सभी प्रॉपर्टी सेव होती हैं. जब किसी नोड में बदलाव होता है, तो अलग-अलग तरीके से कैश मेमोरी को सूचना दी जाती है, ताकि बाद में सीरियलाइज़ेशन के लिए उस नोड को बदलाव किया गया के तौर पर मार्क किया जा सके. इसके बाद, बदलाव किए गए नोट की सभी प्रॉपर्टी को सीरियलाइज़ किया जाता है और ब्राउज़र पर भेजा जाता है. इनमें वे प्रॉपर्टी भी शामिल होती हैं जिनमें कोई बदलाव नहीं किया गया है. इस डिज़ाइन में, अपडेट के लिए एक ही पाथ होता है, जिससे कोड आसान हो जाता है और जटिलता कम हो जाती है. हालांकि, जब "बदली गई वैल्यू के तौर पर मार्क करें" वाले इवेंट तेज़ी से होते हैं, तो यह धीमा हो जाता है. जैसे, स्क्रोल करने से होने वाले इवेंट. सिर्फ़ scrollX
और scrollY
की वैल्यू बदलती हैं. इसके बावजूद, हम हर बार बाकी प्रॉपर्टी को उनके साथ क्रम से लगाते हैं. यहां अपडेट की दर, हर सेकंड में बीस से ज़्यादा बार पहुंच गई!
बॉर्डिंग बॉक्स को सीरियलाइज़ करने की सुविधा, तेज़ी से सीरियलाइज़ करने वाले पाथ का इस्तेमाल करके इस समस्या को हल करती है. यह पाथ सिर्फ़ बॉर्डिंग बॉक्स की जानकारी भेजता है. इससे, अन्य प्रॉपर्टी पर असर डाले बिना, तेज़ी से अपडेट किए जा सकते हैं. यह तरीका, बॉउंडिंग बॉक्स में होने वाले बदलावों को बेहतर तरीके से मैनेज करता है.
स्क्रोल करने से जुड़ी समस्या ठीक करना
इसका समाधान साफ़ था: बॉउंडिंग बॉक्स को सीरियलाइज़ करने के साथ, मौजूदा स्क्रोल ऑफ़सेट शामिल करें. इससे यह पक्का होता है कि स्क्रोलिंग अपडेट, तेज़ पाथ के ज़रिए प्रोसेस किए जाते हैं. इससे, बिना किसी देरी के परफ़ॉर्मेंस बेहतर होती है. हम बाउंडिंग बॉक्स के डेटा के साथ स्क्रोल ऑफ़सेट को पैक करके, अपडेट को आसान और ज़्यादा बेहतर बनाने के लिए प्रोसेस को ऑप्टिमाइज़ करते हैं. इससे, सुलभता मोड चालू होने पर, उपयोगकर्ताओं को बेहतर अनुभव मिलता है. सुधार लागू करने के बाद, स्क्रोलिंग टेस्ट में 825%तक सुधार हुआ है.
कोड को आसान बनाना
इस दौरान, मैंने Onion Soup नाम के प्रोजेक्ट के तहत कोड की क्वालिटी पर फ़ोकस किया. इस प्रोजेक्ट की मदद से, कोड को आसान बनाया जा सकता है. इसके लिए, सभी लेयर में कोड को कम किया जाता है या ज़रूरत के बिना फैले हुए कोड को हटाया जाता है.
पहले प्रोजेक्ट का मकसद, सुलभता डेटा को रेंडरर से ब्राउज़र में सीरियलाइज़ करने के तरीके को बेहतर बनाना था. पहले, डेटा को अपने डेस्टिनेशन तक पहुंचने से पहले एक अतिरिक्त लेयर से गुज़रना पड़ता था. इससे डेटा प्रोसेस करने की प्रोसेस में ग़ैर-ज़रूरी जटिलताएं आती थीं. हमने इस प्रोसेस को आसान बनाया है. इसके लिए, हमने डेटा को सीधे भेजने की सुविधा दी है.
इसके अलावा, हमने कुछ ऐसे पुराने इवेंट का पता लगाया और उन्हें हटा दिया है जिनकी वजह से सिस्टम में ग़ैर-ज़रूरी काम हो रहा था. जैसे, लेआउट पूरा होने पर ट्रिगर होने वाला इवेंट. हमने इनकी जगह, ज़्यादा असरदार समाधान उपलब्ध कराया है.
इसमें कुछ और छोटे सुधार भी किए गए हैं. माफ़ करें, इनके लिए परफ़ॉर्मेंस में हुए सुधारों को रिकॉर्ड नहीं किया गया था. हालांकि, हमें यह बताते हुए खुशी हो रही है कि कोड पहले के मुकाबले ज़्यादा साफ़ और अपने-आप दस्तावेज़ बनाने वाला है. इससे आने वाले समय में परफ़ॉर्मेंस को बेहतर बनाने में काफ़ी मदद मिलती है. असल बदलावों को देखने के लिए, मेरी gerrit प्रोफ़ाइल पर जाएं.
नतीजा
Chromium की सुलभता टीम के साथ काम करना मेरे लिए एक बेहतरीन अनुभव रहा. स्क्रोलिंग की परफ़ॉर्मेंस को ऑप्टिमाइज़ करने से लेकर, कोडबेस को आसान बनाने तक, कई चुनौतियों का सामना करने के दौरान, मुझे बड़े पैमाने पर प्रोजेक्ट डेवलप करने के बारे में बेहतर तरीके से पता चला. साथ ही, प्रोफ़ाइलिंग के लिए ज़रूरी टूल भी सीखने को मिले. इसके अलावा, मुझे यह भी पता चला है कि सभी के लिए वेब को ऐक्सेस करने लायक बनाना कितना ज़रूरी है. हमने जो सुधार किए हैं उनसे, सहायक टेक्नोलॉजी का इस्तेमाल करने वाले लोगों के लिए उपयोगकर्ता अनुभव बेहतर होगा. साथ ही, इससे ब्राउज़र की परफ़ॉर्मेंस और बेहतर होगी.
परफ़ॉर्मेंस के नतीजे काफ़ी अच्छे रहे हैं. उदाहरण के लिए, टास्क शेड्यूल करने के लिए, सूचियों का इस्तेमाल करने पर, परफ़ॉर्मेंस 20%से ज़्यादा बेहतर हुई. इसके अलावा, स्क्रॉल करने से जुड़ी समस्या को ठीक करने के बाद, स्क्रॉल करने से जुड़े टेस्ट में 825% तक की कमी आई है. कोड को आसान बनाने के लिए किए गए बदलावों से, कोड को समझना और उसे मैनेज करना आसान हो गया है. साथ ही, आने वाले समय में इसमें और भी सुधार किए जा सकेंगे.
मैं पूरे साल अपने साथ बने रहने और दिशा-निर्देश देने के लिए, स्टीफ़न ज़गर, क्रिस हर्रलसन, और मेसन फ़्रीड का धन्यवाद करना चाहता/चाहती हूं. खास तौर पर, मुझे अरेऑन लेवेंटल का धन्यवाद करना है, जिनके बिना यह अवसर मिलना मुमकिन नहीं होता. साथ ही, मुझे Tab Atkins-Bittner और GSoC टीम का भी धन्यवाद करना है, जिन्होंने इस प्रोजेक्ट में मदद की.
अगर आपको किसी काम के प्रोजेक्ट में योगदान देना है और अपनी स्किल को बेहतर बनाना है, तो मेरा सुझाव है कि आप Chromium से जुड़ें. यह सीखने का एक बेहतरीन तरीका है. Google Summer of Code जैसे प्रोग्राम, इसकी शुरुआत करने के लिए एक बेहतरीन प्लैटफ़ॉर्म हैं.