Выявление узкого места в производительности с помощью информации профайлера ANTs

Этот код работает довольно медленно:

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 )));
        }        
    }

В частности, проблема с оператором select, где мы сравниваем d.IDCode с c.IDCode. Эта строка сообщает о количестве совпадений в 90 миллионов от ANTS с% времени 14,8. items.count составляет около 9 тысяч.

Я знаю, что моя точка останова не достигнута 90 миллионов раз. Что здесь означает число попаданий?

Другой полезный код:

LabItem имеет List<LabLineItem> это то, что мы сравниваем здесь. 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();
    }

1 ответ

Решение

ANTS говорит, что Select с string.Compare Звонок совершается 90 миллионов раз, потому что для каждого элемента в основном списке он снова ищет весь список.

Каждая из первичных 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)));
Другие вопросы по тегам