Improve performance and reduce allocations in DecisionTreeBuilder<T>.

This commit is contained in:
Gert Driesen 2018-10-20 12:12:08 +02:00 committed by Ryan Nowak
parent 29b50c7b64
commit 3c9086e3d0
1 changed files with 12 additions and 9 deletions

View File

@ -74,14 +74,16 @@ namespace Microsoft.AspNetCore.Routing.DecisionTree
{ {
public static DecisionTreeNode<TItem> GenerateTree(IReadOnlyList<TItem> items, IClassifier<TItem> classifier) public static DecisionTreeNode<TItem> GenerateTree(IReadOnlyList<TItem> items, IClassifier<TItem> classifier)
{ {
var itemDescriptors = new List<ItemDescriptor<TItem>>(); var itemCount = items.Count;
for (var i = 0; i < items.Count; i++) var itemDescriptors = new List<ItemDescriptor<TItem>>(itemCount);
for (var i = 0; i < itemCount; i++)
{ {
var item = items[i];
itemDescriptors.Add(new ItemDescriptor<TItem>() itemDescriptors.Add(new ItemDescriptor<TItem>()
{ {
Criteria = classifier.GetCriteria(items[i]), Criteria = classifier.GetCriteria(item),
Index = i, Index = i,
Item = items[i], Item = item,
}); });
} }
@ -95,7 +97,7 @@ namespace Microsoft.AspNetCore.Routing.DecisionTree
private static DecisionTreeNode<TItem> GenerateNode( private static DecisionTreeNode<TItem> GenerateNode(
TreeBuilderContext context, TreeBuilderContext context,
DecisionCriterionValueEqualityComparer comparer, DecisionCriterionValueEqualityComparer comparer,
IList<ItemDescriptor<TItem>> items) List<ItemDescriptor<TItem>> items)
{ {
// The extreme use of generics here is intended to reduce the number of intermediate // The extreme use of generics here is intended to reduce the number of intermediate
// allocations of wrapper classes. Performance testing found that building these trees allocates // allocations of wrapper classes. Performance testing found that building these trees allocates
@ -156,16 +158,17 @@ namespace Microsoft.AspNetCore.Routing.DecisionTree
foreach (var branch in criterion.Value) foreach (var branch in criterion.Value)
{ {
var reducedItems = new List<ItemDescriptor<TItem>>(); bool hasReducedItems = false;
foreach (var item in branch.Value) foreach (var item in branch.Value)
{ {
if (context.MatchedItems.Add(item)) if (context.MatchedItems.Add(item))
{ {
reducedItems.Add(item); hasReducedItems = true;
} }
} }
if (reducedItems.Count > 0) if (hasReducedItems)
{ {
var childContext = new TreeBuilderContext(context); var childContext = new TreeBuilderContext(context);
childContext.CurrentCriteria.Add(criterion.Key); childContext.CurrentCriteria.Add(criterion.Key);
@ -189,7 +192,7 @@ namespace Microsoft.AspNetCore.Routing.DecisionTree
return new DecisionTreeNode<TItem>() return new DecisionTreeNode<TItem>()
{ {
Criteria = reducedCriteria.ToList(), Criteria = reducedCriteria,
Matches = matches, Matches = matches,
}; };
} }