Improve performance of ActorInfo.TraitsInConstructOrder.
Avoid redundant enumerations of the more and unresolved enumerables. This gives an approx 3x speedup for this function.
This commit is contained in:
@@ -115,27 +115,34 @@ namespace OpenRA
|
|||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
var resolved = source.Where(s => s.Dependencies.Count == 0 && s.OptionalDependencies.Count == 0).ToList();
|
var resolved = source.Where(s => s.Dependencies.Count == 0 && s.OptionalDependencies.Count == 0).ToList();
|
||||||
var unresolved = source.Except(resolved);
|
var unresolved = source.ToHashSet();
|
||||||
|
unresolved.ExceptWith(resolved);
|
||||||
|
|
||||||
var testResolve = new Func<Type, Type, bool>((a, b) => a == b || a.IsAssignableFrom(b));
|
bool AreResolvable(Type a, Type b) => a.IsAssignableFrom(b);
|
||||||
|
|
||||||
// This query detects which unresolved traits can be immediately resolved as all their direct dependencies are met.
|
// This query detects which unresolved traits can be immediately resolved as all their direct dependencies are met.
|
||||||
var more = unresolved.Where(u =>
|
var more = unresolved.Where(u =>
|
||||||
u.Dependencies.All(d => // To be resolvable, all dependencies must be satisfied according to the following conditions:
|
u.Dependencies.All(d => // To be resolvable, all dependencies must be satisfied according to the following conditions:
|
||||||
resolved.Exists(r => testResolve(d, r.Type)) && // There must exist a resolved trait that meets the dependency.
|
resolved.Exists(r => AreResolvable(d, r.Type)) && // There must exist a resolved trait that meets the dependency.
|
||||||
!unresolved.Any(u1 => testResolve(d, u1.Type))) && // All matching traits that meet this dependency must be resolved first.
|
!unresolved.Any(u1 => AreResolvable(d, u1.Type))) && // All matching traits that meet this dependency must be resolved first.
|
||||||
u.OptionalDependencies.All(d => // To be resolvable, all optional dependencies must be satisfied according to the following condition:
|
u.OptionalDependencies.All(d => // To be resolvable, all optional dependencies must be satisfied according to the following condition:
|
||||||
!unresolved.Any(u1 => testResolve(d, u1.Type)))); // All matching traits that meet this optional dependencies must be resolved first.
|
!unresolved.Any(u1 => AreResolvable(d, u1.Type)))); // All matching traits that meet this optional dependencies must be resolved first.
|
||||||
|
|
||||||
// Continue resolving traits as long as possible.
|
// Continue resolving traits as long as possible.
|
||||||
// Each time we resolve some traits, this means dependencies for other traits may then be possible to satisfy in the next pass.
|
// Each time we resolve some traits, this means dependencies for other traits may then be possible to satisfy in the next pass.
|
||||||
while (more.Any())
|
var readyToResolve = more.ToList();
|
||||||
resolved.AddRange(more);
|
while (readyToResolve.Count != 0)
|
||||||
|
{
|
||||||
|
resolved.AddRange(readyToResolve);
|
||||||
|
unresolved.ExceptWith(readyToResolve);
|
||||||
|
readyToResolve.Clear();
|
||||||
|
readyToResolve.AddRange(more);
|
||||||
|
}
|
||||||
|
|
||||||
if (unresolved.Any())
|
if (unresolved.Count != 0)
|
||||||
{
|
{
|
||||||
var exceptionString = "ActorInfo(\"" + Name + "\") failed to initialize because of the following:\r\n";
|
var exceptionString = "ActorInfo(\"" + Name + "\") failed to initialize because of the following:\r\n";
|
||||||
var missing = unresolved.SelectMany(u => u.Dependencies.Where(d => !source.Any(s => testResolve(d, s.Type)))).Distinct();
|
var missing = unresolved.SelectMany(u => u.Dependencies.Where(d => !source.Any(s => AreResolvable(d, s.Type)))).Distinct();
|
||||||
|
|
||||||
exceptionString += "Missing:\r\n";
|
exceptionString += "Missing:\r\n";
|
||||||
foreach (var m in missing)
|
foreach (var m in missing)
|
||||||
|
|||||||
Reference in New Issue
Block a user