अलाइन किए गए इनपुट इवेंट

Dave Tapuska
Dave Tapuska

कम शब्दों में कहा जाए तो

  • Chrome 60, इवेंट की फ़्रीक्वेंसी कम करके, फ़्रेम टाइमिंग को एक जैसा बनाए रखता है. इससे, फ़्रेम में रुकावट की समस्या कम हो जाती है.
  • Chrome 58 में पेश किया गया getCoalescedEvents() तरीका, इवेंट की उतनी ही जानकारी देता है जितनी आपको पहले मिलती थी.

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

Chrome 60 में, हम एक बदलाव कर रहे हैं. इससे, ब्राउज़िंग को बेहतर बनाने और परफ़ॉर्मेंस को बेहतर बनाने में मदद मिलेगी. इस बदलाव की वजह से, ये इवेंट कम फ़्रीक्वेंसी पर होंगे. साथ ही, दी गई जानकारी ज़्यादा बेहतर होगी. Jelly Bean के रिलीज़ होने के बाद, Android पर इनपुट को अलाइन करने वाला Choreographer उपलब्ध कराया गया था. ठीक उसी तरह, हम सभी प्लैटफ़ॉर्म पर वेब पर फ़्रेम अलाइन करने वाला इनपुट उपलब्ध करा रहे हैं.

हालांकि, कभी-कभी आपको ज़्यादा इवेंट की ज़रूरत पड़ती है. इसलिए, हमने Chrome 58 में, getCoalescedEvents() नाम का एक तरीका लागू किया है. इसकी मदद से, आपके ऐप्लिकेशन को पॉइंटर का पूरा पाथ तब भी मिल सकता है, जब उसे कम इवेंट मिल रहे हों.

सबसे पहले, इवेंट की फ़्रीक्वेंसी के बारे में बात करते हैं.

इवेंट की फ़्रीक्वेंसी कम करना

आइए, कुछ बुनियादी बातें समझते हैं: टच-स्क्रीन 60-120Hz पर इनपुट देती हैं और माउस आम तौर पर 100Hz पर इनपुट देते हैं. हालांकि, यह 2000Hz तक भी हो सकता है. हालांकि, आम तौर पर किसी मॉनिटर की रीफ़्रेश दर 60 हर्ट्ज़ होती है. इसका क्या मतलब है? इसका मतलब है कि हमें इनपुट की दर, डिसप्ले को अपडेट करने की दर से ज़्यादा होती है. इसलिए, चलिए devtools में जाकर, कैनवस वाले पेंटिंग ऐप्लिकेशन की परफ़ॉर्मेंस की टाइमलाइन देखें.

नीचे दी गई इमेज में, requestAnimationFrame()-अलाइन किए गए इनपुट की सुविधा बंद होने पर, आपको हर फ़्रेम में अलग-अलग फ़्रेम टाइम के साथ कई प्रोसेसिंग ब्लॉक दिख सकते हैं. छोटे पीले ब्लॉक, हिट टेस्टिंग के बारे में बताते हैं. जैसे, डीओएम इवेंट का टारगेट, इवेंट डिस्पैच करना, JavaScript चलाना, कर्सर घुमाने पर दिखने वाले नोड को अपडेट करना, और लेआउट और स्टाइल का फिर से हिसाब लगाना.

परफ़ॉर्मेंस की टाइमलाइन, जिसमें फ़्रेम की समयावधि अलग-अलग दिख रही है

तो हम ऐसा अतिरिक्त काम क्यों कर रहे हैं जिससे विज़ुअल में कोई अपडेट नहीं होता? आम तौर पर, हम ऐसा कोई भी काम नहीं करना चाहते जिससे उपयोगकर्ता को फ़ायदा न हो. Chrome 60 से, इनपुट पाइपलाइन, लगातार होने वाले इवेंट (wheel, mousewheel, touchmove, pointermove, mousemove) को डिस्पैच करने में देरी करेगी. साथ ही, इन्हें requestAnimationFrame() कॉलबैक होने से ठीक पहले डिस्पैच करेगी. नीचे दी गई इमेज में (इसमें सुविधा चालू है), आपको फ़्रेम का समय एक जैसा दिखता है और इवेंट को प्रोसेस करने में कम समय लगता है.

