Improve MiniYaml MergePartial performance.
- Track plain keys in a set, to avoid quadratic searches for plain node keys. - Avoid the Concat iterator by looping twice instead.
This commit is contained in:
committed by
Matthias Mailänder
parent
a96e445e4d
commit
f5daa19a1c
@@ -437,34 +437,40 @@ namespace OpenRA
|
|||||||
return existingNodes;
|
return existingNodes;
|
||||||
|
|
||||||
var ret = new List<MiniYamlNode>(existingNodes.Count + overrideNodes.Count);
|
var ret = new List<MiniYamlNode>(existingNodes.Count + overrideNodes.Count);
|
||||||
|
var plainKeys = new HashSet<string>(existingNodes.Count + overrideNodes.Count);
|
||||||
|
|
||||||
foreach (var node in existingNodes.Concat(overrideNodes))
|
foreach (var node in existingNodes)
|
||||||
|
MergeNode(node);
|
||||||
|
foreach (var node in overrideNodes)
|
||||||
|
MergeNode(node);
|
||||||
|
|
||||||
|
void MergeNode(MiniYamlNode node)
|
||||||
{
|
{
|
||||||
// Append Removal nodes to the result.
|
// Append Removal nodes to the result.
|
||||||
// Therefore: we know the remainder of the loop deals with plain nodes.
|
// Therefore: we know the remainder of the method deals with a plain node.
|
||||||
if (node.Key.StartsWith("-", StringComparison.Ordinal))
|
if (node.Key.StartsWith("-", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
ret.Add(node);
|
ret.Add(node);
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no previous node with this key is present, it is new and can just be appended.
|
// If no previous node with this key is present, it is new and can just be appended.
|
||||||
var previousNodeIndex = ret.FindLastIndex(n => n.Key == node.Key);
|
if (plainKeys.Add(node.Key))
|
||||||
if (previousNodeIndex == -1)
|
|
||||||
{
|
{
|
||||||
ret.Add(node);
|
ret.Add(node);
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Removal node is closer than the previous node.
|
// A Removal node is closer than the previous node.
|
||||||
// We should not merge the new node, as the data being merged will jump before the Removal.
|
// We should not merge the new node, as the data being merged will jump before the Removal.
|
||||||
// Instead, append it so the previous node is applied, then removed, then the new node is applied.
|
// Instead, append it so the previous node is applied, then removed, then the new node is applied.
|
||||||
var removalKey = $"-{node.Key}";
|
var removalKey = $"-{node.Key}";
|
||||||
|
var previousNodeIndex = ret.FindLastIndex(n => n.Key == node.Key);
|
||||||
var previousRemovalNodeIndex = ret.FindLastIndex(n => n.Key == removalKey);
|
var previousRemovalNodeIndex = ret.FindLastIndex(n => n.Key == removalKey);
|
||||||
if (previousRemovalNodeIndex != -1 && previousRemovalNodeIndex > previousNodeIndex)
|
if (previousRemovalNodeIndex != -1 && previousRemovalNodeIndex > previousNodeIndex)
|
||||||
{
|
{
|
||||||
ret.Add(node);
|
ret.Add(node);
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A previous node is present with no intervening Removal.
|
// A previous node is present with no intervening Removal.
|
||||||
|
|||||||
Reference in New Issue
Block a user