पांच तरीके, AirSHIFT ने अपने React ऐप्लिकेशन के रनटाइम परफ़ॉर्मेंस को बेहतर बनाया है

React SPA की परफ़ॉर्मेंस ऑप्टिमाइज़ेशन की असल दुनिया की केस स्टडी.

Kento Tsuji
Kento Tsuji
Satoshi Arai
Satoshi Arai
Yusuke Utsunomiya
Yusuke Utsunomiya
Yosuke Furukawa
Yosuke Furukawa

वेबसाइट की परफ़ॉर्मेंस का मतलब सिर्फ़ पेज लोड होने में लगने वाले समय से नहीं है. उपयोगकर्ताओं को तेज़ और रिस्पॉन्सिव अनुभव देना ज़रूरी है. खास तौर पर, ऐसे डेस्कटॉप ऐप्लिकेशन के लिए जिनका इस्तेमाल लोग हर दिन करते हैं. Recruit Technologies की इंजीनियरिंग टीम ने, उपयोगकर्ताओं से बेहतर इनपुट पाने के लिए, अपने एक वेब ऐप्लिकेशन AirSHIFT को बेहतर बनाने के लिए, एक रीफ़ैक्टरिंग प्रोजेक्ट किया. आइए जानते हैं कि उन्होंने इसे कैसे किया.

धीमा जवाब, कम उत्पादकता

AirSHIFT एक डेस्कटॉप वेब ऐप्लिकेशन है, जो रेस्टोरेंट और कैफ़े जैसे स्टोर के मालिकों की, स्टाफ़ के सदस्यों की शिफ़्ट वाले काम को मैनेज करने में मदद करता है. 'रिऐक्ट' की मदद से बनाया गया एक ही पेज का ऐप्लिकेशन, क्लाइंट को कई सुविधाएं देता है. इसमें दिन, हफ़्ते, महीने वगैरह के हिसाब से शिफ़्ट शेड्यूल की अलग-अलग ग्रिड टेबल शामिल हैं.

AirSHIFT वेब ऐप्लिकेशन का स्क्रीनशॉट.

जैसे ही Recruit Technologies की इंजीनियरिंग टीम ने AirSHIFT ऐप्लिकेशन में नई सुविधाएं जोड़ी हैं, उन्हें ऐप्लिकेशन की धीमी परफ़ॉर्मेंस के बारे में ज़्यादा सुझाव मिलने शुरू हो गए हैं. AirSHIFT के इंजीनियरिंग मैनेजर, योसुक फ़ुरुकावा ने कहा:

उपयोगकर्ताओं पर एक रिसर्च स्टडी के मुताबिक, जब एक स्टोर के मालिक ने कहा कि वह बटन पर क्लिक करने के बाद कॉफ़ी बनाने के लिए अपनी सीट से निकल जाएगी, तो शिफ़्ट टेबल के लोड होने का इंतज़ार करने में समय बचेगा.

रिसर्च के बाद, इंजीनियरिंग टीम को पता चला कि उनके कई उपयोगकर्ता, 10 साल पहले के 1 GHz Celeron M लैपटॉप जैसे कम क्षमता वाले कंप्यूटर पर, बहुत बड़ी शिफ़्ट टेबल लोड करने की कोशिश कर रहे थे.

लो एंड डिवाइसों पर कभी न खत्म होने वाला स्पिनर.

AirSHIFT ऐप्लिकेशन, मुख्य थ्रेड को महंगी स्क्रिप्ट वाले ब्लॉक कर रहा था, लेकिन इंजीनियरिंग टीम को स्क्रिप्ट की महंगी चीज़ों के बारे में पता नहीं था, क्योंकि वे तेज़ वाई-फ़ाई कनेक्शन वाले बेहतरीन तकनीकी कंप्यूटर पर डेवलप और टेस्ट कर रही थीं.

