C # Performance of classes with generics

Consider the set of elements that are derived from the base element.

// "Abstract" general element class class AElement { public int Key; } // Specific element class implementation class BElement : AElement { } 

I want to save to the list. Two options:

 List<AElement> aData = new List<AElement>(); List<BElement> bData = new List<BElement>(); 

If you add BElement to the aData and bData lists and perform operations on them, the bData version is significantly faster than the aData version. For example, if you use a generic dump of BubbleSort, sorting the "key" AElement:

 static void BubbleSort<TElement>(List<TElement> Data) where TElement : AElement { for (int i = 0; i < Data.Count; i++) { for (int j = 0; j < Data.Count; j++) { if (Data[i].Key< Data[j].Key) { TElement tmp = Data[i]; Data[i] = Data[j]; Data[j] = tmp; } } } } 

In my case with 5000 data elements, I see a 20% difference in favor of bData compared to aData.

Why is bData faster than aData here?

Edit: Added full code:

 using System; using System.Collections.Generic; using System.Diagnostics; namespace TemplateClassPerformance { class Program { // "Abstract" general element class class AElement { public int Index; } // Specific element class implementation class BElement : AElement { } static void Main(string[] args) { Random random = new Random(); Stopwatch stopwatch = new Stopwatch(); for (int j = 0; j < 10; j++) { List<AElement> aData = new List<AElement>(); List<BElement> bData = new List<BElement>(); // Put the same elements in both lists for (int i = 0; i < 5000; i++) { BElement element = new BElement(); element.Index = random.Next(1000000); aData.Add(element); bData.Add(element); } stopwatch.Reset(); stopwatch.Start(); BubbleSort(bData); stopwatch.Stop(); long sbTicks = stopwatch.ElapsedTicks; stopwatch.Reset(); stopwatch.Start(); BubbleSort(aData); stopwatch.Stop(); long saTicks = stopwatch.ElapsedTicks; Console.Out.WriteLine("sb: {0}, sa: {1}", sbTicks, saTicks); } } static void BubbleSort<TElement>(List<TElement> data) where TElement : AElement { for (int i = 0; i < data.Count; i++) { for (int j = 0; j < data.Count; j++) { if (data[i].Index < data[j].Index) { TElement tmp = data[i]; data[i] = data[j]; data[j] = tmp; } } } } } } 
+4
source share
2 answers
  • Public fields are not a good idea.
  • Bubble sorting is not a good grade.
  • This is still a strange result. Have you eliminated the effects of JIT and GC? Do the tests several times in a different order? Did you use a stopwatch?

Why is bData faster than aData here?

Answer: This should not be. I suspect some measurement artifact.


Edit, after viewing the full code:

There is a difference, and I can’t make a mistake in benchmarking. Therefore, there is something.

When I change the initialization to:

 int k = random.Next(1000000); aData.Add(new AElement() { Index = k }); bData.Add(new BElement() { Index = k }); 

The difference goes away. But I understand that this is not a complete answer.

+2
source

Please replace:

 for (int i = 0; i < 5000; i++) { BElement element = new BElement(); element.Index = random.Next(1000000); aData.Add(element); bData.Add(element); } 

with:

 int index_; for (int i = 0; i < 5000; i++) { BElement belement = new BElement(); AElement aelement = new AElement(); index_=random.Next(1000000); Belement.Index =Aelement.Index = index_; aData.Add(Aelement); bData.Add(Belement); } 

And report the result.

+1
source

Source: https://habr.com/ru/post/1346220/


All Articles