Monday, February 10, 2014

C#: Count() or Length?


Level: 4 where 1 is noob and 5 is totally awesome
System: C# on .NET

Intro


When working with some data structures such as Arrays, strings or alike in C#, we often have 2 choices if we want to know the count of elements in the structure. For most I guess the choice might by easy, people are used to use Count() from LINQ or other structures, so Count() it often is. Length might feel like as, it is just something which pops up, when you scroll the intellisense. You see it, you know what it does, but you prefer Count(), because it makes more sense prosa wise in you code.

Are there any arguments for using Length? Yes.

Performance wise, Length is superior to Count(). Under Count() is some evaluation logic, to count the elements of the structure. Under Length is a pure IL mnemonic, meaning there is directly CLR support for Length.

An Example


I have a reduced IL example, to show what happens IL wise when Length/Count() in C# is compiled:

 .method private hidebysig static void Main(string[] args) cil managed  
 {  
      ...  
      ...  
      ...  
   
      // We initialize 3 variables  
  [0] string[] strings,     // The string array  
  [2] int32 length,         // The length variable  
  [3] int32 count,          // The count variable  
             
      ...  
      ...  
      ...  
   
      // Getting array element count by Length  
  IL_0020: ldloc.0          // puts the string array on the stack  
  IL_0021: ldlen            // using the IL mnemonic for to get length for the array. An unsigned int is returned  
  IL_0022: conv.i4          // The Length variable is a signed int so we convert the output from ldlen  
  IL_0023: stloc.2          // Stores the value, in the variable Length  
   
      ...  
      ...  
      ...  
   
      // Getting array element count by Count()  
  IL_005f: ldloc.0          // puts the string array on the stack  
                            // Next, calling Count() and gets a signed int.  
  IL_0060: call    int32 [System.Core]System.Linq.Enumerable::Count<string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)  
  IL_0065: stloc.3          // Stores the value, in the variable count  
      ...  
      ...  
      ...  
    
 } // end of method Program::Main  
   


Performance

To show the difference in performance, I will use the following example:


 using System;  
 using System.Diagnostics;  
 using System.Linq;  
   
 namespace ArrayCount  
 {  
   public class Program  
   {  
     static void Main(string[] args)  
     {  
       var strings = new string[1000];  
       var stopwatch = new Stopwatch();  
       var length = 0;  
       var count = 0;  
   
       Console.WriteLine("@Intel I5-3337");  
   
       stopwatch.Start();  
       for (var i = 0; i < 1000000; i++)  
       {  
         length = strings.Length;  
       }  
       stopwatch.Stop();  
   
       Console.WriteLine("Counted {0} elements by using Length : {1} ms", length, stopwatch.ElapsedMilliseconds);  
   
       stopwatch.Restart();  
       for (var i = 0; i < 1000000; i++)  
       {  
         count = strings.Count();  
       }  
       stopwatch.Stop();  
   
       Console.WriteLine("Counted {0} elements by using Count() : {1} ms", count, stopwatch.ElapsedMilliseconds);  
     }  
   }  
 }  
   

When compiling for release and running it without debugger (shift+f5) the output is:

 @Intel I5-3337  
 Counted 1000 elements by using Length : 0 ms <--- Less than millisecond, not no time:-) 
 Counted 1000 elements by using Count() : 66 ms  
 Press any key to continue . . .  

Conclusion

Now you know the difference between Length and Count(). When performance is preferred Length should always be used, but in general it depends on the context. 


No comments:

Post a Comment