मेरे सी # अनुप्रयोग प्रोफाइलिंग से संकेत मिलता है कि List<T>.AddRange
में महत्वपूर्ण समय बिताया गया है। परावर्तक का उपयोग कोड को देखने के लिए इस विधि का संकेत दिया है कि यह List<T>.InsertRange
जो इस तरह के रूप में कार्यान्वित किया जाता है कहता है:सूची <T> .ddRange कार्यान्वयन suboptimal
public void InsertRange(int index, IEnumerable<T> collection)
{
if (collection == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
}
if (index > this._size)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
}
ICollection<T> is2 = collection as ICollection<T>;
if (is2 != null)
{
int count = is2.Count;
if (count > 0)
{
this.EnsureCapacity(this._size + count);
if (index < this._size)
{
Array.Copy(this._items, index, this._items, index + count, this._size - index);
}
if (this == is2)
{
Array.Copy(this._items, 0, this._items, index, index);
Array.Copy(this._items, (int) (index + count), this._items, (int) (index * 2), (int) (this._size - index));
}
else
{
T[] array = new T[count]; // (*)
is2.CopyTo(array, 0); // (*)
array.CopyTo(this._items, index); // (*)
}
this._size += count;
}
}
else
{
using (IEnumerator<T> enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
this.Insert(index++, enumerator.Current);
}
}
}
this._version++;
}
private T[] _items;
यह तर्क कर सकते हैं कि इंटरफेस (केवल InsertRange में से एक अधिभार वाले) की सादगी के प्रदर्शन भूमि के ऊपर सही ठहराते रनटाइम प्रकार cheching और कास्टिंग। लेकिन (*)
के साथ मैंने 3 लाइनों के पीछे क्या कारण हो सकता है? मुझे लगता है कि यह तेजी से विकल्प को फिर से लिखा जा सकता है:
is2.CopyTo(this._items, index);
आप इस सरल और जाहिरा तौर पर तेजी से विकल्प का उपयोग नहीं करने के लिए किसी भी कारण से देखते हैं?
संपादित करें:
जवाब के लिए धन्यवाद। तो आम सहमति यह है कि यह एक दोषपूर्ण/दुर्भावनापूर्ण तरीके से CopyTo को लागू करने वाले इनपुट संग्रह के खिलाफ एक सुरक्षा उपाय है। मेरे लिए यह लगातार 1) रनटाइम प्रकार की जांच का भुगतान करने के लिए एक ओवरकिल की तरह लगता है 2) अस्थायी सरणी के गतिशील आवंटन 3) प्रतिलिपि ऑपरेशन को दोगुना करें, जब यह सब InsertRange के 2 या कुछ और ओवरलोड को परिभाषित करके सहेजा जा सकता था , अब IEnumerable
हो रहा है, दूसरा List<T>
प्राप्त कर रहा है, तीसरा T[]
प्राप्त हो रहा है। बाद के दो को वर्तमान मामले में जितनी तेजी से दोगुनी दौड़ने के लिए लागू किया जा सकता था।
संपादित करें 2:
मैं एक वर्ग फ़ास्टलिस्ट, समान सूची में लागू है, सिवाय यह भी AddRange की एक अधिभार जो एक टी [] तर्क लेता प्रावधान है कि किया था। इस अधिभार को गतिशील प्रकार सत्यापन, और तत्वों की दोहरी प्रतिलिपि की आवश्यकता नहीं है। मैंने इस फास्टलिस्ट को प्रोफाइल किया था। सूची के खिलाफ एड्रेंज करें। 4-बाइट सरणी को एक सूची में 1000 बार जोड़कर जोड़ें, जो प्रारंभ में अचंभित था। मेरा कार्यान्वयन मानक सूची की गति को धड़कता है। 9 (नौ!) के कारक के साथ जोड़ें। List.AddRange हमारे आवेदन के महत्वपूर्ण उपयोग परिदृश्यों में से एक में रनटाइम का लगभग 5% लेता है, एक श्रेणी के साथ सूची को एक तेज़ AddRange प्रदान करने से एप्लिकेशन रनटाइम 4% तक सुधार सकता है।
@shojtsy: सुनिश्चित करें कि आप मेरे संपादन को पकड़ लें 2 :) –
आपने अपने परीक्षण के लिए सबसे खराब स्थिति परिदृश्य का उपयोग किया था। 'InsertRange' के साथ 4-बाइट सरणी के बजाय 'सम्मिलित करें' के साथ एक 'int' डालने का प्रयास करें और आपको एक और टक्कर मिल जाएगी। –
परीक्षण परिदृश्य मेरे आवेदन में वास्तविक उपयोग का प्रतिनिधि है। सूची एक बाइट स्ट्रीम है जहां 4-10 बाइट एरे कई बार संलग्न की जा रही हैं। मैं समझता हूं कि AddRange के लिए एक साधारण ऐरे पास करना है जहां मानक कार्यान्वयन के प्रदर्शन दंड सबसे अधिक दिखाई दे रहे हैं। वह बिल्कुल मेरा मुद्दा था। – shojtsy