简体   繁体   English

C#具有泛型的类的性能

[英]C# Performance of classes with generics

Consider a set of elements that derive from a base element. 考虑一组从基本元素派生的元素。

// "Abstract" general element class
class AElement {
  public int Key;
}

// Specific element class implementation
class BElement : AElement {
}

That I want to store in a list. 我想存储在列表中。 The two options: 这两个选项:

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

If adding BElement's to both the aData and bData lists, and doing operations on the two, the bData version is significantly faster than the aData version. 如果将BElement添加到aData和bData列表,并对两者执行操作,则bData版本明显快于aData版本。 For example if using a dump generic BubbleSort, sorting of the "Key" of AElement: 例如,如果使用转储通用BubbleSort,则对AElement的“Key”进行排序:

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 up to 20% difference in favor of the bData compared to the aData. 在我使用5000个数据元素的情况下,与aData相比,我认为bData有利于20%的差异。

Why is the bData faster than the aData here? 为什么bData比aData更快?

Edit: Added complete 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;
          }
        }
      }
    }
  }
}
  1. Public fields are not a good idea. 公共领域不是一个好主意。
  2. Bubble sort is not a very good bench-mark 冒泡排序不是一个很好的基准
  3. It is still a strange result. 这仍然是一个奇怪的结果。 Did you eliminate JIT and GC effects? 你有没有消除JIT和GC的影响? Ran the tests multiple times in different order? 以不同的顺序多次测试? Did you use the Stopwatch? 你用过秒表吗?

Why is the bData faster than the aData here? 为什么bData比aData更快?

Answer: It shouldn't be. 答:不应该。 I'm suspecting some measurement artefact. 我怀疑是一些测量假象。


Edit, after seeing the full code: 在看到完整代码后编辑:

There is a difference, and I can't fault the benchmarking. 有一点不同,我不能错过基准测试。 So there is something to this. 所以有一些东西。

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 realize this is not a complete answer. 但我意识到这不是一个完整的答案。

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. 并报告结果。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM