For vs Foreach vs LinQ vs Array vs List - Performance Tests

So, this is something that I always read about it, and I've see a few contradictions here and there, so I've decided to do this test by my own! And see which performance betters compared to the others! 

Populating

So, for the testing purpose I'll just created a simple class here, like this one:

using System;

[Serializable]
public class ClassOne
{
    public float simpleFloat;
    public int simpleInt;
    public string simpleString;

    public ClassOne(float pFloat, int pInt, string pString)
    {
        simpleFloat = pFloat;
        simpleInt = pInt;
        simpleString = pString;
    }
}

And I'll first populate with a 5000 items and create one Array and one List

public class PerformanceTestController : MonoBehaviour 
{

    public List<ClassOne> list = new List<ClassOne>();
    public ClassOne[] array;


    public bool populateList;
    public bool populateArray;


    private void PopulateList()
    {
        Stopwatch tStopwatch = new Stopwatch();
        tStopwatch.Start();
        list = new List<ClassOne>();
        for (int i = 0; i < 1000; i++)
        {
            ClassOne tClassOne = GenerateNewObject();

            list.Add(tClassOne);
        }
        tStopwatch.Stop();
        Debug.Log("Total time to populate a list: " + tStopwatch.Elapsed);
    }

   

    private void PopulateArray ()
    {
        Stopwatch tStopwatch = new Stopwatch();
        tStopwatch.Start();
        array = new ClassOne[1000];
        for (int i = 0 ; i < 1000 ; i++)
        {
            ClassOne tClassOne = GenerateNewObject();

            array[i] = tClassOne;
        }
        tStopwatch.Stop();
        Debug.Log("Total time to populate a array: " + tStopwatch.Elapsed);
    }


    private static ClassOne GenerateNewObject ()
    {
        int tRandomInt = Random.Range(0, 100);
        float tRandomFloat = Random.Range(0f, 100f);
        string tString = string.Format("String test: int = {0}, float = {1}", tRandomInt, tRandomFloat);

        ClassOne tClassOne = new ClassOne(tRandomFloat, tRandomInt, tString);
        return tClassOne;
    }

    void Update()
    {
        if (populateList)
        {
            populateList = false;
            PopulateList();
        }

        if (populateArray)
        {
            populateArray = false;
            PopulateArray();
        }
    }

Result Populating a List vs Array

  The Array, after 3 tests, seems to be an average of 13.62% faster than populate a List

 

The Array, after 3 tests, seems to be an average of 13.62% faster than populate a List

Update - Populating a list with max items

When you initialize a List without max item setted, the list is initialized with 40 empty items, when you reach the item 41, the list will add more 40 items to the list and goes on, so a few more comparison between the performance in both:

Don't 

Don't 



Traveling using foreach - difference between Array and List

Now lets try the difference between the foreach and for in this generated class, using the following methods:

 public void TravelListInForeach()
 {
     Stopwatch tStopwatch = new Stopwatch();
     tStopwatch.Start();
     foreach (ClassOne tClassOne in list)
     {

     }
     tStopwatch.Stop();
     Debug.Log("Total time to run the List using foreach: " + tStopwatch.Elapsed);
 }

public void TravelArrayInForeach ()
{
    Stopwatch tStopwatch = new Stopwatch();
    tStopwatch.Start();
    foreach (ClassOne tClassOne in array)
    {

    }
    tStopwatch.Stop();
    Debug.Log("Total time to run the Array using foreach: " + tStopwatch.Elapsed);
}

Result traveling using foreach

Using the foreach the Array proved to be an average of 647% faster than List

Using the foreach the Array proved to be an average of 647% faster than List


Traveling using for - difference between Array and List

Now lets using a regular for, using these methods:

