परिचय: JavaScript प्रदर्शन क्यों महत्वपूर्ण है?
\nJavaScript (विशेषकर Node.js वातावरण में) आधुनिक वेब विकास की नींव बन गया है। कोड निष्पादन की गति न केवल उपयोगकर्ताओं की सुविधा को प्रभावित करती है, बल्कि सर्वर पर लोड को भी प्रभावित करती है। धीमे अनुप्रयोग दर्शकों को खो देते हैं, और अनुकूलित अनुरोध महंगी क्षमता वृद्धि का कारण बन सकते हैं। इस लेख में, हम प्रदर्शन अनुकूलन के बुनियादी लेकिन प्रभावी तरीकों पर चर्चा करेंगे जो शुरुआती लोगों के लिए भी उपयुक्त हैं।
\nहम तीन प्रमुख क्षेत्रों को कवर करेंगे: एसिंक्रोनस प्रोग्रामिंग, मेमोरी प्रबंधन और प्रोफाइलिंग। सभी उदाहरण Node.js पर होंगे।
\n\n1. एसिंक्रोनस: Event Loop को ब्लॉक होने से बचाना
\nNode.js Event Loop का उपयोग करके सिंगल-थ्रेडेड मोड में काम करता है। यदि आप कोई सिंक्रोनस भारी ऑपरेशन करते हैं (जैसे बड़ी फ़ाइल पढ़ना या जटिल लूप), तो पूरा सर्वर उसके पूरा होने तक "फ्रीज" हो जाता है। इससे बचने के लिए, एसिंक्रोनस विधियों का उपयोग करें।
\nखराब उदाहरण (ब्लॉकिंग कोड):
\nconst fs = require('fs');\nconst data = fs.readFileSync('/bigfile.txt', 'utf8'); // थ्रेड को ब्लॉक करता है\nconsole.log('फ़ाइल पढ़ी गई');\n\nअच्छा उदाहरण (नॉन-ब्लॉकिंग):
\nconst fs = require('fs').promises;\nasync function readFile() {\n const data = await fs.readFile('/bigfile.txt', 'utf8');\n console.log('फ़ाइल पढ़ी गई');\n}\nreadFile();\n\nसभी इनपुट/आउटपुट (I/O) ऑपरेशनों के लिए async/await और प्रॉमिस का उपयोग करें। यह Event Loop को डेटाबेस या फ़ाइल सिस्टम से प्रतिक्रिया की प्रतीक्षा करते समय अन्य अनुरोधों को संसाधित करने की अनुमति देता है।
सुझाव: Production में सिंक्रोनस विधियों से बचें
\nfs.readFileSync या crypto.pbkdf2Sync जैसी विधियाँ केवल एप्लिकेशन स्टार्टअप पर स्वीकार्य हैं। रनटाइम में, उनके एसिंक्रोनस संस्करणों का उपयोग करें।
2. मेमोरी प्रबंधन और लीक का अनुकूलन
\nमेमोरी लीक Node.js अनुप्रयोगों के प्रदर्शन में गिरावट के सामान्य कारणों में से एक है। ये तब होते हैं जब ऑब्जेक्ट मेमोरी में रहते हैं, भले ही उनकी अब आवश्यकता न हो।
\nलीक के मुख्य कारण:
\n- \n
- ग्लोबल वेरिएबल \n
- साफ न किए गए टाइमर (clearInterval के बिना setInterval) \n
- क्लोजर में बंद संदर्भ \n
- ईवेंट लिसनर जो हटाए नहीं जाते \n
लिसनर के माध्यम से लीक का उदाहरण:
\nconst EventEmitter = require('events');\nconst emitter = new EventEmitter();\n\nfunction processRequest() {\n emitter.on('data', (chunk) => {\n // डेटा प्रोसेसिंग\n });\n}\n// processRequest का प्रत्येक कॉल एक नया लिसनर जोड़ता है, लेकिन पुराने को नहीं हटाता!\n\nसमाधान: लिसनर हटाएं या once का उपयोग करें
\nemitter.once('data', (chunk) => {\n // केवल एक बार निष्पादित होगा और स्वचालित रूप से हटा दिया जाएगा\n});\n\nमेमोरी विश्लेषण के लिए heapdump जैसी उपयोगिताओं का उपयोग करना भी उपयोगी है। लेकिन शुरुआत में, यह सुनिश्चित करना पर्याप्त है कि ऑब्जेक्ट के संदर्भ ग्लोबल स्कोप में न रहें।
3. कैशिंग और प्रोफाइलिंग
\nकैशिंग भारी गणनाओं को बार-बार करने से बचाती है। प्रोफाइलिंग कोड में बाधाओं को खोजने में मदद करती है।
\nMap का उपयोग करके सरल कैशिंग:
\nconst cache = new Map();\n\nfunction expensiveCalculation(input) {\n if (cache.has(input)) {\n console.log('कैश से');\n return cache.get(input);\n }\n const result = input * 1000 + Math.random(); // जटिल लॉजिक का अनुकरण\n cache.set(input, result);\n return result;\n}\n\nconsole.log(expensiveCalculation(5)); // गणना करें\nconsole.log(expensiveCalculation(5)); // कैश से\n\nअधिक जटिल परिदृश्यों के लिए, node-cache या Redis जैसी लाइब्रेरी का उपयोग करें।
Node.js के अंतर्निहित टूल से प्रोफाइलिंग
\nएप्लिकेशन को --prof फ्लैग के साथ चलाएं:
node --prof app.js\n\nएप्लिकेशन रोकने के बाद, फ़ोल्डर में isolate-*.log फ़ाइल दिखाई देगी। इसे च में बदलें