ऐप्लिकेशन की रनटाइम गतिविधि को दिखाने वाला चार्ट.
शिफ़्ट टेबल लोड करते समय, स्क्रिप्ट चलाने से लोड होने में लगने वाले 80% समय का इस्तेमाल हो गया.

सीपीयू और नेटवर्क थ्रॉटलिंग के साथ Chrome DevTools में उनकी परफ़ॉर्मेंस की प्रोफ़ाइल बनाने के बाद, यह साफ़ तौर पर पता चला कि परफ़ॉर्मेंस को ऑप्टिमाइज़ करने की ज़रूरत थी. AirSHIFT ने इस समस्या को हल करने के लिए एक टास्क फ़ोर्स बनाई है. उपयोगकर्ता के इनपुट के हिसाब से ऐप्लिकेशन को ज़्यादा बेहतर बनाने के लिए, उन्होंने इन 5 चीज़ों पर फ़ोकस किया.

1. बड़ी टेबल वर्चुअलाइज़ करें

शिफ़्ट टेबल को दिखाने के लिए कई महंगे चरणों की ज़रूरत थी: वर्चुअल डीओएम बनाना और स्टाफ़ के सदस्यों की संख्या और टाइम स्लॉट के अनुपात में उसे स्क्रीन पर रेंडर करना. उदाहरण के लिए, अगर किसी रेस्टोरेंट में काम करने वाले 50 सदस्य हैं और वे हर महीने के हिसाब से शिफ़्ट का शेड्यूल देखना चाहते हैं, तो यह 50 (सदस्य) वाली टेबल को 30 (दिन) से गुणा करने पर मिलने वाली टेबल होगी. इस टेबल में 1,500 सेल वाले कॉम्पोनेंट को रेंडर करने के लिए इस्तेमाल किया जाएगा. यह एक बहुत महंगा ऑपरेशन है, खास तौर पर कम सुविधाओं वाले डिवाइसों के लिए. असल में, चीज़ें काफ़ी खराब थीं. रिसर्च से पता चला कि ऐसी दुकानें मौजूद थीं जहां 200 कर्मचारी कर्मचारी मैनेज करते थे और इनके लिए एक महीने में एक टेबल में करीब 6,000 सेल कॉम्पोनेंट की ज़रूरत होती थी.

इस ऑपरेशन की लागत को कम करने के लिए, AirSHIFT ने शिफ़्ट टेबल को वर्चुअलाइज़ किया है. ऐप्लिकेशन अब कॉम्पोनेंट को सिर्फ़ व्यूपोर्ट में माउंट करता है और ऑफ़-स्क्रीन वाले कॉम्पोनेंट को अलग करता है.

जानकारी देने वाला एक स्क्रीनशॉट, जिसमें यह दिखाया गया है कि AirSHIFT का इस्तेमाल, व्यूपोर्ट के बाहर कॉन्टेंट को रेंडर करने के लिए किया जाता है.
पहले: Shift टेबल की सभी सेल रेंडर करना.
जानकारी देने वाला एक स्क्रीनशॉट, जिसमें यह दिखाया गया है कि AirSHIFT अब सिर्फ़ उस कॉन्टेंट को रेंडर करता है जो व्यूपोर्ट में दिखता है.
बाद में: सिर्फ़ व्यूपोर्ट में सेल को रेंडर करना.

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

नतीजे

टेबल को वर्चुअल तौर पर इस्तेमाल करने से, स्क्रिप्टिंग का समय 6 सेकंड कम हो गया (चार गुना सीपीयू स्लोडाउन + फ़ास्ट 3G थ्रॉटल होने वाला Macbook Pro एनवायरमेंट). रीफ़ैक्टरिंग प्रोजेक्ट में, यह परफ़ॉर्मेंस में सबसे ज़्यादा सुधार था.

