Chrome 88 में, चेन वाले JS टाइमर की भारी थ्रॉटलिंग.

Chrome 88 (जनवरी 2021) कुछ खास स्थितियों में, छिपे हुए पेजों के लिए JavaScript टाइमर को बहुत तेज़ी से थ्रॉटल करेगा. इससे सीपीयू का इस्तेमाल कम हो जाएगा, और बैटरी भी कम हो जाएगी. कुछ ऐसे मामले होते हैं जहां पर इसका असर बदल सकता है. हालांकि, टाइमर का इस्तेमाल अक्सर वहां किया जाता है, जहां दूसरा एपीआई ज़्यादा कुशल और ज़्यादा भरोसेमंद होता है.

ठीक है, वह भारी-भरकम शब्द था और समझ में नहीं आया. चलिए, शुरू करते हैं...

शब्दावली

छिपे हुए पेज

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

JavaScript टाइमर

JavaScript टाइमर से मेरा मतलब setTimeout और setInterval है. इनकी मदद से, आने वाले समय में कभी भी कॉलबैक शेड्यूल किया जा सकता है. टाइमर उपयोगी होते हैं और वे वापस नहीं जाते, लेकिन कभी-कभी उनका उपयोग मतदान की स्थिति बताने के लिए किया जाता है, जब कोई इवेंट ज़्यादा बेहतर और सटीक होता है.

चेन वाले टाइमर

अगर setTimeout को उसी टास्क में कॉल किया जाता है जिसमें setTimeout कॉलबैक है, तो दूसरा अनुरोध 'चेन' होता है. setInterval के साथ हर इटरेशन, चेन का हिस्सा है. इसे कोड की मदद से समझना आसान हो सकता है:

let chainCount = 0;

setInterval(() => {
  chainCount++;
  console.log(`This is number ${chainCount} in the chain`);
}, 500);

और:

let chainCount = 0;

function setTimeoutChain() {
  setTimeout(() => {
    chainCount++;
    console.log(`This is number ${chainCount} in the chain`);
    setTimeoutChain();
  }, 500);
}

थ्रॉटलिंग कैसे काम करती है

थ्रॉटलिंग कई चरणों में होती है:

कम से कम थ्रॉटलिंग

ऐसा उन टाइमर के साथ होता है जो इनमें से कोई भी स्थिति सही होने पर शेड्यूल किए जाते हैं:

  • पेज दिख रहा हो.
  • पेज ने पिछले 30 सेकंड में शोर मचाया है. यह डेटा, साउंड बनाने वाले किसी भी एपीआई से हो सकता है. हालांकि, इसमें साइलेंट ऑडियो ट्रैक शामिल नहीं होता.

टाइमर को तब तक थ्रॉटल नहीं किया जाता, जब तक अनुरोध किया गया टाइम आउट 4 मि॰से॰ से कम न हो और चेन की संख्या 5 या उससे ज़्यादा हो. इस स्थिति में, टाइम आउट 4 मि॰से॰ पर सेट नहीं होगा. यह नई बात नहीं है. ब्राउज़र कई सालों से ऐसा कर रहे हैं.

थ्रॉटलिंग

ऐसा उन टाइमर के साथ होता है जो कम से कम थ्रॉटलिंग लागू न होने पर शेड्यूल किए जाते हैं. साथ ही, इनमें से कोई भी शर्त लागू होती है:

  • चेन की संख्या पांच से कम है.
  • पेज को पांच मिनट से भी कम समय से छिपाया गया है.
  • WebRTC का इस्तेमाल किया जा रहा है. खास तौर पर, इसमें 'खुला है' RTCDataChannel या 'लाइव' MediaStreamTrack वाला एक RTCPeerConnection है.

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

इंटेंसिव थ्रॉटलिंग

ठीक है, यह रहा Chrome 88 का नया बिट. इंटेंसिव थ्रॉटलिंग उन टाइमर के लिए होती है जो कम से कम थ्रॉटलिंग या थ्रॉटलिंग की कोई भी शर्त लागू न होने पर शेड्यूल किए जाते हैं. साथ ही, नीचे दी गई सभी स्थितियां सही होती हैं:

  • पेज, पांच मिनट से ज़्यादा समय से छिपा हुआ है.
  • चेन की संख्या पांच या इससे ज़्यादा है.
  • पेज कम से कम 30 सेकंड के लिए साइलेंट रहा है.
  • WebRTC का इस्तेमाल नहीं किया जा रहा है.

ऐसे में, ब्राउज़र हर मिनट में एक बार इस ग्रुप में टाइमर की जांच करेगा. पहले की तरह ही, इसका मतलब है कि टाइमर हर मिनट की इन जांचों में एक साथ काम करेंगे.

समाधान

