I’ve tested List<string> vs IEnumerable<string>
iterations with for and foreach loops , is it possible that the List is much faster ?
these are 2 of few links I could find that are publicly stating that performance is better iterating IEnumerable over List.
my tests was loading 10K lines from a text file that holds a list of URLs.
I’ve first loaded it in to a List , then copied List to an IEnumerable
List<string> StrByLst = ...method to load records from the file .
IEnumerable StrsByIE = StrByLst;
so each has 10k items Type <string>
looping on each collection for 100 times , meaning 100K iterations, resulted with
List<string> is faster by amazing 50 x than the IEnumerable<string>
is that predictable ?
- update
this is the code that is doing the tests
string WorkDirtPath = HostingEnvironment.ApplicationPhysicalPath;
string fileName = "tst.txt";
string fileToLoad = Path.Combine(WorkDirtPath, fileName);
List<string> ListfromStream = new List<string>();
ListfromStream = PopulateListStrwithAnyFile(fileToLoad) ;
IEnumerable<string> IEnumFromStream = ListfromStream ;
string trslt = "";
Stopwatch SwFr = new Stopwatch();
Stopwatch SwFe = new Stopwatch();
string resultFrLst = "",resultFrIEnumrable, resultFe = "", Container = "";
SwFr.Start();
for (int itr = 0; itr < 100; itr++)
{
for (int i = 0; i < ListfromStream.Count(); i++)
{
Container = ListfromStream.ElementAt(i);
}
//the stop() was here , i was doing changes , so my mistake.
}
SwFr.Stop();
resultFrLst = SwFr.Elapsed.ToString();
//forgot to do this reset though still it is faster (x56??)
SwFr.Reset();
SwFr.Start();
for(int itr = 0; itr<100; itr++)
{
for (int i = 0; i < IEnumFromStream.Count(); i++)
{
Container = IEnumFromStream.ElementAt(i);
}
}
SwFr.Stop();
resultFrIEnumrable = SwFr.Elapsed.ToString();
Update … final
taking out the counter to outside of the for loops ,
int counter = ..countfor both IEnumerable & List
then passed counter(int) as a count of total items as suggested by @ScottChamberlain .
re checked that every thing is in place, now the results are 5 % faster IEnumerable.
so that concludes , use by scenario – use case… no performance difference at all …
You have a few problems with your test, one is the
IEnumFromStream.Count()inside theforloop, every time it want to get that value it must enumerate over the entire list to get the count and the value is not cached between loops. Move that call outside of theforloop and save the result in aintand use that value for theforloop, you will see a shorter time for your IEnumerable.Also the
IEnumFromStream.ElementAt(i)behaves similarly toCount()it must iterate over the whole list up toi(eg: first time it goes0, second time0,1, third0,1,2, and so on…) every time whereListcan jump directly to the index it needs. You should be working with theIEnumeratorreturned fromGetEnumerator()instead.IEnumerable‘s andforloop’s don’t mix well. Use the correct tool for the job, either callGetEnumerator()and work with that or use it in aforeachloop.Now, I know a lot of you may be saying “But it is a interface it will be just mapping the calls and it should make no difference”, but there is a key thing,
IEnumerable<T>Does not have aCount()orElementAt()method!. Those methods are extension methods added by LINQ, and the LINQ classes do not know the underlying collection is a List, so it does what it knows the underlying object can do, and that is iterating over the list every time the method is called.IEnumerableusingIEnumeratorThe above code is basically the same thing as
The important thing to remember is
IEnumerable‘s do not have a length, in fact they can be infinitely long. There is a whole field of computer science on detecting a infinitely longIEnumerable