2014-04-04 6 views
8

क्या कोई इन परिणामों को समझा सकता है? मुझे पता है कि डुप्लिकेट सवाल कर रहे हैं, लेकिन मैं अभी तक एक भी सवाल है कि मेरे परिणाम के रूप में ही निष्कर्ष पर पहुंचा खोजने के लिए: ओप्रदर्शन परीक्षण परिणामों के लिए LINQ बनाम foreach बनाम

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace SpeedTest 
{ 
    class Person 
    {  
     public Person(string name) 
     { 
      this.Name = name; 
     } 

     public string Name { get; set; } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var people = new List<Person>(); 
      AddTwins("FRANCISCO", people); 
      var stopwatch = new Stopwatch(); 

      string name = "OCSICNARF"; 

      long linqTime = 0L; 
      long foreachTime = 0L; 
      long forTime = 0L; 

      stopwatch.Start(); 
      Person person0; 
      var result = from person in people 
         where person.Name == name 
         select person; 
      person0 = result.First(); 
      linqTime = stopwatch.ElapsedMilliseconds; 
      stopwatch.Restart(); 
      Person person1; 
      foreach (Person p in people) 
      { 
       if (p.Name == name) 
       { 
        person1 = p; 
        break; 
       } 
      } 
      foreachTime = stopwatch.ElapsedMilliseconds; 
      stopwatch.Restart(); 
      Person person2; 
      for (int i = 0; i < people.Count; i++) 
      { 
       if (people[i].Name == name) 
       { 
        person2 = people[i]; 
        break; 
       } 
      } 
      forTime = stopwatch.ElapsedMilliseconds; 
      stopwatch.Stop(); 

      Console.WriteLine(string.Format("LINQ took {0}ms", linqTime)); 
      Console.WriteLine(string.Format("FOREACH took {0}ms", foreachTime)); 
      Console.WriteLine(string.Format("FOR took {0}ms", forTime)); 
     } 

     static void AddTwins(string name, List<Person> people) 
     { 
      AddTwins(people, name, ""); 
     } 

     private static void AddTwins(List<Person> people, string choices, string chosen) 
     { 
      if (choices.Length == 0) 
      { 
       people.Add(new Person(chosen)); 
      } 
      else 
      { 
       for (int i = 0; i < choices.Length; i++) 
       { 
        // choose 
        char c = choices[i]; 
        string choose1 = choices.Substring(0, i); 
        string choose2 = choices.Substring(i + 1); 
        choices = choose1 + choose2; 

        // explore 
        AddTwins(people, choices, chosen + c); 

        // Unchoose 
        string unchoose1 = choices.Substring(0, i); 
        string unchoose2 = choices.Substring(i); 
        choices = unchoose1 + c + unchoose2; 
       } 
      } 
     } 
    } 
} 

enter image description here

+0

कृपया देखें http://ericlippert.com/2013/05/14/benchmarking-mistakes-part-one/ –

उत्तर

16

आप LINQ क्वेरी निष्पादित कभी नहीं, तुम बस बनाने यह। या ToArray विधि को पुनरावृत्ति के लिए उपयोग करने के लिए उपयोग करना चाहिए, शायद आपको एक अलग परिणाम नहीं मिलेगा क्योंकि LINQforeach लूप का भी उपयोग करता है।

संपादित करें: LINQ कुछ और समय लेता है क्योंकि आप सभी वस्तुओं पर पुनरावृत्त कर रहे हैं। लेकिन जैसे ही आप एक मैच पाते हैं, आप अपने दो दो लूपों में लूप तोड़ रहे हैं। Where के बजाय FirstOrDefault का उपयोग करने का प्रयास करें और आपको वही (या समान) परिणाम मिलना चाहिए।

people.FirstOrDefault(p => p.Name == name); 
+0

मेरा बुरा मुझे अभी एहसास हुआ कि, नए परिणाम/कोड देखें। –

1

LINQ एक ही समय ले जा रहा है, क्योंकि क्वेरी का मूल्यांकन कभी नहीं है वास्तव में।

Linq is lazy अधिकांश परिचालनों के लिए, यह वास्तव में तब तक कुछ नहीं करेगा जब तक कोई परिणाम नतीजे शुरू नहीं कर लेता है।

अगर आप

result.Count(); // add this line, query will be evaluated 
linqTime = stopwatch.ElapsedMilliseconds; 
stopwatch.Restart(); 

जोड़ा तो मैं यकीन है कि आप एक गैर शून्य LINQ के लिए परिणाम होगा हूँ।

+0

हाँ, मैंने देखा, लेकिन आप लोग मेरे लिए बहुत जल्दी थे। नए परिणाम देखें। यदि LINQ क्वेरी को फ़ोरैच लूप की तरह फोरैच होना चाहिए, तो यह धीमा क्यों है? –

+0

यदि आप इसके लिए जेनरेट कोड देखते हैं, तो फोरैच शायद सुंदर "फ्लैट" है, जहां जेनरेट कोड * संभवतया * इसमें कुछ अतिरिक्त विधि कॉल है जो फोरैच में/बाहर निकलने के लिए है, और वापसी की चीजें, और सामान उसके जैसा। –

0

यह स्पष्ट रूप से महत्वपूर्ण है कि Sum को ढेर पर सूची गणनाकर्ता के एक बॉक्स किए गए उदाहरण को स्टोर करना होगा, और हेप ऑब्जेक्ट का उपयोग सूची को फिर से करने के लिए करना होगा। इनलाइन फोरैच और लूप के लिए दोनों इससे बचते हैं; पूर्व क्योंकि सूची की सार्वजनिक GetEnumerator विधि एक मान प्रकार देता है। यदि आप IEnumerable<Person> चर में लोगों के लिए संदर्भ संग्रहीत करते हैं, तो फ़ोरैच लूप को इसके परिणाम प्राप्त करने में थोड़ा समय लगता है।

इसके अलावा, लिनक को जहां ऑटरेटर और प्रतिनिधि इसे पास कर चुके हैं, वहां ऑब्जेक्ट्स बनाना है, और यह अधिक शून्य जांच करता है ताकि अगर कोई तर्क शून्य हो तो जानकारीपूर्ण अपवाद फेंक सकता है। यह लिनक कोड के लिए आवश्यक अतिरिक्त समय के लिए जिम्मेदार हो सकता है।

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