Chrome DevTools के परफ़ॉर्मेंस पैनल की रिकॉर्डिंग की जानकारी देने वाला स्क्रीनशॉट.
पहले: उपयोगकर्ता के इनपुट के बाद, स्क्रिप्टिंग के करीब 10 सेकंड बाद.
Chrome DevTools के परफ़ॉर्मेंस पैनल की रिकॉर्डिंग की जानकारी देने वाला एक और स्क्रीनशॉट.
उपयोगकर्ता के इनपुट के बाद: चार सेकंड की स्क्रिप्टिंग के बाद.

2. User Timing API की मदद से ऑडिट करें

इसके बाद, AirSHIFT टीम ने उपयोगकर्ता के इनपुट पर चलने वाली स्क्रिप्ट को फिर से बांटा है. Chrome DevTools के फ़्लेम चार्ट की मदद से, यह विश्लेषण किया जा सकता है कि मुख्य थ्रेड में क्या हो रहा है. हालांकि, AirSHIFT टीम को React की लाइफ़साइकल के आधार पर ऐप्लिकेशन गतिविधि का विश्लेषण करना आसान लगा.

React 16, User Timing API की मदद से परफ़ॉर्मेंस ट्रेस देता है. इसे Chrome DevTools के समय सेक्शन से विज़ुअलाइज़ किया जा सकता है. AirSHIFT ने रिऐक्ट लाइफ़साइकल इवेंट में चल रहे ग़ैर-ज़रूरी लॉजिक का पता लगाने के लिए, समय सेक्शन का इस्तेमाल किया है.

Chrome DevTools के परफ़ॉर्मेंस पैनल का समय सेक्शन.
प्रतिक्रिया से जुड़े उपयोगकर्ता समय के इवेंट.

नतीजे

AirSHIFT टीम को पता चला कि हर रूट नेविगेशन से ठीक पहले एक ग़ैर-ज़रूरी रिऐक्ट ट्री का मिलान हो रहा है. इसका मतलब था कि रिऐक्ट, नेविगेशन से पहले ही Shift टेबल को बेवजह अपडेट कर रहा था. ग़ैर-ज़रूरी Redux स्टेट अपडेट की वजह से यह समस्या हो रही थी. इसे ठीक करने से स्क्रिप्टिंग में लगने वाला करीब 750 मि॰से॰ समय बचा. AirSHIFT ने अन्य माइक्रो ऑप्टिमाइज़ेशन भी किए हैं, जिससे स्क्रिप्टिंग के समय में कुल 1 सेकंड की कमी आई.

3. लेज़ी लोड कॉम्पोनेंट और महंगे लॉजिक को वेब वर्कर पर ले जाना

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

इस सुविधा को बेहतर बनाने के लिए, अब AirSHIFT, टेबल के कॉन्टेंट के लिए प्लेसहोल्डर दिखाने के लिए React.lazy और Suspense का इस्तेमाल करता है. साथ ही, असली कॉम्पोनेंट को लेज़ी तरीके से लोड करता है.

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

आम तौर पर, डेवलपर को कर्मचारियों का इस्तेमाल करने में परेशानी होती है, लेकिन इस बार Comlink ने उनका सबसे बड़ा काम किया. यहां एक pseudo code है, जिससे यह पता चलता है कि AirSHIFT के मामले में, उसके सबसे महंगे कामों में से एक को कैसे लागू किया जाता है: कर्मचारियों की कुल लागत का हिसाब लगाना.

App.js में, लोड करते समय फ़ॉलबैक कॉन्टेंट दिखाने के लिए React.lazy और Suspense का इस्तेमाल करें

/** App.js */
import React, { lazy, Suspense } from 'react'

// Lazily loading the Cost component with React.lazy
const Hello = lazy(() => import('./Cost'))

const Loading = () => (
  <div>Some fallback content to show while loading</div>
)

// Showing the fallback content while loading the Cost component by Suspense
export default function App({ userInfo }) {
   return (
    <div>
      <Suspense fallback={<Loading />}>
        <Cost />
      </Suspense>
    </div>
  )
}