आम तौर पर, टाइमर का एक बेहतर विकल्प होता है या टाइमर को किसी अन्य चीज़ के साथ जोड़कर, सीपीयू और बैटरी लाइफ़ पर भी अच्छा असर डाला जा सकता है.

राज्य का मतदान

टाइमर का यह सबसे सामान्य (गलत) इस्तेमाल है, जहां उनका इस्तेमाल लगातार जांच करने या यह देखने के लिए पोल करने के लिए किया जाता है कि कहीं कुछ बदलाव तो नहीं हुआ है. ज़्यादातर मामलों में, push का इस्तेमाल किया जाता है, जहां इस सुविधा से आपको बदलाव के बारे में जानकारी मिलती है, ताकि आपको बार-बार जांच करने की ज़रूरत न पड़े. यह देखें कि क्या कोई ऐसा इवेंट है जो वही चीज़ हासिल करता है.

कुछ उदाहरण:

अगर आपको किसी खास समय पर कोई सूचना दिखानी है, तो यहां सूचना ट्रिगर भी होती हैं.

Animation

ऐनिमेशन एक विज़ुअल चीज़ है. इसलिए, पेज छिपा हुआ होने पर इसे सीपीयू समय का इस्तेमाल नहीं करना चाहिए.

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

अगर पूरे ऐनिमेशन को अप-फ़्रंट पेमेंट के तौर पर दिखाया जा सकता है, तो सीएसएस ऐनिमेशन या वेब ऐनिमेशन एपीआई का इस्तेमाल करें. इनके भी requestAnimationFrame जैसे फ़ायदे हैं, लेकिन ब्राउज़र अपने-आप कंपोज़िटिंग जैसे अतिरिक्त ऑप्टिमाइज़ेशन कर सकता है और आम तौर पर उनका इस्तेमाल आसान होता है.

अगर आपका ऐनिमेशन कम फ़्रेम दर वाला है (जैसे किसी ब्लिंक करता हुआ कर्सर), तो टाइमर अब भी सबसे अच्छे विकल्प हैं. हालांकि, दोनों का भरपूर आनंद लेने के लिए, टाइमर को requestAnimationFrame के साथ जोड़ा जा सकता है:

function animationInterval(ms, signal, callback) {
  const start = document.timeline.currentTime;

  function frame(time) {
    if (signal.aborted) return;
    callback(time);
    scheduleFrame(time);
  }

  function scheduleFrame(time) {
    const elapsed = time - start;
    const roundedElapsed = Math.round(elapsed / ms) * ms;
    const targetNext = start + roundedElapsed + ms;
    const delay = targetNext - performance.now();
    setTimeout(() => requestAnimationFrame(frame), delay);
  }

  scheduleFrame(start);
}

इस्तेमाल:

const controller = new AbortController();

// Create an animation callback every second:
animationInterval(1000, controller.signal, time => {
  console.log('tick!', time);
});

// And stop it:
controller.abort();

टेस्ट करना

यह बदलाव Chrome 88 (जनवरी 2021) में, Chrome का इस्तेमाल करने वाले सभी लोगों के लिए चालू हो जाएगा. फ़िलहाल, यह सुविधा Chrome बीटा, डेव, और कैनरी के 50% उपयोगकर्ताओं के लिए चालू है. अगर आपको इसकी जांच करनी है, तो Chrome का बीटा, डेव या कैनरी लॉन्च करते समय इस कमांड लाइन फ़्लैग का इस्तेमाल करें:

--enable-features="IntensiveWakeUpThrottling:grace_period_seconds/10,OptOutZeroTimeoutTimersFromThrottling,AllowAggressiveThrottlingWithWebSocket"

grace_period_seconds/10 तर्क की वजह से, पेज के छिपे होने के 10 सेकंड के बजाय, 10 सेकंड बाद तेज़ थ्रॉटलिंग होती है. इससे थ्रॉटलिंग का असर आसानी से देखा जा सकता है.

आने वाला समय

टाइमर बहुत ज़्यादा सीपीयू का इस्तेमाल करते हैं, इसलिए हम उन तरीकों पर लगातार नज़र रखेंगे जिनसे वेब कॉन्टेंट को तोड़े बिना, उन्हें थ्रॉटल किया जा सकता है. साथ ही, इस्तेमाल के उदाहरणों के हिसाब से एपीआई को जोड़ा/बदला जा सकता है. निजी तौर पर, हम कम फ़्रीक्वेंसी वाले ऐनिमेशन कॉलबैक के लिए, animationInterval की ज़रूरत को खत्म करना चाहते हैं. अगर आपका कोई सवाल है, तो कृपया Twitter पर हमसे संपर्क करें!

Unsplash पर हेदर ज़ैब्रिस्की की हेडर फ़ोटो.