हमने Canary और Dev चैनलों पर इस सुविधा को चालू करके एक एक्सपेरिमेंट किया है. इससे हमें पता चला है कि हम 35% कम हिट टेस्ट करते हैं. इससे मुख्य थ्रेड ज़्यादा बार चलने के लिए तैयार हो जाता है.

वेब डेवलपर को एक अहम बात का ध्यान रखना चाहिए. वह यह है कि कोई भी अलग इवेंट (जैसे, keydown, keyup, mouseup, mousedown, touchstart, touchend) होने पर, उसे तुरंत भेज दिया जाएगा. साथ ही, किसी भी इवेंट के क्रम में कोई बदलाव नहीं किया जाएगा. इस सुविधा के चालू होने पर, ज़्यादातर काम सामान्य इवेंट लूप फ़्लो में व्यवस्थित हो जाता है. इससे इनपुट इंटरवल एक जैसा रहता है. इससे, लगातार होने वाले इवेंट, scroll और resize इवेंट के साथ मिलते-जुलते हो जाते हैं. इन्हें पहले से ही Chrome में इवेंट लूप फ़्लो में स्ट्रीमलाइन किया जा चुका है.

परफ़ॉर्मेंस की टाइमलाइन, जिसमें फ़्रेम की समयावधि अपेक्षाकृत एक जैसी दिख रही है.

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

getCoalescedEvents() तरीका

जैसा कि मैंने बताया था, कुछ ही मामलों में ऐप्लिकेशन को पॉइंटर का पूरा पाथ जानना होता है. इसलिए, Chrome 58 में, हमने पॉइंटर इवेंट के लिए एक एक्सटेंशन लॉन्च किया है. इसका नाम getCoalescedEvents() है. इससे, इवेंट की फ़्रीक्वेंसी में होने वाली बढ़ोतरी और गिरावट को ठीक किया जा सकता है. यहां एक उदाहरण दिया गया है, जिसमें दिखाया गया है कि इस एपीआई का इस्तेमाल करने पर, मुख्य थ्रेड पर होने वाली रुकावट को ऐप्लिकेशन से कैसे छिपाया जाता है.

स्टैंडर्ड और मर्ज किए गए इवेंट की तुलना करना.

किसी एक इवेंट के बजाय, उन पुराने इवेंट का कलेक्शन ऐक्सेस किया जा सकता है जिनकी वजह से इवेंट हुआ है. Android, iOS, और Windows के नेटिव SDK टूल में एक जैसे एपीआई होते हैं. हम वेब के लिए भी एक ऐसा ही एपीआई उपलब्ध करा रहे हैं.

आम तौर पर, ड्रॉइंग ऐप्लिकेशन ने इवेंट के ऑफ़सेट को देखकर कोई पॉइंट बनाया हो:

window.addEventListener("pointermove", function(event) {
    drawPoint(event.pageX, event.pageY);
});

इवेंट की कलेक्शन का इस्तेमाल करने के लिए, इस कोड को आसानी से बदला जा सकता है:

window.addEventListener("pointermove", function(event) {
    var events = 'getCoalescedEvents' in event ? event.getCoalescedEvents() : [event];
    for (let e of events) {
    drawPoint(e.pageX, e.pageY);
    }
});

ध्यान दें कि मर्ज किए गए इवेंट में हर प्रॉपर्टी अपने-आप नहीं भरती. इकट्ठा किए गए इवेंट, असल में डिस्पैच नहीं किए जाते, बल्कि सिर्फ़ ट्रैफ़िक बढ़ाने के लिए इस्तेमाल किए जाते हैं. इसलिए, इनकी हिट जांच नहीं की जाती. currentTarget और eventPhase जैसे कुछ फ़ील्ड में, डिफ़ॉल्ट वैल्यू दिखेंगी. डिस्पैच से जुड़े तरीकों, जैसे कि stopPropagation() या preventDefault() को कॉल करने से, पैरंट इवेंट पर कोई असर नहीं पड़ेगा.