लागत कॉम्पोनेंट में, कैल्क लॉजिक को एक्ज़ीक्यूट करने के लिए, comlink का इस्तेमाल करें

/** Cost.js */
import React from 'react';
import { proxy } from 'comlink';

// import the workerlized calc function with comlink
const WorkerlizedCostCalc = proxy(new Worker('./WorkerlizedCostCalc.js'));
export default async function Cost({ userInfo }) {
  // execute the calculation in the worker
  const instance = await new WorkerlizedCostCalc();
  const cost = await instance.calc(userInfo);
  return <p>{cost}</p>;
}

वर्कर में चलने वाला कैलकुलेशन लॉजिक लागू करना और उसे कंपाइल करने के साथ दिखाना

// WorkerlizedCostCalc.js
import { expose } from 'comlink'
import { someExpensiveCalculation } from './CostCalc.js'

// Expose the new workerlized calc function with comlink
expose({
  calc(userInfo) {
    // run existing (expensive) function in the worker
    return someExpensiveCalculation(userInfo);
  }
}, self);

नतीजे

मुफ़्त में आज़माने के लिए इस्तेमाल किए जाने वाले लॉजिक के सीमित होने के बावजूद, AirSHIFT ने अपने JavaScript के करीब 100 मि॰से॰ को मुख्य थ्रेड से वर्कर थ्रेड (4x सीपीयू थ्रॉटलिंग के साथ सिम्युलेट) में शिफ़्ट किया है.

Chrome DevTools के परफ़ॉर्मेंस पैनल की रिकॉर्डिंग का स्क्रीनशॉट. इसमें दिखाया गया है कि स्क्रिप्टिंग अब मुख्य थ्रेड के बजाय, वेब वर्कर पर हो रही है.

फ़िलहाल, AirSHIFT यह एक्सप्लोर कर रहा है कि क्या अन्य कॉम्पोनेंट को लेज़ी लोड किया जा सकता है और जैंक को और कम करने के लिए, वेब वर्कर को ज़्यादा लॉजिक ऑफ़लोड किया जा सकता है या नहीं.

4. परफ़ॉर्मेंस बजट सेट करना

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

  • हर Redux इवेंट के लिए, स्क्रिप्ट पूरा होने में लगने वाला समय अब मेज़र किया जाता है
  • परफ़ॉर्मेंस का डेटा, Elasticsearch में इकट्ठा किया जाता है
  • हर इवेंट के 10वें, 25वें, 50वें, और 75वें पर्सेंटाइल की परफ़ॉर्मेंस को Kibana के साथ विज़ुअलाइज़ किया जाता है

AirSHIFT अब शिफ़्ट टेबल लोड होने के इवेंट पर नज़र रख रहा है, ताकि यह पक्का किया जा सके कि यह 75वें पर्सेंटाइल पर उपयोगकर्ताओं के लिए तीन सेकंड में पूरा हो जाए. फ़िलहाल, यह बजट लागू नहीं है, लेकिन बजट से ज़्यादा होने पर वे Elasticsearch के ज़रिए अपने-आप सूचनाएं पाने की सुविधा के बारे में सोच रहे हैं.

चार्ट से पता चलता है कि 75वां पर्सेंटाइल करीब 2, 500 मि॰से॰ में पूरा हो जाता है. 50वां पर्सेंटाइल करीब 1250 मि॰से॰ में, 25वां पर्सेंटाइल (करीब 750 मि॰से॰), और 10वां पर्सेंटाइल करीब 500 मि॰से॰ में पूरा होता है.
Kibana डैशबोर्ड, पर्सेंटाइल के हिसाब से रोज़ की परफ़ॉर्मेंस का डेटा दिखाता है.

नतीजे