 public void TravelListInFor ()
 {
     Stopwatch tStopwatch = new Stopwatch();
     tStopwatch.Start();
     for (int i = 0; i < list.Count; i++)
     {
       ClassOne tClassOne = list[i];
     }
     tStopwatch.Stop();
     Debug.Log("Total time to run the List using for: " + tStopwatch.Elapsed);
 }

public void TravelArrayInFor ()
{
    Stopwatch tStopwatch = new Stopwatch();
    tStopwatch.Start();
    for (int i = 0; i < array.Length; i++)
    {
      ClassOne tClassOne = array[i];
    }
    tStopwatch.Stop();
    Debug.Log("Total time to run the Array using for: " + tStopwatch.Elapsed);
}

Result traveling using for

Using a regular for, the Array proved to be an average of 189% faster than List

Using a regular for, the Array proved to be an average of 189% faster than List


Traveling using for - difference between Array and List assign the variable first

I've decided to made more one test using for, but this time saving the Count and the Length in a variable before the for, like this:

 public void TravelListInFor2 ()
 {
     Stopwatch tStopwatch = new Stopwatch();
     tStopwatch.Start();
     int tCount = list.Count;
     for (int i = 0 ; i < tCount ; i++)
     {
       ClassOne tClassOne = list[i];
     }
     tStopwatch.Stop();
     Debug.Log("Total time to run the List using for: " + tStopwatch.Elapsed);
 }

public void TravelArrayInFor2 ()
{
    Stopwatch tStopwatch = new Stopwatch();
    tStopwatch.Start();
    int tLenght = array.Length;
    for (int i = 0 ; i < tLenght ; i++)
    {
      ClassOne tClassOne = array[i];
    }
    tStopwatch.Stop();
    Debug.Log("Total time to run the Array using for: " + tStopwatch.Elapsed);
}

Results

Now the difference between both are not so bigger, but the array still 60% faster than list

Now the difference between both are not so bigger, but the array still 60% faster than list

Just to display, that saving the enumerator before the for, gives a performance increase of 56%

Just to display, that saving the enumerator before the for, gives a performance increase of 56%


Search a regular for 

The code used is here

  public void SearchUsingForOnArray ()
  {
      Stopwatch tStopwatch = new Stopwatch();
      tStopwatch.Start();
      int tCount = array.Length;
      for (int i = 0 ; i < tCount ; i++)
      {
        ClassOne tClassOne = array[i];

        if (tClassOne.simpleInt == 50)
          break;
      }
      tStopwatch.Stop();
      Debug.Log("Total time to search the list using for: " + tStopwatch.Elapsed);
  }
 public void SearchUsingForOnList ()
    {
        Stopwatch tStopwatch = new Stopwatch();
        tStopwatch.Start();
        int tCount = list.Count;
        for (int i = 0 ; i < tCount ; i++)
        {
            ClassOne tClassOne = list[i];

            if(tClassOne.simpleInt == 50)
                break;
        }
        tStopwatch.Stop();
        Debug.Log("Total time to search the list using for: " + tStopwatch.Elapsed);
    }

Results

Again, the performance of the same operation on a Length is outstanding

Again, the performance of the same operation on a Length is outstanding


Searching using LinQ 

code used:

 public void SearchUsingLinqOnList ()
 {
     Stopwatch tStopwatch = new Stopwatch();
     tStopwatch.Start();

     ClassOne tClassOne = list.FirstOrDefault(x => 50 == x.simpleInt);
     tStopwatch.Stop();
     Debug.Log("Total time to search the list using for: " + tStopwatch.Elapsed);
 }

public void SearchUsingLinqOnArray ()
{
    Stopwatch tStopwatch = new Stopwatch();
    tStopwatch.Start();

    ClassOne tClassOne = array.FirstOrDefault(x => 50 == x.simpleInt);
    tStopwatch.Stop();
    Debug.Log("Total time to search the list using for: " + tStopwatch.Elapsed);
}

Results

This is strange! The List is almost 200% times faster than the Array on this case.

This is strange! The List is almost 200% times faster than the Array on this case.

Another thing that I've noticed, when you are using a LinQ on a array, the first time initialization need to generate the enumerator, that's why the first one is so expensive. 

     

 

 

 

 

Conclusion

After this tests, a few last comments here:

- I'm not a C# or Visual Studio expert, so maybe a few things here that I don't know why
- Array is 99% of the times faster than a List, so use it whenever you can
- The LinQ is not lighter than a regular for, but maintains a clear code in my opinion
- Avoid foreach
- Assign the enumerator to a variable, do not user Count on a for in to a List


That's it guys :)