2012-11-01 12 views
19

यह इस उत्कृष्ट प्रश्न का पालन करता है C# Sort and OrderBy comparison। मैं एक ही उदाहरण का उपयोग करेगा:ऑर्डरबी जो IOrderedEnumerable <T> सॉर्ट करने से बहुत तेज़ है?

List<Person> persons = new List<Person>(); 
persons.Add(new Person("P005", "Janson")); 
persons.Add(new Person("P002", "Aravind")); 
persons.Add(new Person("P007", "Kazhal")); 

विवाद में तरीके हैं:

persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true)); 
//and 
persons.OrderBy(n => n.Name); 

मुझे यह कहते हुए मैं समझता हूँ कि वहाँ के बारे में चिंता करने के लिए किसी भी महत्वपूर्ण प्रदर्शन अंतर नहीं है द्वारा शुरू करते हैं। लेकिन मुझे यह जानना अच्छा लगेगा कि OrderBySort से इतना बेहतर प्रदर्शन क्यों करता है। मैं मूल प्रश्न में @phoog द्वारा पोस्ट किए गए उत्तर का उपयोग कर रहा हूं।

private void button1_Click(object sender, EventArgs e) 
{ 
    IEnumerable<Person> people; 

    BenchMark(persons => persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true))); 

    BenchMark(persons => people = persons.OrderBy(n => n.Name)); 
} 

private static Random randomSeed = new Random(); 
public static string RandomString(int size, bool lowerCase) 
{ 
    var sb = new StringBuilder(size); 
    int start = (lowerCase) ? 97 : 65; 
    for (int i = 0; i < size; i++) 
    { 
     sb.Append((char)(26 * randomSeed.NextDouble() + start)); 
    } 
    return sb.ToString(); 
} 

private static void BenchMark(Action<List<Person>> action) 
{ 
    List<Person> persons = new List<Person>(); 
    for (int i = 0; i < 10000; i++) 
    { 
     persons.Add(new Person("P" + i.ToString(), RandomString(5, true))); 
    } 
    List<Person> unsortedPersons = new List<Person>(persons); 

    Stopwatch watch = new Stopwatch(); 
    for (int i = 0; i < 100; i++) 
    { 
     watch.Start(); 

     action(persons); 

     watch.Stop(); 
     persons.Clear(); 
     persons.AddRange(unsortedPersons); 
    } 

    MessageBox.Show(watch.Elapsed.TotalMilliseconds.ToString()); 
} 

परिणाम:

Sort() => 3500 ~ 5000 ms 
OrderBy() => 0.2 ~ 1.5 ms 

हालांकि मतभेद भी छोटे सूचियों मैं शुरू में परीक्षण किया साथ गहरा थे, यह अधिक से अधिक स्पष्ट हो गया एक बार संग्रह के आकार को गया। हो सकता है मैं नेट संग्रह को समझने के लिए कुछ प्रमुख याद कर रहा हूँ, लेकिन मेरी सोच के बाद से एक मौजूदा List<T> पर Sort कार्य करता है, यह कम भूमि के ऊपर (यदि हर कोई हो) जब OrderBy जो एक ही List<T> पर काम करता है की तुलना में होना चाहिए प्रसंस्करण में (में है हमारे मामले persons) लेकिन एक और संग्रह IOrderedEnumerable<T> वापस करना है। लेकिन अभी भी OrderBy बहुत बेहतर प्रदर्शन करता है। List<T> में IEnumerable<T> प्रकार की तुलना में कुछ ओवरहेड हो सकता है, लेकिन Sort वैसे भी मौजूदा सूची पर कार्य करता है! इसके अलावा, मैं Linq मौजूदा .NET विधि से तेज़ी से काम करने वाली विधि देखने के लिए बहुत खुश हूं।

मूल प्रश्न में सभी उत्तरों OrderBy.ToList के विरुद्ध तुलना करते हैं जो मुझे विश्वास है कि कुछ ओवरहेड होगा और इसलिए उतना ही कम समान प्रदर्शन करेगा।

कार्यान्वयन अंतर क्या हो सकता है?


संपादित करें: ठीक है, मैं कुछ नया सीखा है। यहां बताया गया है कि मैंने स्थगित निष्पादन के बारे में कैसे पुष्टि की।

private void button1_Click(object sender, EventArgs e) 
{ 
    BenchMark(persons => 
    { 
     persons.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, true)); 
     foreach (var item in persons) 
     { 
      break; 
     } 
    }); 

    BenchMark(persons => 
    { 
     IEnumerable<Person> people = persons.OrderBy(n => n.Name); 
     foreach (var item in people) 
     { 
      break; 
     } 
    }); 
} 

