मैं .NET 3.5 (सी #) का उपयोग कर रहा हूं और मैंने सुना है कि सी # List<T>.ToArray
का प्रदर्शन "खराब" है, क्योंकि यह स्मृति सभी तत्वों के लिए एक नई सरणी बनाने के लिए प्रतिलिपि बनाता है। क्या यह सच है?सी # सूची <T>.ToArray प्रदर्शन खराब है?
उत्तर
नहीं है कि सच नहीं है लिया। प्रदर्शन अच्छा है क्योंकि यह सब कुछ करता है स्मृति सभी तत्वों (*) को एक नई सरणी बनाने के लिए प्रतिलिपि बनाता है।
बेशक यह "अच्छा" या "खराब" प्रदर्शन के रूप में परिभाषित करने पर निर्भर करता है।
(*) संदर्भ प्रकारों के लिए संदर्भ, मूल्य प्रकारों के लिए मान।
संपादित
अपनी टिप्पणी के जवाब में, परावर्तक का उपयोग कर कार्यान्वयन की जांच करने (देखें नीचे) एक अच्छा तरीका है। या बस कुछ मिनट के लिए सोचें कि आप इसे कैसे कार्यान्वित करेंगे, और इसे विश्वास पर लें कि माइक्रोसॉफ्ट के इंजीनियरों को एक खराब समाधान के साथ नहीं आना होगा।
public T[] ToArray()
{
T[] destinationArray = new T[this._size];
Array.Copy(this._items, 0, destinationArray, 0, this._size);
return destinationArray;
}
बेशक, "अच्छा" या "खराब" प्रदर्शन केवल कुछ विकल्प के सापेक्ष एक अर्थ है। यदि आपके विशिष्ट मामले में, आपके लक्ष्य को प्राप्त करने के लिए एक वैकल्पिक तकनीक है जो मापने योग्य तेज़ है, तो आप प्रदर्शन को "खराब" मान सकते हैं। यदि ऐसा कोई विकल्प नहीं है, तो प्रदर्शन "अच्छा" (या "पर्याप्त पर्याप्त") है।
संपादित 2
टिप्पणी के जवाब में: "वस्तुओं की कोई फिर से निर्माण?":।।।
संदर्भ प्रकार के लिए कोई पुनर्निर्माण मूल्य प्रकारों के लिए मूल्यों को कॉपी कर रहे हैं, शिथिल के रूप में पुनर्निर्माण
धन्यवाद जो, आपका जवाब बहुत अच्छा है!क्या आपके पास आगे चर्चा करने या दावे के आगे साबित करने के लिए कोई संबंधित दस्तावेज हैं - "यह सब एक नई सरणी बनाने के लिए सभी तत्वों (*) की स्मृति प्रतिलिपि बनाता है।" – George2
धन्यवाद जो, ऐरे। कॉपी केवल प्रतिलिपि संदर्भ? वस्तुओं का पुन: निर्माण नहीं? – George2
जॉर्ज। इसे देखो! या परावर्तक का उपयोग करें और पता लगाएं। ToArray के लिए यह इतना जटिल नहीं था, है ना? –
यह एक सरणी में नए संदर्भ बनाता है, लेकिन है कि बस केवल बात यह है कि उस विधि और क्या करना चाहिए सकता है ...
आपका मतलब है कि संदर्भ की प्रतिलिपि बनाई गई है? – George2
कारण toArray()
- कॉल करने के लिए, तो दिए गए मान नहीं है संशोधित करने के लिए, इसे एक सरणी के रूप में लौटने से यह तथ्य थोड़ा स्पष्ट हो जाता है।
- यदि कॉलर से डेटा पर कई अनुक्रमिक पहुंच करने की अपेक्षा की जाती है, तो सूची <> पर एक सरणी के लिए प्रदर्शन लाभ हो सकता है।
- यदि आपको पता है कि आपको लौटाए गए मान को किसी तृतीय-पक्ष फ़ंक्शन पर पास करना होगा जो किसी सरणी की अपेक्षा करता है।
- कॉलिंग फ़ंक्शंस के साथ संगतता जिसे .NET संस्करण 1 या 1.1 के साथ काम करने की आवश्यकता है। इन संस्करणों में सूची <> प्रकार (या किसी भी सामान्य प्रकार, उस मामले के लिए) नहीं है।
कारण toArray कॉल करने के लिए नहीं()
- फोन करने वाले कभी जोड़ सकते हैं या तत्वों को हटाने की जरूरत होती है, तो एक सूची <> बिल्कुल आवश्यक है।
- प्रदर्शन लाभों की आवश्यकता नहीं है, खासकर अगर कॉलर अनुक्रमिक फैशन में डेटा तक पहुंच रहा है। सूची <> से सरणी में कनवर्ट करने का अतिरिक्त चरण भी है, जो प्रोसेसिंग समय लेता है।
- कॉलर हमेशा सूची को एक सरणी में परिवर्तित कर सकता है।
से here
अच्छा रिफर्न, लेकिन मेरे प्रश्न का सीधा जवाब नहीं है? मेरे प्रश्न का आपका उत्तर क्या है? – George2
यह एकमात्र उत्तर है जिसे हम दे सकते हैं: सुधार हमेशा प्रदर्शन को कम करता है। आप सबसे अधिक सक्षम चीज नहीं कर सकते जो आप अभी भी सही कर सकते हैं। इसका आवेदन यह है कि आप कॉल नहीं करते हैं। ToArray() जब तक आपको वैसे भी नहीं करना है। –
"... सूची में किसी सरणी के लिए प्रदर्शन लाभ हो सकता है <>।" - इसके लिए कोई सबूत? मेरे लिए एक मिथक की तरह लगता है। – Joe
प्रदर्शन सापेक्ष दृष्टि से समझना है वर्णित किया जा सकता है जो एक सूची के लिए एक सरणी परिवर्तित को कॉपी शामिल सरणी, और इसकी लागत सरणी के आकार पर निर्भर करेगी। लेकिन आपको उस लागत की तुलना अन्य कार्यक्रमों की तुलना में करना है जो आपके प्रोग्राम कर रहे हैं। आपने पहली जगह में सरणी डालने के लिए जानकारी कैसे प्राप्त की? अगर यह डिस्क, या नेटवर्क कनेक्शन, या डेटाबेस से पढ़कर था, तो स्मृति में एक सरणी प्रतिलिपि समय के लिए एक पता लगाने योग्य अंतर बनाने की संभावना नहीं है।
"पहली जगह में सरणी में डाल दिया" का अर्थ है? – George2
सरणी की प्रतिलिपि बनाने से पहले, आपको सरणी में स्टोर करने के लिए कुछ जानकारी प्राप्त करनी होगी, अन्यथा इसकी प्रतिलिपि बनाने का कोई कारण नहीं होगा। –
हां , यह सच है कि यह सभी तत्वों की स्मृति प्रतिलिपि करता है। क्या यह एक प्रदर्शन समस्या है? यह आपकी प्रदर्शन आवश्यकताओं पर निर्भर करता है।
ए List
सभी तत्वों को पकड़ने के लिए आंतरिक रूप से एक सरणी है। अगर सूची सूची के लिए अब पर्याप्त नहीं है तो सरणी बढ़ जाती है। किसी भी समय ऐसा होता है, सूची सभी तत्वों को एक नई सरणी में कॉपी करेगी। यह हर समय होता है, और ज्यादातर लोगों के लिए जो कोई प्रदर्शन समस्या नहीं है।
उदा। एक डिफ़ॉल्ट कन्स्ट्रक्टर के साथ एक सूची क्षमता 16 पर शुरू होती है, और जब आप 1712 तत्व .Add()
करते हैं, तो यह आकार 32 की एक नई सरणी बनाता है, 16 पुराने मानों की प्रतिलिपि बनाता है और 17 वें जोड़ता है।
आकार अंतर भी ToArray()
निजी संदर्भ पारित करने के बजाय एक नया सरणी उदाहरण देता है।
धन्यवाद chris166, मैं सिर्फ पुष्टि करना चाहता हूं कि केवल संदर्भ को ToArray के दौरान कॉपी किया गया है। ToArray के दौरान वस्तुओं का पुन: निर्माण नहीं? – George2
हां, केवल संदर्भों की प्रतिलिपि बनाई गई है। सूची नहीं जानता कि आपकी वस्तुओं की गहरी प्रति कैसे बनाएं। अपवाद मूल्य प्रकार (structs, ints, युगल, enums आदि) हैं। – chris166
किसी भी प्रकार की सूची/आईसीलेक्शन के लिए जहां यह लंबाई जानता है, यह शुरुआत से बिल्कुल सही आकार की सरणी आवंटित कर सकता है।
T[] destinationArray = new T[this._size];
Array.Copy(this._items, 0, destinationArray, 0, this._size);
return destinationArray;
यदि आपका स्रोत प्रकार IEnumerable है (न कि किसी सूची/संग्रह) तो स्रोत है:
items = new TElement[4];
..
if (no more space) {
TElement[] newItems = new TElement[checked(count * 2)];
Array.Copy(items, 0, newItems, 0, count);
items = newItems;
यह आकार 4 में शुरू होता है और तेजी से बढ़ता है, हर बार यह स्थान से बाहर चलाता है दोहरीकरण। प्रत्येक बार जब यह दोगुना हो जाता है, तो उसे स्मृति को पुन: आवंटित करना होगा और डेटा को कॉपी करना होगा।
यदि हम स्रोत-डेटा आकार जानते हैं, तो हम इस मामूली ओवरहेड से बच सकते हैं। हालांकि ज्यादातर मामलों में सरणी आकार < = 1024, यह इतनी जल्दी निष्पादित होगा कि हमें इस कार्यान्वयन के विवरण के बारे में भी सोचने की आवश्यकता नहीं है।
संदर्भ: Enumerable.cs, List.cs (उन्हें में F12ing), जो जवाब
- 1. लिंक टोलिस्ट/ToArray/ToDictionary प्रदर्शन
- 2. सी # सूची <> जोड़ें() विधि प्रदर्शन
- 3. प्रदर्शन के लिए आलसी <T> खराब है?
- 4. PostgreSQL सबक्वेरी खराब प्रदर्शन
- 5. ए * पथदर्शी खराब प्रदर्शन
- 6. खराब boost.ASIO प्रदर्शन
- 7. एंटिटी फ्रेमवर्क विलय प्रदर्शन खराब प्रदर्शन
- 8. सी # सूची <string[]> सूची <object[]> रूपांतरण
- 9. सी # सूची <T> बनाम IEnumerable <T> प्रदर्शन सवाल
- 10. सूची <int> सी #
- 11. सी # सूची <T>
- 12. सूची <long> सी #
- 13. सी # सूची <T>
- 14. लॉक बनाम ToArray थ्रेड सुरक्षित फोरच सूची संग्रह संग्रह
- 15. सूची <T> सूची के लिए अंतिम() एक्सटेंशन विधि का प्रदर्शन क्या है?
- 16. सी # जेनिक्स: सूची <Object> या नई कक्षा सूची
- 17. SqlDataReader प्रदर्शन सूची <string[]> या सूची <object[]>
- 18. संग्रह .toArray() java.lang.ClassCastException
- 19. एज़ूर कैश के साथ खराब प्रदर्शन
- 20. एंड्रॉइड जिंजरब्रेड में ओपनजीएल खराब प्रदर्शन
- 21. बड़ी जावा सूचियों के साथ खराब प्रदर्शन
- 22. की खराब समय प्रदर्शन 'रेक संपत्ति: precompile'
- 23. जावा की अनजिप यूटिलिटीज का खराब प्रदर्शन
- 24. स्ट्रिंग का उपयोग करते समय ToArray() का उपयोग क्यों किया जाता है। सूची <string> के साथ जुड़ें?
- 25. सूची <int> सी # 3.5
- 26. स्ट्रिंग [] बनाम सूची <string> सी #
- 27. सी # सूची <> ऑर्डर/समूह द्वारा
- 28. सी # सूची <T>। .NET 2.0
- 29. सी # सूची <T> परीक्षण
- 30. सी # सूची <string> delimiter
आप को देखने के लिए [चाहते हो सकता है है यह बेहतर करने के लिए कॉल-tolist या toArray-इन-linq- प्रश्न] (http://stackoverflow.com/questions/1105990/is-it-better-to-call-tolist-or-toarray-in-linq-queries) – nawfal