जब से हाई स्कूल में मेरा पहला प्रोग्रामिंग क्लास आया है, तब से सुन रहा हूँ कि स्ट्रिंग ऑपरेशंस धीमे हैं - यानी अधिक महंगा - पौराणिक "औसत ऑपरेशन" की तुलना में। उन्हें इतना धीमा क्यों बनाता है? (यह सवाल जानबूझकर व्यापक छोड़ दिया गया।)
जब से हाई स्कूल में मेरा पहला प्रोग्रामिंग क्लास आया है, तब से सुन रहा हूँ कि स्ट्रिंग ऑपरेशंस धीमे हैं - यानी अधिक महंगा - पौराणिक "औसत ऑपरेशन" की तुलना में। उन्हें इतना धीमा क्यों बनाता है? (यह सवाल जानबूझकर व्यापक छोड़ दिया गया।)
जवाबों:
"औसत संचालन" प्राथमिकताओं पर होता है। लेकिन उन भाषाओं में भी जहां स्ट्रिंग्स को आदिम के रूप में माना जाता है, वे अभी भी हुड के नीचे सरणियां हैं, और कुछ भी करने से पूरे स्ट्रिंग को ओ (एन) समय लगता है, जहां एन स्ट्रिंग की लंबाई है।
उदाहरण के लिए, दो संख्याओं को जोड़ने पर सामान्यतः 2-4 ASM निर्देश लगते हैं। समवर्ती ("जोड़ना") दो तारों को एक नई मेमोरी आवंटन की आवश्यकता होती है और पूरे स्ट्रिंग को शामिल करते हुए एक या दो स्ट्रिंग प्रतियां होती हैं।
भाषा के कुछ कारक इसे बदतर बना सकते हैं। सी में, उदाहरण के लिए, एक स्ट्रिंग केवल वर्णों के अशक्त-समाप्त सरणी के लिए एक संकेतक है। इसका मतलब है कि आप नहीं जानते कि यह कितना लंबा है, इसलिए तेज चाल के संचालन के साथ स्ट्रिंग-कॉपी करने वाले लूप को अनुकूलित करने का कोई तरीका नहीं है; आपको एक बार में एक वर्ण की प्रतिलिपि बनाने की आवश्यकता है ताकि आप अशक्त टर्मिनेटर के लिए प्रत्येक बाइट का परीक्षण कर सकें।
char*
, not a strbuf
, और आप वापस वर्ग 1 में आ गए हैं। केवल इतना ही आप हैं एक बुरा डिजाइन भाषा में पके हुए है जब कर सकते हैं।
buf
सूचक के वहाँ है। मेरा मतलब कभी नहीं था कि यह उपलब्ध नहीं है; बल्कि, यह आवश्यक है। कोई भी कोड जो आपके अनुकूलित-लेकिन-गैर-मानक स्ट्रिंग प्रकार के बारे में नहीं जानता है, जिसमें मानक लाइब्रेरी जैसी मूलभूत चीजें शामिल हैं , फिर भी धीमी, असुरक्षित पर वापस गिरना पड़ता है char*
। आप चाहें तो उस FUD को कॉल कर सकते हैं, लेकिन यह सच नहीं है।
यह एक पुराना धागा है और मुझे लगता है कि अन्य उत्तर महान हैं, लेकिन कुछ को नजरअंदाज करते हैं, इसलिए यहां मेरे (देर से) 2 सेंट हैं।
स्ट्रिंग्स के साथ समस्या यह है कि वे अधिकांश भाषाओं में द्वितीय श्रेणी के नागरिक हैं, और वास्तव में अधिकांश समय वास्तव में स्वयं भाषा विनिर्देश का हिस्सा नहीं होते हैं: वे एक पुस्तकालय-कार्यान्वित निर्माण होते हैं जिसके शीर्ष पर कुछ सामयिक वाक्यात्मक चीनी-कोटिंग होती है एक दर्द का उपयोग करने के लिए उन्हें कम करने के लिए।
इसका प्रत्यक्ष परिणाम यह है कि भाषा उनकी जटिलता के एक बहुत बड़े हिस्से को आपकी दृष्टि से दूर छुपाती है, और आप डरपोक साइड-इफेक्ट्स के लिए भुगतान करते हैं क्योंकि आप उन्हें एक निम्न-स्तरीय परमाणु इकाई की तरह मानने की आदत में विकसित होते हैं, जैसे अन्य आदिम प्रकार (जैसा कि शीर्ष-मतदान जवाब और अन्य लोगों द्वारा समझाया गया है)।
इस अंतर्निहित "जटिलता" के तत्वों में से एक यह है कि अधिकांश स्ट्रिंग कार्यान्वयन स्ट्रिंग का प्रतिनिधित्व करने के लिए कुछ सन्निहित स्मृति स्थान के साथ एक सरल डेटा-संरचना का उपयोग करने का सहारा लेंगे: आपका अच्छा ol 'सरणी।
यह अच्छी तरह से समझ में आता है, आपका मन करता है, जैसा कि आप चाहते हैं कि स्ट्रिंग की पहुंच पूरी तेजी से हो। लेकिन इसका मतलब यह है कि जब आप इस स्ट्रिंग में हेरफेर करना चाहते हैं तो संभावित भयानक लागतें। बीच में एक तत्व तक पहुंचना तेज़ हो सकता है यदि आप जानते हैं कि आप किस सूचकांक के बाद हैं, लेकिन एक शर्त के आधार पर एक तत्व की तलाश नहीं है।
यहां तक कि स्ट्रिंग के आकार को लौटाना महंगा हो सकता है, अगर आपकी भाषा स्ट्रिंग की लंबाई को कैश नहीं करती है और वर्णों को गिनने के लिए इसे चलाने की आवश्यकता है।
इसी तरह के कारणों के लिए, अपने स्ट्रिंग में तत्वों को जोड़ना महंगा साबित होगा क्योंकि आपको इस ऑपरेशन के लिए कुछ मेमोरी को फिर से आवंटित करने की आवश्यकता होगी।
इसलिए, विभिन्न भाषाएँ इन मुद्दों पर अलग-अलग दृष्टिकोण अपनाती हैं। उदाहरण के लिए, जावा ने अपने तार को कुछ वैध कारणों (कैचिंग लेंथ, थ्रेड-सेफ्टी) के लिए अपरिवर्तनीय बनाने की स्वतंत्रता ले ली और अपने परस्पर समकक्षों (स्ट्रिंगबफर्बर और स्ट्रिंगब्यूलर) के लिए बड़े आकार के आकार का उपयोग करके आवंटित करने का चयन करेंगे, जिन्हें आवंटित करने की आवश्यकता नहीं है। हर बार, बल्कि सर्वश्रेष्ठ मामले परिदृश्यों के लिए आशा करते हैं। यह आम तौर पर अच्छी तरह से काम करता है, लेकिन डाउन-साइड मेमोरी प्रभावों के लिए कभी-कभी भुगतान करना है।
इसके अलावा, और फिर से यह इस तथ्य के कारण है कि आपकी भाषा की चीनी की चीनी कोटिंग आपको अच्छा खेलने के लिए आपसे छुपाती है, आप अक्सर इसे यूनिकोड समर्थन की शर्तों के बारे में नहीं सोचते हैं (विशेष रूप से लंबे समय तक जब तक आपको वास्तव में इसकी आवश्यकता नहीं होती है और उस दीवार को मारा)। और कुछ भाषाएं, आगे की सोच होने के कारण, सरल 8-बिट चार प्राइमिटिव के अंतर्निहित सरणियों के साथ तार को लागू नहीं करते हैं। वे यूटीएफ -8 या यूटीएफ -16 या आपके लिए क्या-क्या समर्थन करते हैं, में बेक किया गया है, और परिणाम एक बहुत बड़ी मेमोरी खपत है, जिसकी अक्सर आवश्यकता नहीं होती है, और मेमोरी को आवंटित करने के लिए एक बड़ा प्रसंस्करण समय, स्ट्रिंग्स को संसाधित करता है, और कोड अंक में हेरफेर करने वाले सभी तर्क को हाथ से लागू करें।
इन सबका परिणाम यह है कि जब आप छद्म कोड के समकक्ष कुछ करते हैं:
hello = "hello,"
world = " world!"
str = hello + world
यह नहीं हो सकता है - भाषा के विकासकर्ताओं ने उन सभी बेहतरीन प्रयासों के बावजूद, जैसा कि आप को छोड़कर उन्हें व्यवहार में रखा है - एक सरल रूप में:
a = 1;
b = 2;
shouldBeThree = a + b
अनुवर्ती के रूप में, आप पढ़ना चाह सकते हैं:
वाक्यांश "औसत संचालन" संभवतः एक सैद्धांतिक रैंडम-एक्सेस स्टोर-प्रोग्राम मशीन के एकल संचालन के लिए शॉर्टहैंड है । यह सैद्धांतिक मशीन है जो विभिन्न एल्गोरिदम के चलने के समय का विश्लेषण करने के लिए उपयोग करने के लिए प्रथागत है।
सामान्य संचालन को लोड, जोड़, घटाना, स्टोर, शाखा के रूप में लिया जाता है। शायद यह भी पढ़ें, प्रिंट करें और रोकें।
लेकिन अधिकांश स्ट्रिंग ऑपरेशनों में इन मूलभूत कार्यों में से कई की आवश्यकता होती है। उदाहरण के लिए, आमतौर पर एक स्ट्रिंग को डुप्लिकेट करने के लिए एक कॉपी ऑपरेशन की आवश्यकता होती है, और इसलिए कई ऑपरेशन जो एक स्ट्रिंग की लंबाई के लिए आनुपातिक है (यानी, यह "रैखिक" है)। एक दूसरे स्ट्रिंग के अंदर एक विकल्प खोजने से रैखिक जटिलता भी होती है।
यह पूरी तरह से ऑपरेशन पर निर्भर करता है, कैसे तार का प्रतिनिधित्व किया जाता है, और क्या अनुकूलन मौजूद हैं। यदि तार 4 या 8 बाइट लंबाई (और संरेखित) हैं, तो वे आवश्यक रूप से धीमे नहीं होंगे - कई ऑपरेशन आदिम के समान तेज़ होंगे। या, यदि सभी तारों में 32-बिट या 64-बिट हैश है, तो कई ऑपरेशन भी उतनी ही तेजी से होंगे (हालांकि आप हैशिंग लागत का भुगतान करते हैं)।
यह इस बात पर भी निर्भर करता है कि आप "धीमा" से क्या मतलब है। अधिकांश कार्यक्रमों की जरूरत है जो बहुत तेजी से तार प्रक्रिया होगी। स्ट्रिंग तुलना तुलनात्मक रूप से दो ints की तुलना में तेज़ नहीं हो सकती है, लेकिन केवल प्रोफाइलिंग से पता चलेगा कि आपके प्रोग्राम के लिए "धीमी" का क्या अर्थ है।
मुझे एक सवाल के साथ अपने सवाल का जवाब दें। एक शब्द कहने की तुलना में शब्दों की एक स्ट्रिंग को अधिक समय क्यों लगता है?