Sort 4000 में भाग गया - 5000ms जबकि OrderBy बस ऊपर 5000ms भाग गया। तो वास्तव में मेरा निष्कर्ष गलत था। एक बार जब मैंने संग्रहों की गणना करना शुरू किया तो दोनों ने बराबर शर्तों पर प्रदर्शन किया। मैं सिर्फ पाया कि इस this one की सटीक डुप्लिकेट है: मैं OrderBy anyday :)

संपादित 2 की वाक्य रचना पसंद करते हैं। लेकिन यहाँ एक more interesting question about deferred execution in general नहीं है, हालांकि कुल मिलाकर आदेश देने के बारे में है।

+0

संभावित डुप्लिकेट [LINQ की तुलना में Array.Sort() इतनी धीमी क्यों है?] (Http://stackoverflow.com/questions/10299464/why-is-array-sort-so-slow-compared-to- linq) – nawfal

उत्तर

36

इस मामले में, OrderBy दूर तेजी से क्योंकि आप वास्तव में यह क्रियान्वित नहीं कर रहे है।

जब तक आप परिणामों की गणना नहीं करते हैं, क्वेरी स्थगित है, इसलिए यह वास्तव में ऑर्डरिंग नहीं कर रही है। जब तक आप वास्तव में परिणामों के माध्यम से गणना नहीं करते हैं, IOrderedEnumerable<T> इनपुट को संसाधित नहीं करता है और ऑर्डर करने का कोई भी रूप नहीं करता है। काफी

BenchMark(persons => people = persons.OrderBy(n => n.Name).Count()); 

Count() कॉल वास्तव में होने के लिये (क्योंकि यह IOrderedEnumerable<T> की गणना करने में गिनती उत्पन्न करने के लिए की जरूरत है) आदेश के लिए बाध्य करेगा, यहां तक ​​कि अपने समय बाहर करना चाहिए जो:

करने के लिए अपने बेंचमार्क बदलने का प्रयास करें।

अधिकांश LINQ विस्तार तरीकों इस तरह से काम करते हैं - जब तक आप उन्हें बताना (Count() के माध्यम से, ToList() आदि बुला, या बस उन्हें एक सामान्य foreach पाश में उपयोग करते हुए,), वे, कम प्रभाव पड़ेगा के रूप में वे वास्तव में कुछ भी नहीं करते गणना करने के अलावा सीधे। कारण अन्य मानक OrderBy(...).ToList() से तुलना कि ToList() के अलावा OrderBy बलों को पूरी तरह से अमल करने के लिए और वास्तव में परिणाम के आदेश है।

+0

रीड, वास्तव में ऑर्डर करने से आपका क्या मतलब है? मैं 'IOrderedEnumerable' लौटे गणना और सत्यापित करने के लिए वस्तुओं जब तक माइक्रोसॉफ्ट डरपोक नहीं किया गया और पता चला कि वे इसकी गिनती वापस जाने के लिए में संग्रह को सॉर्ट करने की जरूरत नहीं है है – nawfal

+5

आदेश दिया जाता है उस में वस्तुओं मुद्रित कर सकते हैं ... : पी – Rawling

+0

@nawfal हां, लेकिन जब तक कि आप वास्तव में उस संग्रह की गणना नहीं करते हैं, परिणाम वास्तव में अभी तक आदेश नहीं दिया गया है। गणना के अनुरोध के तुरंत बाद उन्हें आदेश दिया जाता है (और परिणाम वास्तव में लौटाए जाने से पहले)। – ean5533

12

OrderBy(), सबसे LINQ तरीकों की तरह, आस्थगित निष्पादन का उपयोग करता है।

यह वास्तव में कुछ भी जब तक आप अपने परिणामों की गणना नहीं करता है।

ठीक से इसके प्रदर्शन को मापने के लिए, आप .OrderBy(...).Count() कॉल कर सकते हैं।

+0

स्लाक्स, क्या आप दूसरी वाक्य समझा सकते हैं? । मैं बहुत स्पष्ट – nawfal

+0

बेंचमार्क (व्यक्तियों => लोग = persons.OrderBy (n => n.Name)) गणना नहीं कर रहा हूँ(); – StingyJack

+0

मेरा संपादन देखें जो उत्तर में आपने जो कहा है उसकी पुष्टि करता है। धन्यवाद। – nawfal

2

OrderBy() एक हल कर सूची का निर्माण नहीं करता।

यह एक IEnumerable उद्देश्य यह है कि, जब आप इसे करके बताना, एक क्रमबद्ध सूची उत्पन्न करता है बनाता है। वास्तविक सॉर्टिंग तब तक नहीं होती जब तक आप सूची की गणना नहीं करते।

संबंधित मुद्दे