Remove allocations when enumerating sync hashes on an actor.

Exposing Actor.SyncHashes as an array allows allocation free enumeration, we just need to adjust the SyncHash type to run the hash function.
This commit is contained in:
RoosterDragon
2017-11-17 21:37:16 +00:00
committed by Paul Chote
parent 5338784e45
commit 8ef8c60a1a
3 changed files with 17 additions and 11 deletions

View File

@@ -28,8 +28,9 @@ namespace OpenRA
internal struct SyncHash internal struct SyncHash
{ {
public readonly ISync Trait; public readonly ISync Trait;
public readonly int Hash; readonly Func<object, int> hashFunction;
public SyncHash(ISync trait, int hash) { Trait = trait; Hash = hash; } public SyncHash(ISync trait) { Trait = trait; hashFunction = Sync.GetHashFunction(trait); }
public int Hash() { return hashFunction(Trait); }
} }
public readonly ActorInfo Info; public readonly ActorInfo Info;
@@ -70,7 +71,7 @@ namespace OpenRA
} }
} }
internal IEnumerable<SyncHash> SyncHashes { get; private set; } internal SyncHash[] SyncHashes { get; private set; }
readonly IFacing facing; readonly IFacing facing;
readonly IHealth health; readonly IHealth health;
@@ -129,11 +130,7 @@ namespace OpenRA
defaultVisibility = Trait<IDefaultVisibility>(); defaultVisibility = Trait<IDefaultVisibility>();
Targetables = TraitsImplementing<ITargetable>().ToArray(); Targetables = TraitsImplementing<ITargetable>().ToArray();
SyncHashes = SyncHashes = TraitsImplementing<ISync>().Select(sync => new SyncHash(sync)).ToArray();
TraitsImplementing<ISync>()
.Select(sync => Pair.New(sync, Sync.GetHashFunction(sync)))
.ToArray()
.Select(pair => new SyncHash(pair.First, pair.Second(pair.First)));
} }
Rectangle DetermineRenderBounds() Rectangle DetermineRenderBounds()

View File

@@ -68,28 +68,37 @@ namespace OpenRA.Network
report.Effects.Clear(); report.Effects.Clear();
foreach (var actor in orderManager.World.ActorsHavingTrait<ISync>()) foreach (var actor in orderManager.World.ActorsHavingTrait<ISync>())
{
foreach (var syncHash in actor.SyncHashes) foreach (var syncHash in actor.SyncHashes)
if (syncHash.Hash != 0) {
var hash = syncHash.Hash();
if (hash != 0)
{
report.Traits.Add(new TraitReport() report.Traits.Add(new TraitReport()
{ {
ActorID = actor.ActorID, ActorID = actor.ActorID,
Type = actor.Info.Name, Type = actor.Info.Name,
Owner = (actor.Owner == null) ? "null" : actor.Owner.PlayerName, Owner = (actor.Owner == null) ? "null" : actor.Owner.PlayerName,
Trait = syncHash.Trait.GetType().Name, Trait = syncHash.Trait.GetType().Name,
Hash = syncHash.Hash, Hash = hash,
NamesValues = DumpSyncTrait(syncHash.Trait) NamesValues = DumpSyncTrait(syncHash.Trait)
}); });
}
}
}
foreach (var sync in orderManager.World.SyncedEffects) foreach (var sync in orderManager.World.SyncedEffects)
{ {
var hash = Sync.Hash(sync); var hash = Sync.Hash(sync);
if (hash != 0) if (hash != 0)
{
report.Effects.Add(new EffectReport() report.Effects.Add(new EffectReport()
{ {
Name = sync.GetType().Name, Name = sync.GetType().Name,
Hash = hash, Hash = hash,
NamesValues = DumpSyncTrait(sync) NamesValues = DumpSyncTrait(sync)
}); });
}
} }
} }

View File

@@ -404,7 +404,7 @@ namespace OpenRA
// Hash fields marked with the ISync interface. // Hash fields marked with the ISync interface.
foreach (var actor in ActorsHavingTrait<ISync>()) foreach (var actor in ActorsHavingTrait<ISync>())
foreach (var syncHash in actor.SyncHashes) foreach (var syncHash in actor.SyncHashes)
ret += n++ * (int)(1 + actor.ActorID) * syncHash.Hash; ret += n++ * (int)(1 + actor.ActorID) * syncHash.Hash();
// Hash game state relevant effects such as projectiles. // Hash game state relevant effects such as projectiles.
foreach (var sync in SyncedEffects) foreach (var sync in SyncedEffects)