2

我已经尝试根据传统的蛮力搜索检查 LINQ 性能,看起来 LINQ 比蛮力方法慢得多,并且使用 Contains 方法需要更长的时间!

以下是我的代码:

class Program
{
  int[] array;
  public Program(int size)
  {
     array = new int[size];
     for (int i = 0; i < size; i++)
     {
        array[i] = size - i;
     }
  }
  public void BruteForceSearch(int toBeSearched)
  {
     foreach (int i in array)
     {
        if (i == toBeSearched)
        {
           return;
        }
     }
  }
  public void SearchViaContainsMethod(int toBeSearched)
  {
     if (array.Contains(toBeSearched)) { return; }
  }
  public void SearchViaLINQ(int toBeSearched)
  {
     var x = from a in array
             where a == toBeSearched
             select a;
  }
  static void Main(string[] args)
  {
     Program p = new Program(100000);
     using (new OperationTimer("BruteForceSearch"))
     {
        p.BruteForceSearch(0);
     }
     using (new OperationTimer("SearchViaContainsMethod"))
     {
        p.SearchViaContainsMethod(0);
     }
     using (new OperationTimer("SearchViaLINQ"))
     {
        p.SearchViaLINQ(0);
     }
     Console.Read();
  }



class OperationTimer : IDisposable
{
  private Stopwatch m_stopwatch;
  private String m_text;

  public OperationTimer(String text)
  {
     m_text = text;
     m_stopwatch = Stopwatch.StartNew();
  }

  public void Dispose()
  {
     Console.WriteLine("{0} {1}",
        (m_stopwatch.Elapsed), m_text);
  }
}

输出:

00:00:00.0009032 BruteForceSearch
00:00:00.0068469 SearchViaContainsMethod
00:00:00.0032512 SearchViaLINQ

我可以理解所有事情所花费的时间都非常短,并且以当前处理器的速度使用 LINQ 可能不会产生内存开销。

我想知道,当处理大量数据时,速度会不会呈指数级增长,我们真的必须在速度上妥协以保证代码的可读性?

请帮助理解这一点。

(礼貌:OperationTimer 类型取自Jeffery Ritcher通过 C# 的 CLR 。

4

4 回答 4

4

是的,我们正在这样做:选择代码可读性而不是性能。但在绝大多数情况下,提高代码的可读性确实更好。如果您使用非常有限的内存或 CPU,或者在对性能非常敏感的环境中工作,这可能是个问题。但是如果你在这样的环境中,你不应该选择像 C#/.NET 这样的高级语言/平台。

如果您分析您的应用程序并发现 LINQ 的开销为某些特定操作增加了大量时间,那么您可以重写它以提高效率。在此之前担心它只是过早的微优化,并且弊大于利。

于 2013-10-16T11:58:15.870 回答
3

通常,由于常识原因,Linq 会更慢,因为它是 IEnumerable 之上的实现,而这只是一种抽象。任何对使用的数据结构有深入了解的算法“可以”比任何抽象实现更快。

现在您的特定基准不正确,因为实现不等效:

  • linq 应该使用 Any 扩展方法,以确保在第一次匹配时中断迭代,就像对其他 2 一样

  • linq 方法似乎无论如何都不会执行,因为你根本没有枚举结果,所以这让我对你实际测量的东西非常怀疑

于 2013-10-16T12:02:59.397 回答
2

没那么简单;原始示例实际上也没有在 LINQ 语句中找到任何内容 - 只是构建表达式树;实际定位实现 linq 表达式所需的元素;或将其更改为类似

var rv = array.SingleOrDefault(xx=>xx == toBeSearched);

不要忘记你需要在同一堂课上做两次整个事情,因为有启动开销;这样做给了我们

00:00:00.0001726 BruteForceSearch
00:00:00.0001774 SearchViaContainsMethod
00:00:00.0011443 SearchViaLINQ

00:00:00.0000009 BruteForceSearch
00:00:00.0000881 SearchViaContainsMethod
00:00:00.0009255 SearchViaLINQ

所以; 与所有事物一样,性能分析现实世界情况是唯一有效的优化方法。这是从一开始就做好的最难的事情之一,并且随着经验的增加(稍微)容易。

于 2013-10-16T12:02:21.997 回答
0

是的,LINQ 并不神奇,它是编译器的高级指令。

于 2013-10-16T11:54:12.470 回答