2010-05-03 14 views
29

नेट में कुछ संग्रह प्रकारों में वैकल्पिक "प्रारंभिक क्षमता" कन्स्ट्रक्टर पैरामीटर है। उदाहरण के लिए:संग्रह प्रकारों की आरंभिक क्षमता, उदा। शब्दकोश, सूची

Dictionary<string, string> something = new Dictionary<string,string>(20); 

List<string> anything = new List<string>(50); 

मुझे यह नहीं लगता कि एमएसडीएन पर इन वस्तुओं के लिए डिफ़ॉल्ट प्रारंभिक क्षमता क्या है।

यदि मुझे पता है कि मैं केवल एक शब्दकोश में 12 या तो आइटम संग्रहीत कर रहा हूं, तो क्या शुरुआती क्षमता को 20 की तरह सेट करने का अर्थ नहीं है?

मेरा तर्क यह मानते हुए है कि क्षमता स्ट्रिंगबिल्डर के लिए बढ़ती है, जो प्रत्येक बार क्षमता हिट होने पर दोगुनी हो जाती है, और प्रत्येक पुनर्वितरण महंगा होता है, क्यों आप जो कुछ जानते हैं उस आकार को प्री-सेट क्यों नहीं करते हैं , बस कुछ अतिरिक्त कमरे के साथ मामले में? यदि प्रारंभिक क्षमता 100 है, और मुझे पता है कि मुझे केवल एक दर्जन की आवश्यकता होगी, ऐसा लगता है कि शेष स्मृति को कुछ भी नहीं आवंटित किया गया है।

उत्तर

60

यदि डिफ़ॉल्ट मान दस्तावेज नहीं हैं, तो कारण यह है कि इष्टतम प्रारंभिक क्षमता कार्यान्वयन विवरण है और फ्रेमवर्क संस्करणों के बीच परिवर्तन के अधीन है। यही है, आपको कोड नहीं लिखना चाहिए जो एक निश्चित डिफ़ॉल्ट मान मानता है। क्षमता के साथ

निर्माता भार के मामलों के लिए कर रहे हैं, जिसमें आप वर्ग क्या मदों की संख्या उम्मीद की जा करने के लिए कर रहे हैं की तुलना में बेहतर पता है। उदाहरण के लिए, यदि आप 50 मानों का संग्रह बनाते हैं और जानते हैं कि यह संख्या कभी भी बढ़ेगी, तो आप संग्रह को 50 की क्षमता से प्रारंभ कर सकते हैं, इसलिए डिफ़ॉल्ट क्षमता कम होने पर इसे आकार बदलना नहीं होगा।

उसने कहा, आप प्रतिबिंबक का उपयोग कर डिफ़ॉल्ट मान निर्धारित कर सकते हैं। उदाहरण के लिए, .NET में 4.0 (और शायद पिछले संस्करणों के रूप में अच्छी तरह से),

  • एक सूची < टी > 0. की क्षमता के साथ आरंभ नहीं हो जाता जब पहला आइटम जोड़ा जाता है, इसके बारे में एक क्षमता के लिए इसे पुनः शुरू किया गया है 4. इसके बाद, जब भी क्षमता तक पहुंच जाती है, तो क्षमता दोगुनी हो जाती है।

  • एक शब्दकोश < टी > 0 की क्षमता के साथ भी अंतर्निहित है। लेकिन यह क्षमता बढ़ाने के लिए एक पूरी तरह से अलग एल्गोरिदम का उपयोग करता है: यह हमेशा प्राइम संख्याओं की क्षमता को बढ़ाता है।

+6

प्राइम संख्या गणना हैश टकराव और इनपुट स्थानों के लिए जांच के साथ सौदा करने की संभावना है। आंतरिक तंत्र के आधार पर यदि वे केवल प्रत्येक हैश पर एक मान संग्रहीत करते हैं तो उन्हें माध्यमिक संग्रहण स्थानों की आवश्यकता होती है। यदि आप प्राइम का उपयोग नहीं करते हैं तो आप संभावित रूप से एक हैश ढूंढ सकते हैं जिसे आप सम्मिलित करने में असफल हो सकते हैं। – Matt

+5

