using System; using System.Collections.Generic; using Microsoft.Extensions.ObjectPool; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.Utility; using SharpZstd.Interop; namespace Robust.Server.GameStates; // This partial class contains code for pooling objects to avoid allocations. // This file is now blessedly small, so maybe we can just get rid of it. internal sealed partial class PvsSystem { /// /// Maximum number of pooled objects. /// private const int MaxVisPoolSize = 1024; private readonly ObjectPool> _entDataListPool = new DefaultObjectPool>(new ListPolicy(), MaxVisPoolSize); private readonly ObjectPool> _componentChangeListPool = new DefaultObjectPool>(new ListPolicy(), MaxVisPoolSize); private readonly ObjectPool> _uidSetPool = new DefaultObjectPool>(new SetPolicy(), MaxVisPoolSize); private readonly ObjectPool> _netComponentSetPool = new DefaultObjectPool>(new SetPolicy(), MaxVisPoolSize); private readonly ObjectPool _chunkPool = new DefaultObjectPool(new PvsChunkPolicy(), 256); private sealed class PvsChunkPolicy : PooledObjectPolicy { public override PvsChunk Create() { return new PvsChunk(); } public override bool Return(PvsChunk obj) { obj.Wipe(); return true; } } private sealed class PvsThreadResourcesObjectPolicy(int ce) : IPooledObjectPolicy { PvsThreadResources IPooledObjectPolicy.Create() { var res = new PvsThreadResources(); res.CompressionContext.SetParameter(ZSTD_cParameter.ZSTD_c_compressionLevel, ce); return res; } bool IPooledObjectPolicy.Return(PvsThreadResources _) { return true; } } private sealed class PvsThreadResources { public ZStdCompressionContext CompressionContext = new(); ~PvsThreadResources() { CompressionContext.Dispose(); } } private List GetComponentChangeList(int capacity) { var list = _componentChangeListPool.Get(); list.EnsureCapacity(capacity); return list; } private HashSet GetNetComponentSet() { return _netComponentSetPool.Get(); } private void ReturnEntityState(EntityState state) { if (state.ComponentChanges.Value is List changes) _componentChangeListPool.Return(changes); if (state.NetComponents is { } netComps) { _netComponentSetPool.Return(netComps); state.NetComponents = null; } } internal void ClearSessionState(PvsSession session) { foreach (var state in session.States) { ReturnEntityState(state); } session.ClearState(); } }