Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor PVS stuff #4573

Merged
merged 5 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 45 additions & 23 deletions Robust.Server/GameStates/PvsSystem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -271,6 +272,7 @@ private void OnEntityDeleted(EntityUid e, MetaDataComponent metadata)
{
sessionData.LastSeenAt.Remove(metadata.NetEntity);
sessionData.LastLeftView.Remove(metadata.NetEntity);

if (sessionData.SentEntities.TryGetValue(previousTick, out var ents))
ents.Remove(metadata.NetEntity);
}
Expand Down Expand Up @@ -433,10 +435,15 @@ private void OnMapCreated(MapChangedEvent e)

#endregion

public (List<(int, IChunkIndexLocation)> , HashSet<int>[], EntityUid[][] viewers) GetChunks(ICommonSession[] sessions)
public List<(int, IChunkIndexLocation)> GetChunks(
ICommonSession[] sessions,
ref HashSet<int>[] playerChunks,
ref EntityUid[][] viewerEntities)
{
var playerChunks = new HashSet<int>[sessions.Length];
var viewerEntities = new EntityUid[sessions.Length][];
// Pass these in to avoid allocating new ones every tick, 99% of the time sessions length is going to be the same size.
// These values will get overridden here and the old values have already been returned to the pool by this point.
Array.Resize(ref playerChunks, sessions.Length);
Array.Resize(ref viewerEntities, sessions.Length);

_chunkList.Clear();
// Keep track of the index of each chunk we use for a faster index lookup.
Expand All @@ -459,8 +466,8 @@ private void OnMapCreated(MapChangedEvent e)
var session = sessions[i];
playerChunks[i] = _playerChunkPool.Get();

var viewers = GetSessionViewers(session);
viewerEntities[i] = viewers;
ref var viewers = ref viewerEntities[i];
GetSessionViewers(session, ref viewers);

for (var j = 0; j < viewers.Length; j++)
{
Expand Down Expand Up @@ -552,7 +559,7 @@ private void OnMapCreated(MapChangedEvent e)
}
}

return (_chunkList, playerChunks, viewerEntities);
return _chunkList;
}

public void RegisterNewPreviousChunkTrees(
Expand All @@ -569,23 +576,20 @@ public void RegisterNewPreviousChunkTrees(
_reusedTrees.Add(chunks[i]);
}

var previousIndices = _previousTrees.Keys.ToArray();
for (var i = 0; i < previousIndices.Length; i++)
foreach (var (index, chunk) in _previousTrees)
{
var index = previousIndices[i];
// ReSharper disable once InconsistentlySynchronizedField
if (_reusedTrees.Contains(index)) continue;
var chunk = _previousTrees[index];
if (chunk.HasValue)
if (_reusedTrees.Contains(index))
continue;

if (chunk != null)
{
_chunkCachePool.Return(chunk.Value.metadata);
_treePool.Return(chunk.Value.tree);
}

if (!chunks.Contains(index))
{
_previousTrees.Remove(index);
}
}

_previousTrees.EnsureCapacity(chunks.Count);
Expand Down Expand Up @@ -1313,26 +1317,44 @@ private EntityState GetFullEntityState(ICommonSession player, EntityUid entityUi
return entState;
}

private EntityUid[] GetSessionViewers(ICommonSession session)
private void GetSessionViewers(ICommonSession session, [NotNull] ref EntityUid[]? viewers)
{
if (session.Status != SessionStatus.InGame)
return Array.Empty<EntityUid>();
{
viewers = Array.Empty<EntityUid>();
return;
}

// Fast path
if (session.ViewSubscriptions.Count == 0)
{
if (session.AttachedEntity == null)
return Array.Empty<EntityUid>();
{
viewers = Array.Empty<EntityUid>();
return;
}

return new[] { session.AttachedEntity.Value };
Array.Resize(ref viewers, 1);
viewers[0] = session.AttachedEntity.Value;
return;
}

var viewers = new HashSet<EntityUid>();
if (session.AttachedEntity != null)
viewers.Add(session.AttachedEntity.Value);
int i = 0;
if (session.AttachedEntity is { } local)
{
DebugTools.Assert(!session.ViewSubscriptions.Contains(local));
Array.Resize(ref viewers, session.ViewSubscriptions.Count + 1);
viewers[i++] = local;
}
else
{
Array.Resize(ref viewers, session.ViewSubscriptions.Count);
}

viewers.UnionWith(session.ViewSubscriptions);
return viewers.ToArray();
foreach (var ent in session.ViewSubscriptions)
{
viewers[i++] = ent;
}
}

// Read Safe
Expand Down
9 changes: 6 additions & 3 deletions Robust.Server/GameStates/ServerGameStateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ public sealed class ServerGameStateManager : IServerGameStateManager, IPostInjec
// Mapping of net UID of clients -> last known acked state.
private GameTick _lastOldestAck = GameTick.Zero;

private HashSet<int>[] _playerChunks = Array.Empty<HashSet<int>>();
private EntityUid[][] _viewerEntities = Array.Empty<EntityUid[]>();

private PvsSystem _pvs = default!;

[Dependency] private readonly EntityManager _entityManager = default!;
Expand Down Expand Up @@ -267,7 +270,7 @@ private struct PvsData

private PvsData? GetPVSData(ICommonSession[] players)
{
var (chunks, playerChunks, viewerEntities) = _pvs.GetChunks(players);
var chunks= _pvs.GetChunks(players, ref _playerChunks, ref _viewerEntities);
const int ChunkBatchSize = 2;
var chunksCount = chunks.Count;
var chunkBatches = (int)MathF.Ceiling((float)chunksCount / ChunkBatchSize);
Expand Down Expand Up @@ -310,8 +313,8 @@ private struct PvsData
ArrayPool<bool>.Shared.Return(reuse);
return new PvsData()
{
PlayerChunks = playerChunks,
ViewerEntities = viewerEntities,
PlayerChunks = _playerChunks,
ViewerEntities = _viewerEntities,
ChunkCache = chunkCache,
};
}
Expand Down