【问题标题】:Why Ordered collection enumerates slower and how to handle it?为什么有序集合枚举速度较慢以及如何处理?
【发布时间】:2017-12-22 15:38:01
【问题描述】:

为什么是这个代码:

class Cord  : IComparable<Cord>
{
    public int X { get; set; }
    public int Y { get; set; }

    public int CompareTo(Cordother)
    {
            return this.X.CompareTo(other.X);
    }
}


List<Cord> Cords = LoadCords();
stopwatch.Start();

foreach(var cord in Cords)
{
          // do something
}
stopwatch.Stop();

比这段代码快几倍:

List<Cord> Cords = LoadCords().OrderBy(r=> r.x).ToList();
stopwatch.Start();

foreach(var cord in Cords)
{
          // do something
}

stopwatch.Stop();

为了提高我的应用程序(处理数百万条记录)的性能,我需要一个有序集合。我还尝试在 List 项上使用 SortSet 和 Sort 方法并实现IComparable。无论哪种方式,有序列表上的相同迭代都比未触及的迭代花费更多的时间。为什么会这样?如何让我的排序集合像基本集合一样高效地迭代?

编辑:我只测量迭代的时间。我知道排序本身需要时间。循环内部发生的操作无关紧要。

从字面上看,当我用排序注释掉这一行时,迭代时间会变小。它不应该,在其他基准测试中也不应该,但是在我当前的应用程序中会发生这种情况,我想知道是否有人可以就这个话题给我一些建议。

【问题讨论】:

  • 您说有序集合枚举速度较慢,但​​您的代码中唯一实际发生的地方是.ToList()。您实际上在进行什么基准测试?
  • 排序是一项昂贵的操作。如果在进行排序之前先使用 cord.x &gt; 2 过滤所有项目,您可能会获得一些性能改进。
  • 您应该在LoadCords 方法中过滤和排序数据(cord.x > 2 ...),而不是将所有数据都发送到您的应用程序...
  • 如果您想要准确的性能计时,您应该使用 System.Diagnostics.Stopwatch。 DateTime.Now 不会给出准确的结果。
  • Cord 是值类型还是引用类型?

标签: c# .net performance linq


【解决方案1】:

尝试先使用 linq 查询过滤结果,而不是在循环中执行条件。

var cords = LoadCords().Where(cord => cord.x >2);
// Now iterate via linq .ForEach/.Select to do something without if condition.

此外,正如其他人建议的那样,使用 DataTime.Now 不会给出准确的结果。使用秒表。

【讨论】:

  • 这无关紧要,顺便说一句,使用 Where before 会减慢整个过程,秒表给出相同的结果
猜你喜欢
  • 2016-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-10
  • 2013-10-05
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
相关资源
最近更新 更多