ऊपर दिए गए ग्राफ़ से, आप बता सकते हैं कि AirSHIFT अब ज़्यादातर 75वें पर्सेंटाइल पर उपयोगकर्ताओं के लिए, तीन सेकंड के बजट का इस्तेमाल कर रहा है. साथ ही, 25वें पर्सेंटाइल पर उपयोगकर्ताओं के लिए, शिफ़्ट टेबल एक सेकंड में लोड कर रही है. अलग-अलग स्थितियों और डिवाइसों से RUM की परफ़ॉर्मेंस का डेटा कैप्चर करके, AirSHIFT अब यह देख सकता है कि कोई नई सुविधा, ऐप्लिकेशन की परफ़ॉर्मेंस पर असल में असर डाल रही है या नहीं.

5. परफ़ॉर्मेंस हैकेथॉन (सॉफ़्टवेयर डेवलपमेंट इवेंट)

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

AirSHIFT, अब एक दिन की परफ़ॉर्मेंस से जुड़े आंतरिक हैकेथॉन शुरू कर रहा है, ताकि इंजीनियर सिर्फ़ परफ़ॉर्मेंस से जुड़े काम पर ध्यान दे सकें. इन हैकेथॉन में वे सारी सीमाएं दूर करते हैं और इंजीनियर की क्रिएटिविटी का सम्मान करते हैं. इसका मतलब है कि अगर तेज़ी से काम किया जाता है, तो उसके इस्तेमाल पर विचार किया जा सकता है. हैकेथॉन (सॉफ़्टवेयर डेवलपमेंट इवेंट) को तेज़ी से आगे बढ़ाने के लिए, AirSHIFT ग्रुप को छोटी टीमों में बांट देता है. इसमें हर टीम यह देखने के लिए मुकाबला करती है कि कौन Lighthouse परफ़ॉर्मेंस स्कोर में सबसे बड़ा सुधार कर सकता है. टीमों के बीच मुकाबला बहुत ज़्यादा है! 🔥

हैकेथॉन की फ़ोटो.

नतीजे

हैकेथॉन (सॉफ़्टवेयर डेवलपमेंट इवेंट) का तरीका, उनके लिए कारगर साबित हो रहा है.

  • हैकेथॉन (सॉफ़्टवेयर डेवलपमेंट इवेंट) के दौरान कई तरीके आज़माकर और हर तरीके को Lighthouse की मदद से, परफ़ॉर्मेंस में आने वाली रुकावटों का आसानी से पता लगाया जा सकता है.
  • हैकेथॉन के बाद, टीम को यह समझाना काफ़ी आसान है कि प्रोडक्शन रिलीज़ के लिए उन्हें किस ऑप्टिमाइज़ेशन को प्राथमिकता देनी चाहिए.
  • यह स्पीड की अहमियत को बढ़ावा देने का एक असरदार तरीका है. मीटिंग में हिस्सा लेने वाला हर व्यक्ति यह समझ सकता है कि आपके कोड कैसे जनरेट किए जाते हैं और इससे परफ़ॉर्मेंस कैसी होती है.

इसका एक अच्छा असर यह था कि Recruit की कई अन्य इंजीनियरिंग टीमों ने भी इस तरीके को अपनाने में दिलचस्पी दिखाई. AirSHIFT की टीम, अब कंपनी में तेज़ी से कई तरह के हैकेथॉन की सुविधा दे रही है.

खास जानकारी

इन ऑप्टिमाइज़ेशन पर काम करना, AirSHIFT के लिए सबसे आसान नहीं है, लेकिन इसका फ़ायदा ज़रूर मिल गया है. अब AirSHIFT के बीच शिफ़्ट टेबल को 1.5 सेकंड के अंदर लोड कर रहा है, जो कि प्रोजेक्ट से पहले की परफ़ॉर्मेंस से छह गुना बेहतर है.

परफ़ॉर्मेंस ऑप्टिमाइज़ेशन लॉन्च होने के बाद, एक उपयोगकर्ता ने कहा:

Shift टेबल को तेज़ी से लोड करने के लिए धन्यवाद. शिफ़्ट करने के काम को अब ज़्यादा बेहतर तरीके से किया जा सकता है.