---
title: "OpenResty में `string` के फायदे और नुकसान - API7.ai"
description: "यह लेख OpenResty में अपनाई जाने वाली ऑप्टिमाइज़ेशन तकनीकों का परिचय देता है: अनुरोधों को छोटा, सरल और तेज़ी से संसाधित करना और मध्यवर्ती डेटा उत्पन्न करने से बचना। यह स्ट्रिंग के लिए ऑप्टिमाइज़ेशन तकनीकों को भी दर्शाता है।"
url: "https://api7.ai/hi/learning-center/openresty/advantages-and-disadvantages-of-string"
---

# OpenResty में \`string\` के फायदे और नुकसान

API7.ai

December 8, 2022

[OpenResty (NGINX + Lua)](https://api7.ai/learning-center/openresty)

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

इस प्रक्रिया में, हमें अधिक टेस्ट कोड लिखने की आवश्यकता होगी ताकि हम इन ऑप्टिमाइज़ेशन तकनीक का उपयोग करने और उनकी प्रभावशीलता को सत्यापित करने का अनुभव कर सकें, ताकि हम उनका अच्छी तरह से उपयोग कर सकें।

## परफॉर्मेंस ऑप्टिमाइज़ेशन टिप्स के पीछे

ऑप्टिमाइज़ेशन तकनीक "प्रैक्टिस" भाग का हिस्सा हैं, इसलिए इससे पहले कि हम ऐसा करें, आइए ऑप्टिमाइज़ेशन के "थ्योरी" के बारे में बात करें।

परफॉर्मेंस ऑप्टिमाइज़ेशन विधियाँ LuaJIT और OpenResty के इटरेशन के साथ बदलती रहेंगी। कुछ विधियाँ सीधे अंडरलाइंग टेक्नोलॉजी द्वारा ऑप्टिमाइज़ की जा सकती हैं और उन्हें सीखने की आवश्यकता नहीं होगी; साथ ही, कुछ नई ऑप्टिमाइज़ेशन तकनीक भी आएंगी। इसलिए, इन ऑप्टिमाइज़ेशन तकनीक के पीछे के स्थिर अवधारणा को समझना सबसे महत्वपूर्ण है।

आइए OpenResty प्रोग्रामिंग में परफॉर्मेंस के बारे में कुछ महत्वपूर्ण विचारों पर नज़र डालें।

### थ्योरी 1: अनुरोधों को संक्षिप्त, सरल और तेज़ी से संसाधित करें

OpenResty एक वेब सर्वर है, इसलिए यह अक्सर 1,000+, 10,000+, या यहाँ तक कि 100,000+ क्लाइंट अनुरोधों को एक साथ संसाधित करता है। इसलिए, सर्वोच्च समग्र प्रदर्शन प्राप्त करने के लिए, हमें यह सुनिश्चित करना चाहिए कि व्यक्तिगत अनुरोधों को तेज़ी से संसाधित किया जाए और विभिन्न संसाधन, जैसे मेमोरी, को पुनः प्राप्त किया जाए।

- यहाँ "संक्षिप्त" का अर्थ है कि अनुरोध जीवनचक्र छोटा होना चाहिए ताकि संसाधनों को लंबे समय तक बिना रिलीज़ किए न रखा जाए; यहाँ तक कि लंबे कनेक्शन के लिए भी, समय या अनुरोधों की संख्या की एक सीमा निर्धारित करनी चाहिए ताकि संसाधनों को नियमित रूप से रिलीज़ किया जा सके।
- दूसरा "सरल" का अर्थ है कि एक API में केवल एक काम करें। जटिल बिजनेस लॉजिक को कई APIs में विभाजित करें और कोड को सरल रखें।
- अंत में, "तेज़" का अर्थ है कि मुख्य थ्रेड को ब्लॉक न करें और बहुत अधिक CPU ऑपरेशन न चलाएं। यदि आपको ऐसा करना ही है, तो पिछले लेख में हमने जिन अन्य विधियों का परिचय दिया था, उनके साथ काम करना न भूलें।

यह आर्किटेक्चरल विचार न केवल OpenResty के लिए उपयुक्त है, बल्कि आगे के विकास भाषाओं और प्लेटफॉर्म के लिए भी है, इसलिए मुझे आशा है कि आप इसे समझेंगे और इसके बारे में सोचेंगे।

### थ्योरी 2: मध्यवर्ती डेटा उत्पन्न करने से बचें

मध्यवर्ती प्रक्रिया में अनुपयोगी डेटा से बचना OpenResty प्रोग्रामिंग में सबसे प्रमुख ऑप्टिमाइज़ेशन थ्योरी है। आइए एक छोटे उदाहरण के माध्यम से मध्यवर्ती प्रक्रिया में अनुपयोगी डेटा को समझें।

```
$ resty -e 'local s= "hello"
s = s .. " world"
s = s .. "!"
print(s)
'
```

इस कोड स्निपेट में, हमने `s` वेरिएबल पर कई स्प्लिसिंग ऑपरेशन किए ताकि परिणाम `hello world!` प्राप्त हो। लेकिन केवल अंतिम `hello world!` स्थिति ही उपयोगी है। `s` का प्रारंभिक मान और मध्यवर्ती असाइनमेंट सभी मध्यवर्ती डेटा हैं जिन्हें कम से कम उत्पन्न करना चाहिए।

इसका कारण यह है कि ये अस्थायी डेटा इनिशियलाइज़ेशन और GC प्रदर्शन हानि लाते हैं। इन हानियों को कम न समझें; यदि यह लूप जैसे हॉट कोड में दिखाई देता है, तो प्रदर्शन स्पष्ट रूप से कम हो जाएगा। मैं इसे बाद में एक स्ट्रिंग उदाहरण के साथ समझाऊंगा।

## `string` अपरिवर्तनीय हैं

अब, इस लेख के विषय पर वापस आते हैं, `string`। यहाँ, मैं इस तथ्य पर प्रकाश डाल रहा हूँ कि Lua में `string` अपरिवर्तनीय हैं।

बेशक, इसका मतलब यह नहीं है कि `string` को स्प्लिस, मॉडिफाई आदि नहीं किया जा सकता, लेकिन जब हम एक `string` को मॉडिफाई करते हैं, तो हम मूल `string` को नहीं बदलते बल्कि एक नया `string` ऑब्जेक्ट बनाते हैं और `string` के रेफरेंस को बदलते हैं। इसलिए स्वाभाविक रूप से, यदि मूल `string` का कोई अन्य रेफरेंस नहीं है, तो इसे Lua के GC (गार्बेज कलेक्शन) द्वारा रिकवर कर लिया जाएगा।

अपरिवर्तनीय `string` का स्पष्ट लाभ यह है कि यह मेमोरी बचाता है। इस तरह, मेमोरी में एक ही `string` की केवल एक कॉपी होगी, और अलग-अलग वेरिएबल एक ही मेमोरी एड्रेस की ओर इशारा करेंगे।

इस डिज़ाइन का नुकसान यह है कि जब `string` जोड़ने और रिक्लेम करने की बात आती है, तो हर बार जब आप एक `string` जोड़ते हैं, LuaJIT को `lj_str_new` को कॉल करना पड़ता है ताकि पता लगाया जा सके कि क्या `string` पहले से मौजूद है; यदि नहीं, तो एक नया `string` बनाना पड़ता है। यदि आप इसे बहुत बार करते हैं, तो यह प्रदर्शन पर बहुत बड़ा प्रभाव डालेगा।

आइए इस उदाहरण में दिए गए `string` स्प्लिसिंग ऑपरेशन का एक ठोस उदाहरण देखें, जो कई OpenResty ओपन सोर्स प्रोजेक्ट्स में पाया जाता है।

```
$ resty -e 'local begin = ngx.now()
local s = ""
-- `for` लूप, `..` का उपयोग करके स्ट्रिंग स्प्लिसिंग करें
for i = 1, 100000 do
    s = s .. "a"
end
ngx.update_time()
print(ngx.now() - begin)
'
```

यह सैंपल कोड `s` वेरिएबल पर 100,000 बार `string` स्प्लिसिंग करता है और रनटाइम प्रिंट करता है। हालांकि उदाहरण थोड़ा चरम है, लेकिन यह परफॉर्मेंस ऑप्टिमाइज़ेशन से पहले और बाद के अंतर को अच्छी तरह से दिखाता है। ऑप्टिमाइज़ेशन के बिना, यह कोड मेरे लैपटॉप पर 0.4 सेकंड में चलता है, जो अभी भी अपेक्षाकृत धीमा है। तो हमें इसे कैसे ऑप्टिमाइज़ करना चाहिए?

पिछले लेखों में, उत्तर दिया गया था, जो कि `table` का उपयोग करके एक परत का एनकैप्सुलेशन करना है, सभी अस्थायी मध्यवर्ती `string` को हटाना और केवल मूल डेटा और अंतिम परिणाम को रखना। आइए ठोस कोड इम्प्लीमेंटेशन देखें।

```
$ resty -e 'local begin = ngx.now()
local t = {}
-- for लूप जो स्ट्रिंग को रखने के लिए एक ऐरे का उपयोग करता है, हर बार ऐरे की लंबाई गिनता है
for i = 1, 100000 do
    t[#t + 1] = "a"
end
-- ऐरे के concat मेथड का उपयोग करके स्ट्रिंग्स को जोड़ें
local s =  table.concat(t, "")
ngx.update_time()
print(ngx.now() - begin)
'
```

हम देख सकते हैं कि यह कोड प्रत्येक स्ट्रिंग को `table` में बारी-बारी से सेव करता है, और इंडेक्स `#t + 1` द्वारा निर्धारित किया जाता है, यानी `table` की वर्तमान लंबाई प्लस `1`। अंत में, `table.concat` फ़ंक्शन का उपयोग करके प्रत्येक ऐरे एलिमेंट को जोड़ा जाता है। यह स्वाभाविक रूप से सभी अस्थायी स्ट्रिंग्स को छोड़ देता है और 100,000 बार `lj_str_new` और GC से बचता है।

यह हमारा कोड विश्लेषण था, लेकिन ऑप्टिमाइज़ेशन कैसे काम करता है? ऑप्टिमाइज़ किया गया कोड केवल 0.007 सेकंड लेता है, जो 50 गुना से अधिक प्रदर्शन सुधार दिखाता है। एक वास्तविक प्रोजेक्ट में, प्रदर्शन सुधार और भी अधिक स्पष्ट हो सकता है क्योंकि इस उदाहरण में हमने केवल एक बार में एक कैरेक्टर `a` जोड़ा है।

यदि नया `string` 10x `a` की लंबाई में होता है, तो प्रदर्शन अंतर क्या होगा?

क्या 0.007 सेकंड का कोड हमारे ऑप्टिमाइज़ेशन कार्य के लिए पर्याप्त है? नहीं, इसे और भी ऑप्टिमाइज़ किया जा सकता है। आइए एक और लाइन कोड को संशोधित करें और परिणाम देखें।

```
$ resty -e 'local begin = ngx.now()
local t = {}
-- for लूप, स्ट्रिंग को रखने के लिए एक ऐरे का उपयोग करें, ऐरे की लंबाई को स्वयं बनाए रखें
for i = 1, 100000 do
    t[i] = "a"
end
local s =  table.concat(t, "")
ngx.update_time()
print(ngx.now() - begin)
'
```

इस बार, हमने `t[#t + 1] = "a"` को `t[i] = "a"` में बदल दिया, और केवल एक लाइन कोड से, हम ऐरे की लंबाई प्राप्त करने के लिए 100,000 फ़ंक्शन कॉल से बच सकते हैं। क्या आपको `table` सेक्शन में पहले बताया गया ऐरे की लंबाई प्राप्त करने का ऑपरेशन याद है? इसकी टाइम कॉम्प्लेक्सिटी `O(n)` है, जो एक अपेक्षाकृत महंगा ऑपरेशन है। इसलिए, यहाँ हम केवल अपने ऐरे इंडेक्स को बनाए रखकर ऐरे की लंबाई प्राप्त करने के ऑपरेशन को बायपास करते हैं। जैसा कि कहा जाता है, यदि आप इसे संभाल नहीं सकते, तो इसे टाल दें।

बेशक, यह एक सरल तरीका है। निम्नलिखित कोड और अधिक स्पष्ट रूप से दिखाता है कि कैसे हम स्वयं ऐरे के इंडेक्स को बनाए रख सकते हैं।

```
$ resty -e 'local begin = ngx.now()
local t = {}
local index = 1
for i = 1, 100000 do
    t[index] = "a"
    index = index + 1
end
local s = table.concat(t, "")
ngx.update_time()
print(ngx.now() - begin)
'
```

## अन्य अस्थायी `string` को कम करें

जिन गलतियों के बारे में हमने अभी बात की, `string` स्प्लिसिंग के कारण अस्थायी `string`, स्पष्ट हैं। ऊपर दिए गए सैंपल कोड के कुछ रिमाइंडर के साथ, मुझे विश्वास है कि हम फिर से इसी तरह की गलतियाँ नहीं करेंगे। हालांकि, OpenResty में कुछ और छिपे हुए अस्थायी `string` उत्पन्न होते हैं, जिनका पता लगाना बहुत कम आसान होता है। उदाहरण के लिए, नीचे हम जिस `string` हैंडलिंग फ़ंक्शन के बारे में बात करेंगे, वह अक्सर उपयोग किया जाता है। क्या आप कल्पना कर सकते हैं कि यह भी अस्थायी `string` उत्पन्न करता है?

जैसा कि हम जानते हैं, `string.sub` फ़ंक्शन एक `string` के निर्दिष्ट भाग को इंटरसेप्ट करता है। जैसा कि हमने पहले बताया, Lua में `string` अपरिवर्तनीय हैं, इसलिए एक नई स्ट्रिंग को इंटरसेप्ट करने में `lj_str_new` और बाद के GC ऑपरेशन शामिल होते हैं।

```
resty -e 'print(string.sub("abcd", 1, 1))'
```

उपरोक्त कोड का कार्य `string` के पहले कैरेक्टर को प्राप्त करना और उसे प्रिंट करना है। स्वाभाविक रूप से, यह एक अस्थायी `string` उत्पन्न करेगा। क्या इसी प्रभाव को प्राप्त करने का एक बेहतर तरीका है?

```
resty -e 'print(string.char(string.byte("abcd")))'
```

स्वाभाविक रूप से हाँ। इस कोड को देखते हुए, हम पहले `string.byte` का उपयोग करके पहले कैरेक्टर का न्यूमेरिक कोड प्राप्त करते हैं और फिर `string.char` का उपयोग करके नंबर को संबंधित कैरेक्टर में बदलते हैं। इस प्रक्रिया में कोई अस्थायी `string` उत्पन्न नहीं होता है। इसलिए, `string`-संबंधित स्कैनिंग और विश्लेषण करने के लिए `string.byte` का उपयोग करना सबसे कुशल है।

## `table` प्रकार के लिए SDK समर्थन का लाभ उठाएं

अस्थायी `string` को कम करने का तरीका सीखने के बाद, क्या आप इसे आज़माने के लिए उत्सुक हैं? तो, हम ऊपर दिए गए सैंपल कोड के परिणाम को क्लाइंट को रिस्पॉन्स बॉडी के कंटेंट के रूप में आउटपुट कर सकते हैं। इस बिंदु पर, आप रुक सकते हैं और पहले इस कोड को स्वयं लिखने का प्रयास कर सकते हैं।

```
$ resty -e 'local begin = ngx.now()
local t = {}
local index = 1
for i = 1, 100000 do
    t[index] = "a"
    index = index + 1
end
local response = table.concat(t, "")
ngx.say(response)
'
```

यदि आप यह कोड लिख सकते हैं, तो आप अधिकांश OpenResty डेवलपर्स से आगे हैं। OpenResty के Lua API ने पहले ही `string` स्प्लिसिंग के लिए `table` के उपयोग को ध्यान में रखा है, इसलिए `ngx.say`, `ngx.print`, `ngx.log`, `cosocket:send`, और अन्य API जो बहुत सारे `string` ले सकते हैं, में यह न केवल `string` को पैरामीटर के रूप में स्वीकार करता है, बल्कि `table` को भी पैरामीटर के रूप में स्वीकार करता है।

```
resty -e 'local begin = ngx.now()
local t = {}
local index = 1
for i = 1, 100000 do
    t[index] = "a"
    index = index + 1
end
ngx.say(t)
'
```

इस अंतिम कोड स्निपेट में, हमने `local response = table.concat(t, "")`, `string` स्प्लिसिंग स्टेप को छोड़ दिया है और `table` को सीधे `ngx.say` में पास कर दिया है। यह `string` स्प्लिसिंग टास्क को Lua स्तर से C स्तर पर शिफ्ट करता है, एक और `string` लुकअप, जनरेशन और GC से बचाता है। लंबे `string` के लिए, यह एक और महत्वपूर्ण प्रदर्शन लाभ है।

## सारांश

इस लेख को पढ़ने के बाद, हम देख सकते हैं कि OpenResty का बहुत सारा परफॉर्मेंस ऑप्टिमाइज़ेशन विभिन्न विवरणों से संबंधित है। इसलिए, हमें LuaJIT और OpenResty के Lua API को अच्छी तरह से जानने की आवश्यकता है ताकि इष्टतम प्रदर्शन प्राप्त किया जा सके। यह हमें यह भी याद दिलाता है कि यदि हम पिछले कंटेंट को भूल गए हैं, तो हमें समय पर उसकी समीक्षा और समेकन करना चाहिए।

अंत में, एक समस्या के बारे में सोचें: स्ट्रिंग्स `hello`, `world`, और `!` को एरर लॉग में लिखें। क्या हम `string` स्प्लिसिंग के बिना एक सैंपल कोड लिख सकते हैं?

साथ ही, लेख में दिए गए अन्य प्रश्न को न भूलें। यदि नया `string` 10x `a` की लंबाई में होता है, तो निम्नलिखित कोड में प्रदर्शन अंतर क्या होगा?

```
$ resty -e 'local begin = ngx.now()
local t = {}
for i = 1, 100000 do
    t[#t + 1] = "a"
end
local s =  table.concat(t, "")
ngx.update_time()
print(ngx.now() - begin)
'
```

आप इस लेख को अपने दोस्तों के साथ सीखने और संवाद करने के लिए भी साझा कर सकते हैं।

Share article link

Share

Related Posts

[![नॉन-ब्लॉकिंग I/O - OpenResty प्रदर्शन को बेहतर बनाने की कुंजी](https://static.api7.ai/2022/12/05/638dce5075e0f.png)](https://api7.ai/learning-center/openresty/blocking-io)

## [नॉन-ब्लॉकिंग I/O - OpenResty प्रदर्शन को बेहतर बनाने की कुंजी](https://api7.ai/learning-center/openresty/blocking-io)

[![OpenResty FAQ | OpenResty का व्यवहारिक उपयोग कैसे किया जाता है](https://static.api7.ai/uploads/2023/02/12/jbv9M0zi_Hello%20World%20in%20OpenResty%20%283%29.png)](https://api7.ai/learning-center/openresty/faq-5)

## [OpenResty FAQ | OpenResty का व्यवहारिक उपयोग कैसे किया जाता है](https://api7.ai/learning-center/openresty/faq-5)

Table of Contents

- [परफॉर्मेंस ऑप्टिमाइज़ेशन टिप्स के पीछे](#%E0%A4%AA%E0%A4%B0%E0%A4%AB%E0%A5%89%E0%A4%B0%E0%A5%8D%E0%A4%AE%E0%A5%87%E0%A4%82%E0%A4%B8-%E0%A4%91%E0%A4%AA%E0%A5%8D%E0%A4%9F%E0%A4%BF%E0%A4%AE%E0%A4%BE%E0%A4%87%E0%A4%9C%E0%A4%BC%E0%A5%87%E0%A4%B6%E0%A4%A8-%E0%A4%9F%E0%A4%BF%E0%A4%AA%E0%A5%8D%E0%A4%B8-%E0%A4%95%E0%A5%87-%E0%A4%AA%E0%A5%80%E0%A4%9B%E0%A5%87)

  - [थ्योरी 1: अनुरोधों को संक्षिप्त, सरल और तेज़ी से संसाधित करें](#%E0%A4%A5%E0%A5%8D%E0%A4%AF%E0%A5%8B%E0%A4%B0%E0%A5%80-1-%E0%A4%85%E0%A4%A8%E0%A5%81%E0%A4%B0%E0%A5%8B%E0%A4%A7%E0%A5%8B%E0%A4%82-%E0%A4%95%E0%A5%8B-%E0%A4%B8%E0%A4%82%E0%A4%95%E0%A5%8D%E0%A4%B7%E0%A4%BF%E0%A4%AA%E0%A5%8D%E0%A4%A4-%E0%A4%B8%E0%A4%B0%E0%A4%B2-%E0%A4%94%E0%A4%B0-%E0%A4%A4%E0%A5%87%E0%A4%9C%E0%A4%BC%E0%A5%80-%E0%A4%B8%E0%A5%87-%E0%A4%B8%E0%A4%82%E0%A4%B8%E0%A4%BE%E0%A4%A7%E0%A4%BF%E0%A4%A4-%E0%A4%95%E0%A4%B0%E0%A5%87%E0%A4%82)
  - [थ्योरी 2: मध्यवर्ती डेटा उत्पन्न करने से बचें](#%E0%A4%A5%E0%A5%8D%E0%A4%AF%E0%A5%8B%E0%A4%B0%E0%A5%80-2-%E0%A4%AE%E0%A4%A7%E0%A5%8D%E0%A4%AF%E0%A4%B5%E0%A4%B0%E0%A5%8D%E0%A4%A4%E0%A5%80-%E0%A4%A1%E0%A5%87%E0%A4%9F%E0%A4%BE-%E0%A4%89%E0%A4%A4%E0%A5%8D%E0%A4%AA%E0%A4%A8%E0%A5%8D%E0%A4%A8-%E0%A4%95%E0%A4%B0%E0%A4%A8%E0%A5%87-%E0%A4%B8%E0%A5%87-%E0%A4%AC%E0%A4%9A%E0%A5%87%E0%A4%82)

- [`string` अपरिवर्तनीय हैं](#string-%E0%A4%85%E0%A4%AA%E0%A4%B0%E0%A4%BF%E0%A4%B5%E0%A4%B0%E0%A5%8D%E0%A4%A4%E0%A4%A8%E0%A5%80%E0%A4%AF-%E0%A4%B9%E0%A5%88%E0%A4%82)

- [अन्य अस्थायी `string` को कम करें](#%E0%A4%85%E0%A4%A8%E0%A5%8D%E0%A4%AF-%E0%A4%85%E0%A4%B8%E0%A5%8D%E0%A4%A5%E0%A4%BE%E0%A4%AF%E0%A5%80-string-%E0%A4%95%E0%A5%8B-%E0%A4%95%E0%A4%AE-%E0%A4%95%E0%A4%B0%E0%A5%87%E0%A4%82)

- [`table` प्रकार के लिए SDK समर्थन का लाभ उठाएं](#table-%E0%A4%AA%E0%A5%8D%E0%A4%B0%E0%A4%95%E0%A4%BE%E0%A4%B0-%E0%A4%95%E0%A5%87-%E0%A4%B2%E0%A4%BF%E0%A4%8F-sdk-%E0%A4%B8%E0%A4%AE%E0%A4%B0%E0%A5%8D%E0%A4%A5%E0%A4%A8-%E0%A4%95%E0%A4%BE-%E0%A4%B2%E0%A4%BE%E0%A4%AD-%E0%A4%89%E0%A4%A0%E0%A4%BE%E0%A4%8F%E0%A4%82)

- [सारांश](#%E0%A4%B8%E0%A4%BE%E0%A4%B0%E0%A4%BE%E0%A4%82%E0%A4%B6)
