【问题标题】:Identifying the bottleneck in performance with help from ANTs profiler info在 ANT 分析器信息的帮助下识别性能瓶颈
【发布时间】:2012-11-15 09:06:13
【问题描述】:

这段代码运行得很慢:

public static class DB
    {
        readonly static InlineSql sql = new InlineSql();

        public static IEnumerable<LabItem> GetLabItemsFromLabLineItems(IEnumerable<LabLineItem> items)
        {
            /*
             * Business Rule : 
             * The sproc used to retrieve lab line items has no way of "grouping" lab items out of line items.
             * To compensate, the sproc orders its results by IDCode, we group everything and use the first of each grouping to represent that ID Code.
             * That very same item is also the first item in its Items property.
             * */
            return items
                .GroupBy(c => c.IDCode , c => c, (c, d) => d.First())
                .Select(c => new LabItem(c.IDCode, c.OrderGuid, c.Name, c.SignificantDtm, c.Status, c.Description, items.Where(d => string.Compare(d.IDCode, c.IDCode, true) == 0 )));
        }        
    }

特别是我们将 d.IDCode 与 c.IDCode 进行比较的 select 语句似乎是问题所在。此行报告来自 ANTS 的命中数为 9000 万,时间百分比为 14.8。 items.count 大约是 9000。

我知道我的断点没有被命中 9000 万次。这里的命中数是什么意思?

其他有用的代码:

LabItemList&lt;LabLineItem&gt;,这是我们在这里比较的。 LabLineItem.Equals:

    public override bool Equals(object obj)
    {
        LabLineItem otherItem = obj as LabLineItem;

        if (otherItem == null) return false;

        return
            OrderGuid == otherItem.OrderGuid
            && IDCode == otherItem.IDCode
            && SignificantDtm == otherItem.SignificantDtm
            && ObservationGuid == otherItem.ObservationGuid
            && string.Compare(Value, otherItem.Value, true) == 0;
    }
    public override int GetHashCode()
    {
        return
            OrderGuid.GetHashCode()
            ^ IDCode.GetHashCode()
            ^ SignificantDtm.GetHashCode()
            ^ ObservationGuid.GetHashCode();
    }

【问题讨论】:

  • 嗯,潜在的嵌套枚举器可能会造成严重的性能问题...stackoverflow.com/questions/1043050/…。在 ANTS 上,我一直认为命中数是“实际”命中数。这看起来很有帮助:stackoverflow.com/questions/8454084/…
  • @Cal279 - 我怀疑它正在进入代表。我不会介入代表。我越过那条线。也许这就是区别。
  • @P.Brian.Mackey 调用的代表确实增加了命中数。

标签: c# linq profiler red-gate-ants


【解决方案1】:

ANTS 是说 Selectstring.Compare 调用被点击了 9000 万次,因为对于主列表中的每个项目,它都会再次搜索整个列表。

主要的 9000 次迭代中的每一次都会导致 9000 次额外的迭代,因此必须至少调用 string.Compare 81,000,000 次。

我建议建立一个分组缓存,然后用它来构建LabItem

可能是这样的:

var groupedItems = items.GroupBy(c => c.IDCode);

return items.Select(c => 
                new LabItem(c.IDCode, c.OrderGuid, c.Name, c.SignificantDtm, c.Status, c.Description, 
                groupedItems.Where(d => string.Compare(d.Key, c.IDCode, true) == 0 ).SelectMany(group => group)));

【讨论】:

  • +1 这看起来很有希望。我只需要弄清楚如何将IEnumerable&lt;IGrouping&lt;string, LabLineItem&gt;&gt; 转换回IEnumerable&lt;LabLineItem&gt;,否则我将不得不更改我认为不应该在这里做的 LabItem 构造函数。
  • 构造函数期望什么类型? IGrouping&lt;K, T&gt; 实现了IEnumerable&lt;T&gt;,所以如果构造函数期望IEnumerable&lt;LabLineItem&gt;,它应该编译。
  • 只需要添加SelectMany。优秀的答案。非常感谢。
  • 太棒了!感谢您获得最后一点。
猜你喜欢
  • 1970-01-01
  • 2017-02-02
  • 2022-01-06
  • 1970-01-01
  • 2012-02-21
  • 2021-05-02
  • 2019-02-12
  • 1970-01-01
  • 2023-03-22
相关资源
最近更新 更多