शब्दकोश चेनिंग का उपयोग करता है। प्राइम नंबर टेबल आकार खराब हैश कार्यों के लिए क्षतिपूर्ति करता है। अच्छे हैश फ़ंक्शन यादृच्छिक वितरण उत्पन्न करते हैं; आधुनिक हैश तालिकाओं में दो टेबल आकारों की शक्ति का उपयोग किया जाता है (.NET हैश तालिका जावा हैश तालिका पर आधारित थी, जिसने प्राइम संख्या भी उपयोग की थी, क्योंकि यह खराब हैश कार्यों के दिनों में ऐसा करने का एक पुराना तरीका था)। चूंकि माइक्रोसॉफ्ट ने हैश संयोजन विधियों में निर्मित नहीं किया है, इसलिए कई घर-निर्मित हैश फ़ंक्शन खराब वितरण का उत्पादन करते हैं, इसलिए प्राइम नंबर पसंद क्षतिपूर्ति करता है, कभी-कभी - जब तक हैश फ़ंक्शन प्राइम संख्याओं के गुणक उत्पन्न करता है। –

8

स्रोत, दोनों List<T> और Dictionary<TKey, TValue> के लिए डिफ़ॉल्ट क्षमता जांची जा रही 0.

+4

.Net 4.5 में अतिरिक्त क्षमता वास्तव में है 3. हां, डिफ़ॉल्ट कन्स्ट्रक्टर 0 के क्षमता मान के साथ ओवरलोडेड कन्स्ट्रक्टर को कॉल करता है, लेकिन जब कन्स्ट्रक्टर प्रारंभिक विधि को कॉल करता है तो आकार 3 पर सेट होता है। शब्दकोश को कॉल से हैशहेल्पर तक सेट किया जाता है। गेटप्रिम (क्षमता) जो प्रदान की गई क्षमता से अधिक अगली प्रमुख संख्या देता है। इस प्रकार, .NET 4.5 में एक शब्दकोश के लिए प्रारंभिक क्षमता 3. सूचियों की 0 की डिफ़ॉल्ट क्षमता होती है, लेकिन सूची में पहली आइटम जोड़ने के बाद क्षमता 4 पर जाती है। –

6

आप आकार का पता है, तो यह बता है; अधिकांश "छोटे" मामलों में मामूली अनुकूलन, लेकिन बड़े संग्रह के लिए उपयोगी है। मैं मुख्य रूप से इस बारे में चिंता करता हूं अगर मैं डेटा की एक "सभ्य" राशि फेंक रहा हूं, क्योंकि यह कई सरणी आवंटित करने, प्रतिलिपि बनाने और एकत्र करने से बच सकता है।

अधिकांश संग्रह वास्तव में एक दोगुनी रणनीति का उपयोग करते हैं।

1

ConcurrentDictionary (वर्तमान में) और स्थापित करने के लिए एक प्रारंभिक आकार अपने प्रदर्शन में बाधा प्रतीत होता है वह यह है कि इसके निर्माता का उपयोग कर के साथ एक और मुद्दा।

उदाहरण के लिए, here's some example code and benchmarks मैंने कोशिश की।

मैं अपने मशीन पर कोड भाग गया और इसी तरह के परिणाम मिल गया।

वह है, जब प्रारंभिक आकार निर्दिष्ट होता है, तो ऑब्जेक्ट्स जोड़ने पर ConcurrentDictionary की गति को बढ़ाने के लिए कुछ भी नहीं होता है। तकनीकी रूप से, मुझे लगता है कि यह होना चाहिए क्योंकि इसे स्वयं आकार बदलने के लिए समय या संसाधन नहीं लेना पड़ता है।

हां, यह सामान्य शब्दकोश के रूप में तेज़ी से नहीं चल सकता है, लेकिन मैं अब भी एक प्रारंभिक आकार सेट के साथ एक कंसूरेंट डिक्शनरी की अपेक्षा करता हूं जो एक ConcurrentDictionary की तुलना में लगातार, तेज़ प्रदर्शन करता है जिसमें प्रारंभिक आकार सेट नहीं होता है, खासकर जब कोई पहले से ही उन वस्तुओं की संख्या को जानता है जो इसमें जोड़े जा रहे हैं।

तो कहानी का नैतिक प्रारंभिक आकार निर्धारित करना हमेशा प्रदर्शन सुधार की गारंटी नहीं देता है।