Выявление узкого места в производительности с помощью информации профайлера 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)));