Reduce .ToArray() in PVS with NetListAsArray<T>.

This commit is contained in:
Pieter-Jan Briers
2021-10-05 14:37:39 +02:00
parent ef2f81a77a
commit 1c8958d312
11 changed files with 58 additions and 61 deletions
@@ -412,10 +412,10 @@ namespace Robust.Client.GameStates
private List<EntityUid> ApplyGameState(GameState curState, GameState? nextState)
{
_config.TickProcessMessages();
_mapManager.ApplyGameStatePre(curState.MapData, curState.EntityStates);
var createdEntities = ApplyEntityStates(curState.EntityStates, curState.EntityDeletions,
nextState?.EntityStates);
_players.ApplyPlayerStates(curState.PlayerStates);
_mapManager.ApplyGameStatePre(curState.MapData, curState.EntityStates.Array);
var createdEntities = ApplyEntityStates(curState.EntityStates.Array, curState.EntityDeletions.Array,
nextState?.EntityStates.Array);
_players.ApplyPlayerStates(curState.PlayerStates.Array);
_mapManager.ApplyGameStatePost(curState.MapData);
GameStateApplied?.Invoke(new GameStateAppliedArgs(curState));
@@ -442,7 +442,7 @@ namespace Robust.Client.GameStates
}
else //Unknown entities
{
var metaState = (MetaDataComponentState?) es.ComponentChanges?.FirstOrDefault(c => c.NetID == _metaCompNetId).State;
var metaState = (MetaDataComponentState?) es.ComponentChanges.Value?.FirstOrDefault(c => c.NetID == _metaCompNetId).State;
if (metaState == null)
{
throw new InvalidOperationException($"Server sent new entity state for {es.Uid} without metadata component!");
@@ -553,9 +553,9 @@ namespace Robust.Client.GameStates
var compStateWork = new Dictionary<ushort, (ComponentState? curState, ComponentState? nextState)>();
var entityUid = entity.Uid;
if (curState?.ComponentChanges != null)
if (curState?.ComponentChanges.Array is { } changes)
{
foreach (var compChange in curState.ComponentChanges)
foreach (var compChange in changes)
{
if (compChange.Deleted)
{
@@ -580,17 +580,17 @@ namespace Robust.Client.GameStates
}
}
if (curState?.ComponentChanges != null)
if (curState?.ComponentChanges.Array is { } changes2)
{
foreach (var compChange in curState.ComponentChanges)
foreach (var compChange in changes2)
{
compStateWork[compChange.NetID] = (compChange.State, null);
}
}
if (nextState?.ComponentChanges != null)
if (nextState?.ComponentChanges.Array is { } nextChanges)
{
foreach (var compState in nextState.ComponentChanges)
foreach (var compState in nextChanges)
{
if (compStateWork.TryGetValue(compState.NetID, out var state))
{
+17 -23
View File
@@ -168,37 +168,31 @@ namespace Robust.Client.GameStates
}
else
{
if (state.EntityDeletions != null)
foreach (var deletion in state.EntityDeletions.Array)
{
foreach (var deletion in state.EntityDeletions)
{
_lastStateFullRep.Remove(deletion);
}
_lastStateFullRep.Remove(deletion);
}
}
if (state.EntityStates != null)
foreach (var entityState in state.EntityStates.Array)
{
foreach (var entityState in state.EntityStates)
if (!_lastStateFullRep.TryGetValue(entityState.Uid, out var compData))
{
if (!_lastStateFullRep.TryGetValue(entityState.Uid, out var compData))
{
compData = new Dictionary<uint, ComponentState>();
_lastStateFullRep.Add(entityState.Uid, compData);
}
compData = new Dictionary<uint, ComponentState>();
_lastStateFullRep.Add(entityState.Uid, compData);
}
if (entityState.ComponentChanges != null)
if (entityState.ComponentChanges.Array is { } changes)
{
foreach (var change in changes)
{
foreach (var change in entityState.ComponentChanges)
if (change.Deleted)
{
if (change.Deleted)
{
compData.Remove(change.NetID);
}
else if (change.State is not null)
{
compData[change.NetID] = change.State;
}
compData.Remove(change.NetID);
}
else if (change.State is not null)
{
compData[change.NetID] = change.State;
}
}
}
@@ -352,7 +346,7 @@ namespace Robust.Client.GameStates
/// </summary>
private static GameState ExtrapolateState(GameTick fromSequence, GameTick toSequence, uint lastInput)
{
var state = new GameState(fromSequence, toSequence, lastInput, null, null, null, null);
var state = new GameState(fromSequence, toSequence, lastInput, default, default, default, null);
state.Extrapolated = true;
return state;
}
+2 -2
View File
@@ -65,10 +65,10 @@ namespace Robust.Client.GameStates
var gameState = args.AppliedState;
if(gameState.EntityStates is not null)
if(gameState.EntityStates.HasContents)
{
// Loop over every entity that gets updated this state and record the traffic
foreach (var entityState in gameState.EntityStates)
foreach (var entityState in gameState.EntityStates.Array)
{
var newEnt = true;
for(var i=0;i<_netEnts.Count;i++)
+6 -6
View File
@@ -79,17 +79,17 @@ namespace Robust.Client.GameStates
var conShell = IoCManager.Resolve<IConsoleHost>().LocalShell;
var entStates = args.AppliedState.EntityStates;
if (entStates is not null)
if (entStates.HasContents)
{
var sb = new StringBuilder();
foreach (var entState in entStates)
foreach (var entState in entStates.Array)
{
if (entState.Uid == WatchEntId)
{
if(entState.ComponentChanges is not null)
if(entState.ComponentChanges.Array is { } changes)
{
sb.Append($"\n Changes:");
foreach (var compChange in entState.ComponentChanges)
foreach (var compChange in changes)
{
var registration = _componentFactory.GetRegistration(compChange.NetID);
var create = compChange.Created ? 'C' : '\0';
@@ -107,10 +107,10 @@ namespace Robust.Client.GameStates
}
var entDeletes = args.AppliedState.EntityDeletions;
if (entDeletes is not null)
if (entDeletes.HasContents)
{
var sb = new StringBuilder();
foreach (var entDelete in entDeletes)
foreach (var entDelete in entDeletes.Array)
{
if (entDelete == WatchEntId)
{
+6 -4
View File
@@ -33,10 +33,11 @@ namespace Robust.Client.Map
//get shared euid of map comp entity
foreach (var entityState in entityStates!)
{
if(entityState.ComponentChanges is null)
var changes = entityState.ComponentChanges.Array;
if (changes is null)
continue;
foreach (var compChange in entityState.ComponentChanges)
foreach (var compChange in changes)
{
if (compChange.State is not MapComponentState mapCompState || mapCompState.MapId != mapId)
continue;
@@ -68,10 +69,11 @@ namespace Robust.Client.Map
//get shared euid of map comp entity
foreach (var entityState in entityStates!)
{
if (entityState.ComponentChanges is null)
var changes = entityState.ComponentChanges.Array;
if (changes is null)
continue;
foreach (var compState in entityState.ComponentChanges)
foreach (var compState in changes)
{
if (compState.State is not MapGridComponentState gridCompState || gridCompState.GridIndex != gridId)
continue;
+1 -1
View File
@@ -24,7 +24,7 @@ namespace Robust.Client.Player
void Startup();
void Shutdown();
void ApplyPlayerStates(IEnumerable<PlayerState>? list);
void ApplyPlayerStates(PlayerState[] list);
}
public class LocalPlayerChangedEventArgs : EventArgs
+2 -2
View File
@@ -103,9 +103,9 @@ namespace Robust.Client.Player
}
/// <inheritdoc />
public void ApplyPlayerStates(IEnumerable<PlayerState>? list)
public void ApplyPlayerStates(PlayerState[] list)
{
if (list == null)
if (list.Length == 0)
{
// This happens when the server says "nothing changed!"
return;
@@ -208,11 +208,11 @@ namespace Robust.Server.GameStates
// lastAck varies with each client based on lag and such, we can't just make 1 global state and send it to everyone
var lastInputCommand = inputSystem.GetLastInputCommand(session);
var lastSystemMessage = _entityNetworkManager.GetLastMessageSequence(session);
var state = new GameState(lastAck, _gameTiming.CurTick, Math.Max(lastInputCommand, lastSystemMessage), entStates?.ToArray(), playerStates?.ToArray(), deletions?.ToArray(), mapData);
var state = new GameState(lastAck, _gameTiming.CurTick, Math.Max(lastInputCommand, lastSystemMessage), entStates, playerStates, deletions, mapData);
InterlockedHelper.Min(ref oldestAckValue, lastAck.Value);
DebugTools.Assert(state.MapData?.CreatedMaps is null || (state.MapData?.CreatedMaps is not null && state.EntityStates is not null), "Sending new maps, but no entity state.");
DebugTools.Assert(state.MapData?.CreatedMaps is null || (state.MapData?.CreatedMaps is not null && state.EntityStates.HasContents), "Sending new maps, but no entity state.");
// actually send the state
var stateUpdateMessage = _networkManager.CreateNetMessage<MsgState>();
+5 -5
View File
@@ -1,5 +1,6 @@
using Robust.Shared.Serialization;
using System;
using NetSerializer;
namespace Robust.Shared.GameObjects
{
@@ -8,16 +9,15 @@ namespace Robust.Shared.GameObjects
{
public EntityUid Uid { get; }
public ComponentChange[]? ComponentChanges { get; }
public NetListAsArray<ComponentChange> ComponentChanges { get; }
public bool Empty => ComponentChanges is null;
public bool Empty => ComponentChanges.Value is null or { Count: 0 };
public EntityState(EntityUid uid, ComponentChange[]? changedComponents)
public EntityState(EntityUid uid, NetListAsArray<ComponentChange> changedComponents)
{
Uid = uid;
// empty lists are 5 bytes each
ComponentChanges = changedComponents == null || changedComponents.Length == 0 ? null : changedComponents;
ComponentChanges = changedComponents;
}
}
+5 -4
View File
@@ -2,6 +2,7 @@
using Robust.Shared.Serialization;
using System;
using System.Diagnostics;
using NetSerializer;
using Robust.Shared.Timing;
namespace Robust.Shared.GameStates
@@ -26,7 +27,7 @@ namespace Robust.Shared.GameStates
/// <summary>
/// Constructor!
/// </summary>
public GameState(GameTick fromSequence, GameTick toSequence, uint lastInput, EntityState[]? entities, PlayerState[]? players, EntityUid[]? deletions, GameStateMapData? mapData)
public GameState(GameTick fromSequence, GameTick toSequence, uint lastInput, NetListAsArray<EntityState> entities, NetListAsArray<PlayerState> players, NetListAsArray<EntityUid> deletions, GameStateMapData? mapData)
{
FromSequence = fromSequence;
ToSequence = toSequence;
@@ -42,9 +43,9 @@ namespace Robust.Shared.GameStates
public readonly uint LastProcessedInput;
public readonly EntityState[]? EntityStates;
public readonly PlayerState[]? PlayerStates;
public readonly EntityUid[]? EntityDeletions;
public readonly NetListAsArray<EntityState> EntityStates;
public readonly NetListAsArray<PlayerState> PlayerStates;
public readonly NetListAsArray<EntityUid> EntityDeletions;
public readonly GameStateMapData? MapData;
}
}
@@ -235,7 +235,7 @@ namespace Robust.UnitTesting.Client.GameStates
/// </summary>
private static GameState GameStateFactory(uint from, uint to)
{
return new(new GameTick(@from), new GameTick(to), 0, null, null, null, null);
return new(new GameTick(@from), new GameTick(to), 0, default, default, default, null);
}
/// <summary>