JavaScript टूलिंग स्पेस में अधिकांश परफॉरमेंस के दावे दूध की तरह जल्दी खराब होने वाले होते हैं। कोई किसी शांत मंगलवार की सुबह कुछ पैकेज इंस्टॉल करता है, टर्मिनल आउटपुट कैप्चर करता है, और एक नाटकीय बार चार्ट प्रकाशित कर देता है। अगली स्प्रिंट तक, इनमें से किसी एक टूल ने एक ऐसा पैच जारी कर दिया होता है जो पूरी बात को ही गलत साबित कर देता है। वह पोस्ट सर्च इंजन द्वारा इंडेक्स रहती है। चार्ट शेयर किया जाता रहता है। हालाँकि, वे नंबर आपसे झूठ बोल रहे होते हैं।
यह वह सड़न है जो लगभग सभी पैकेज मैनेजर बेंचमार्क को संक्रमित करती है। वे इवेंट फोटोग्राफी की तरह हैं, जबकि हमें एक लाइव फीड की ज़रूरत है।
depjs/canary नामक एक प्रोजेक्ट इस समस्या को कंटेंट कैलेंडर के काम के बजाय मशीन की ज़िम्मेदारी के रूप में देखता है। यह एक जीवंत बेंचमार्क है जो npm, pnpm, Yarn, और dep पर नज़र रखता है, और जैसे ही उनमें से कोई भी नया वर्ज़न प्रकाशित करता है, यह अपना पूरा सूट फिर से चलाता है। परिणाम सार्वजनिक, निरंतर और अपरिहार्य हैं। जब कुछ टूटता है, तो रिपॉजिटरी तब तक लाल (red) रहती है जब तक कि वह ठीक न हो जाए। यहाँ कोई चयनात्मक डेटा (cherry-picking) नहीं है, किसी पुराने ब्लॉग पोस्ट के पीछे छिपने की गुंजाइश नहीं है, और यह धारणा भी नहीं है कि पिछले महीने का विजेता अभी भी बरकरार है।
स्पीड के दावों को एक्सपायरी डेट की ज़रूरत क्यों है
JavaScript पैकेज मैनेजर स्थिर नहीं रहते। माइनर वर्ज़न के बीच का अंतर पुनर्गठित रेज़ोल्यूशन एल्गोरिदम, बदली हुई होइस्टिंग रणनीतियों, या ग्लोबल कैश को की (key) करने के तरीके में बदलाव को शामिल कर सकता है। एक बेंचमार्क जो npm 10.2.1 और pnpm 8.11.0 को कैप्चर करता है, वह आपको लगभग कुछ नहीं बताता कि वही टूल दो रिलीज़ बाद कैसा व्यवहार करते हैं। फिर भी, वेब ठीक उसी तरह के जमे हुए स्नैपशॉट के आधार पर "टूल X तीन गुना तेज़ है" जैसे निश्चित बयानों से भरा हुआ है।
इससे भी बुरा यह है कि कई टेस्ट उन स्थितियों को नज़रअंदाज़ कर देते हैं जो डेवलपर्स की वास्तविक समस्याओं को परिभाषित करती हैं। एक पैकेज मैनेजर एक वॉर्म (warm) और अच्छी तरह से तैयार वातावरण में इंस्टॉलेशन को बहुत तेज़ी से पूरा कर सकता है, लेकिन एक ऐसे CI रनर पर बहुत धीमा हो सकता है जो खाली डिस्क के साथ शुरू होता है। दोनों चरम सीमाओं का परीक्षण किए बिना, बेंचमार्क उपयोगी इंजीनियरिंग डेटा के बजाय केवल एक प्रेस रिलीज़ बनकर रह जाता है।
कैनरी (Canary) तुलना को कैसे ऑटोमेट करता है
हर दो घंटे में, एक जॉब npm रजिस्ट्री को पोल (poll) करती है। यदि npm, pnpm, Yarn, या dep का कोई नया वर्ज़न दिखाई देता है, तो कैनरी जाग जाता है। यह किसी इंसान के चेंजलॉग (changelog) पर ध्यान देने का इंतज़ार नहीं करता है। यह तुरंत एक पूर्ण टेस्ट मैट्रिक्स चलाता है जो चारों मैनेजर्स की तुलना पाँच लोकप्रिय, वास्तविक-दुनिया के पैकेजों से करता है। इस चयन में React, Next.js, और Vite जैसे बड़े नाम शामिल हैं, वे कोडबेस जिन्हें वास्तविक डेवलपर्स हर दिन इंस्टॉल करते हैं। ये किसी एक विशेष टूल की प्रशंसा करने के लिए बनाए गए सिंथेटिक माइक्रो-प्रोजेक्ट्स नहीं हैं।
यह रिलीज़-ट्रिगर आधारित दृष्टिकोण महत्वपूर्ण है क्योंकि यह मापन (measurement) को सीधे बदलाव से जोड़ता है। यदि बेंचमार्क केवल एक नाइटली शेड्यूल पर चलता, तो यह दिन के बीच में आए किसी हॉटफिक्स को मिस कर सकता था या घंटों तक किसी रिग्रेशन (regression) को नज़रअंदाज़ कर सकता था। विशेष रूप से नए वर्ज़न पर चलने के कारण, कैनरी हर बार एक सीधा सवाल पूछता है: क्या इस रिलीज़ ने चीज़ों को बेहतर बनाया या बदतर?
चार परिदृश्य जो अलग-अलग क्षमताओं का परीक्षण करते हैं
टेस्ट मैट्रिक्स चार अलग-अलग सेटअप के इर्द-गिर्द बनाया गया है जो सीधे उन वर्कफ़्लो से मेल खाते हैं जिन्हें आप पहचानेंगे।
- कोल्ड कैश, कोई लॉकफ़ाइल नहीं। यह एक नए लैपटॉप पर किया गया फ्रेश क्लोन है, या
node_modulesको हटाने के बाद पहला इंस्टॉलेशन है। कुछ भी कैश नहीं है। कुछ भी पिन नहीं है। पैकेज मैनेजर को सब कुछ शुरू से ही रेज़ॉल्व, फ़ेच और राइट करना पड़ता है। - वॉर्म कैश, लॉकफ़ाइल के साथ। यह कंटीन्यूअस इंटीग्रेशन के लिए 'हैप्पी पाथ' है जब सब कुछ सही होता है। लॉकफ़ाइल स्थानीय रूप से मौजूद होती है, और कैश में पिछले रन के टारबॉल्स (tarballs) अभी भी होते हैं। टूल को तेज़ी से काम करना चाहिए क्योंकि अधिकांश निर्णय पहले ही लिए जा चुके हैं।
- कोल्ड कैश, लॉकफ़ाइल के साथ। यहाँ लॉकफ़ाइल मौजूद है, लेकिन कैश मिटा दिया गया है। मैनेजर डिपेंडेंसी रेज़ोल्यूशन को छोड़ सकता है, फिर भी उसे नेटवर्क के माध्यम से हर बाइट डाउनलोड करनी पड़ती है। यह नेटवर्क की गति को रेज़ोल्यूशन की गति से अलग करता है।
- वॉर्म कैश, कोई लॉकफ़ाइल नहीं। कैश वॉर्म है, लेकिन लॉकफ़ाइल गायब है। पैकेज मैनेजर को फ़ाइलों को निकालना शुरू करने से पहले डिपेंडेंसी ट्री को फिर से रेज़ॉल्व करना होगा। यह आदर्श नेटवर्क स्थितियों के तहत सॉल्वर और मेटाडेटा पार्सर की दक्षता का परीक्षण करता है।
प्रत्येक परिदृश्य को पाँच बार निष्पादित किया जाता है, और कैनरी मीडियन (median) परिणाम रखता है। यह एक अकेला चुनाव बहुत सारे शोर (noise) को खत्म कर देता है। नेटवर्क में होने वाली कोई भी अस्थायी समस्या या रजिस्ट्री लेटेंसी में अचानक वृद्धि पूरी कहानी को भटका नहीं सकती। आउटलायर (outlier) को नज़रअंदाज़ कर दिया जाता है; सामान्य अनुभव को रिकॉर्ड किया जाता है।
स्मोक टेस्ट खाली टाइमर से बेहतर हैं
केवल गति को धोखा देना आसान है यदि आप परिणाम की पुष्टि नहीं करते हैं। एक पैकेज मैनेजर postinstall चरणों को छोड़ सकता है, कुछ symlinks को खराब कर सकता है, या गलत वर्ज़न इंस्टॉल कर सकता है और फिर भी एक प्रभावशाली टाइमस्टैम्प पोस्ट कर सकता है। canary केवल टाइमर पर रुकने से इनकार कर देता है। इंस्टॉलेशन पूरा होने के बाद, यह वास्तव में इंस्टॉल किए गए कोड का परीक्षण करता है।
उदाहरण के लिए, यह एक Express एप्लिकेशन को बूट करता है और पुष्टि करता है कि सर्वर अपेक्षित पोर्ट पर सुनना शुरू कर देता है। यदि कोड नहीं चलता है, तो बेंचमार्क पूरी तरह से विफल हो जाता है। smoke test इस सुइट को एक दौड़ से बदलकर एक ऑडिट में बदल देता है। यह उस प्रश्न का उत्तर देता है जिसका उत्तर केवल गति नहीं दे सकती: क्या इंस्टॉलेशन वास्तव में काम करता है?
एक फीचर के रूप में पूर्ण ईमानदारी
canary के लेखक ने प्रक्रिया में तीन नियम लिखे हैं जिन्हें अधिकांश बेंचमार्क लेखक वैकल्पिक मानते हैं।
समान आधार (Same playing field)। विभिन्न टूल्स के बीच व्यवहार को सामान्य बनाने के लिए Flags का उपयोग किया जाता है। यदि कोई पैकेज मैनेजर डिफ़ॉल्ट सेटिंग के पीछे प्रदर्शन की खामी को छिपाता है, तो बेंचमार्क इसे उजागर कर देता है, बजाय इसके कि टूल को गलती से अच्छा दिखने दे।
वास्तविक कोल्ड स्टार्ट (Genuine cold starts)। केवल पहली बार ही नहीं, बल्कि हर एक पुनरावृत्ति से पहले, npm cache और pnpm store को साफ़ कर दिया जाता है। वह शब्द "हर" (every) यहाँ बहुत महत्वपूर्ण भूमिका निभा रहा है। कई बेंचमार्क कैश को एक बार साफ़ करते हैं, और फिर लगातार पांच इंस्टॉलेशन चलाते हैं। दूसरी से पांचवीं रन वास्तव में 'कोल्ड' नहीं होती हैं, और संख्याएँ उसी के अनुसार बढ़ जाती हैं। canary हर बार शून्य से शुरू होता है।
सार्वजनिक विफलता की स्थिति (Public failure states)। जब कोई नया रिलीज़ किसी चीज़ को तोड़ता है, तो रिपॉजिटरी लाल विफलता (red failure) की स्थिति में रहती है। जब तक कोई सुधार (fix) नहीं आ जाता, तब तक यह फ्रंट पेज पर बदसूरत और अनसुलझी स्थिति में बनी रहती है। डैशबोर्ड को हरा दिखाने के लिए इसे चुपचाप दबाने का कोई तरीका नहीं है। यह नीति दृश्यता सुनिश्चित करती है। टूल्स का मूल्यांकन करने वाला उपयोगकर्ता न केवल यह देख सकता है कि कौन सा सबसे तेज़ है, बल्कि यह भी कि समय के साथ कौन सा विश्वसनीय रहा है।
निरीक्षण क्षमता समझौता न करने योग्य है
एक बेंचमार्क जिसे आप पुनरुत्पादित (reproduce) नहीं कर सकते, वह केवल एक प्रचार नारा है। canary इसे एक एकल bash script के साथ हल करता है जो किसी को भी सुइट के किसी भी हिस्से को स्थानीय रूप से चलाने की अनुमति देता है। आपको किसी क्लाउड प्रदाता के नेटवर्किंग या किसी मेंटेनर के हाथ से कॉन्फ़िगर किए गए वातावरण पर भरोसा करने की आवश्यकता नहीं है। यदि आपको संदेह है कि संख्याएँ गलत हैं, तो आप अपनी स्वयं की संख्याएँ उत्पन्न कर सकते हैं।
वह पारदर्शिता इस प्रोजेक्ट को मेंटेनर के लिए भी उपयोगी बनाती है। जब कोई रिग्रेशन (regression) आता है, तो एक डाउनस्ट्रीम डेवलपर स्क्रिप्ट को खींच सकता है, टूल के रिलीज़ को bisect कर सकता है, और अपस्ट्रीम टीम को एक
