【问题标题】:C# Double Foreach OptimizationC# 双 Foreach 优化
【发布时间】:2016-08-14 14:41:39
【问题描述】:

我在这里遇到了一个问题,最近我在一个网络项目(在 Sitefinity 中创建)中发现了这个问题,当时我试图获取需要添加到缓存中以便更快访问的文章的完整列表。

我发现一些天才开发人员 XD 过去常常获取属于分类单元中存在的某个类别的文章的完整列表(sitefinity 的一些属性识别该类别的类型,例如:怀孕 - 婴儿 - 孩子......你明白了),并且必须在具有动态内容的项目集合中进行一些搜索,其中包含有关文章的信息(标题、图像、样式、文本)。

好吧,我的问题是他们使用 ForEach 进行了双循环研究,而我的老板想要“优化”该循环,因为当然,执行该循环花费的时间太长(有时可能更长超过 3 或 4 分钟,是的,我的老板希望立即完成这个过程 :) )。

代码如下:

   foreach (HierarchicalTaxon subt in listWeek)
   {
       foreach (DynamicContent item in myCollection)
       {
            if (item.Organizer.TaxonExists("Category", subt.Id))
            {
                 item.Author = subt.Name;
                 //if (articles.Where(art => art.Author.Equals(item.Author)).Count() == 0)
                 articles.Add(item);
            }
       }
   }

所以我必须处理这个 2^n 实现的双循环,我的问题是,我该怎么做?!?!?!

正如我在其他线程中看到的那样,我正在考虑添加一些 LINQ,但它似乎比这个实际代码慢得多。

看起来 myCollection 没有长长的元素集,但我很确定我必须在其他项目中使用相同逻辑的其他句子中使用这种优化。

拜托各位,稍微备份一下会很感激,有没有可能做得更快??


所以我们开始吧,你们觉得这样好吗??

var data = listWeek.ToDictionary(x => x.Id, x => x.Name);
var iDdata = data.Keys;
var nombresData = data.Values;

foreach (DynamicContent item in myCollection)
{
    if (item.Organizer.TaxonExists("Category", iDdata.First()) )
    {
        item.Author = nombresData.First();
        articlesPrueba1.Add(item);
    }
}

编辑:16/08/2016 --> 目前不工作,首先,我在尝试访问字典的值时遇到了麻烦,所以我为 Id 和 Name 附加了单独的变量,我想应该可以,但我不确定。

但后来我遇到了这个问题,只是在字典数据的内容中做了一轮,看起来很明显,但我认为这样可以,但很遗憾,它没有。


我正在尝试使用 LINQ:

 foreach (HierarchicalTaxon subt in listWeek)
 {
    foreach (DynamicContent item in myCollection.Where(item => item.Organizer.TaxonExists("Category", subt.Id)))
    {
        item.Author = subt.Name;
        articlesPrueba2.Add(item);
        }
    }
 }

但是我得到了这个关于查询没有访问数据库的异常,该死的 Sitefinity,我恨你……但没关系,我并不真正关心 LINQ。

仍然存在严重的优化问题。

【问题讨论】:

  • 我很想看看探查器在这里说什么。您假设嵌套循环是问题所在,但此代码中存在很多效率低下的机会,并且如果不查看一直花费的时间,很难给您一个好的答案。
  • 好吧,当我在调试时,我首先猜测它是缓存,但后来我正在寻找项目在加载内容时花费更多时间的断点,我得到了这个 contentService 隔离,其中foreach 循环必须检查 listWeek 和我的 Collection 对象,在那里获取具有我需要的正确内容的文章集合需要很长时间。但是你是对的,可能还有很多其他的麻烦,我是这个部门的新人,从这个项目开始,从 2013 年开始运行,仅仅 1 个多月就开始提供支持!我想知道它有多大。
  • 明白了——但你不确定是嵌套循环,还是 TaxonExists 方法,甚至是调用 articles.Add。使用分析器进行确认,然后根据测量结果进行优化。一旦你这样做了,如果结果是嵌套循环,下面的字典建议应该会有所帮助。
  • 我正在使用 Telerik 的提琴手,创建 sitefinity 的同一组,我必须在 Visual Studio 中使用的 CMS,你能推荐我一个好的分析器吗?兄弟,我会很感激的。
  • 我使用 JetBrains dotTrace,但那里有很多。蚂蚁不错。一个快速的谷歌搜索出现了这个免费的:nprofiler.com。他们通常有免费试用 - 试一试,看看你喜欢什么。

标签: c# loops optimization foreach


【解决方案1】:

这段代码效率很低,这是肯定的。

从我可以得到的代码中,您基本上想检查动态内容项是否具有类别,如果是,则获取该类别的名称并将其分配给 Author 属性。

更好的方法是循环动态内容项目的集合(仅一次)并检查项目是否具有类别。如果是这样,则使用分类管理器查找分类单元并获取其名称/标题并将其分配给动态内容。

这样,您必须循环一次集合,然后仅在需要时查询分类。

【讨论】:

  • 说得好,伙计,你说的对这样做,我必须检查所有的集合、动态内容和分类法。看到我的问题,我正在考虑在内部循环中放置一个中断,但我不能这样做,因为我会在文章循环中添加更少的项目。看我并不懒惰,只是我在这个优化方面相对较新。另外,我们都知道优化是一项非常艰巨的任务。另外,我想澄清一下,我必须检查 Category 和 Author 属性才能添加到文章中。
  • 该死我不能编辑,我不得不说你是对的,在获得分类名称后我必须继续分配该文章的作者姓名,然后将该项目添加到我的第三个列出“文章”。那么问题是,是否可以在一个循环中检查整个两个集合“listWeek”和“myCollection”?我知道我可以将 Linq 添加到这些循环中以在一轮中同时检查“if”条件,但我认为这在性能方面甚至是最差的。
【解决方案2】:

您可以通过将上周转换为Dictionary 以 Id 和 Name 的 KeyValue 对的形式优化代码。

 var data = listWeek.ToDictionary(x => x.Id, x => x.Name);

接下来,像现在一样使用从字典中查找类别的方法遍历 myCollection

【讨论】:

  • 为什么不使用LINQ JOIN,因为无论如何您都在使用LINQ?
  • 当然,可以使用 LINQ JOIN,但我觉得主要的优化可以通过将两个循环减少到一个来实现。
  • 这假设字典可以保存。每次运行此例程时重新生成字典可能比一开始只执行嵌套循环要慢。
  • 没有。我并不是要在循环中创建字典,而是在外部创建字典。所以它应该只创建一次。
  • 如果我使用字典,我也必须在字典中转换 HierarchicalTaxon subt??或者可以在一个循环中做到这一点?我现在无法访问 C# 代码,但对我来说更重要的是了解如何提高此循环(特别是内部循环)中的性能
猜你喜欢
  • 2011-04-06
  • 1970-01-01
  • 2021-01-10
  • 1970-01-01
  • 1970-01-01
  • 2019-03-15
  • 2023-03-13
  • 2023-03-27
  • 2013-06-30
相关资源
最近更新 更多