do not allocate new memory each tick for player info
This commit is contained in:
parent
abad2c95c8
commit
b3bf62b391
|
@ -1,3 +1,5 @@
|
||||||
|
using System.Buffers;
|
||||||
|
using System.IO;
|
||||||
using System.Net.WebSockets;
|
using System.Net.WebSockets;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using TanksServer.GameLogic;
|
using TanksServer.GameLogic;
|
||||||
|
@ -6,11 +8,15 @@ namespace TanksServer.Interactivity;
|
||||||
|
|
||||||
internal sealed class PlayerInfoConnection : WebsocketServerConnection
|
internal sealed class PlayerInfoConnection : WebsocketServerConnection
|
||||||
{
|
{
|
||||||
private int _wantsInfoOnTick = 1;
|
|
||||||
private byte[]? _lastMessage = null;
|
|
||||||
private byte[]? _nextMessage = null;
|
|
||||||
private readonly Player _player;
|
private readonly Player _player;
|
||||||
private readonly MapEntityManager _entityManager;
|
private readonly MapEntityManager _entityManager;
|
||||||
|
private readonly MemoryStream _tempStream = new();
|
||||||
|
private readonly MemoryPool<byte> _memoryPool = MemoryPool<byte>.Shared;
|
||||||
|
private int _wantsInfoOnTick = 1;
|
||||||
|
private Package? _lastMessage = null;
|
||||||
|
private Package? _nextMessage = null;
|
||||||
|
|
||||||
|
private sealed record class Package(IMemoryOwner<byte> Owner, Memory<byte> Memory);
|
||||||
|
|
||||||
public PlayerInfoConnection(Player player,
|
public PlayerInfoConnection(Player player,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
|
@ -36,7 +42,7 @@ internal sealed class PlayerInfoConnection : WebsocketServerConnection
|
||||||
{
|
{
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
|
|
||||||
var response = GetMessageToSend();
|
var response = await GenerateMessageAsync();
|
||||||
var wantsNow = Interlocked.Exchange(ref _wantsInfoOnTick, 0) != 0;
|
var wantsNow = Interlocked.Exchange(ref _wantsInfoOnTick, 0) != 0;
|
||||||
|
|
||||||
if (wantsNow)
|
if (wantsNow)
|
||||||
|
@ -54,7 +60,7 @@ internal sealed class PlayerInfoConnection : WebsocketServerConnection
|
||||||
return ValueTask.CompletedTask;
|
return ValueTask.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] GetMessageToSend()
|
private async ValueTask<Package> GenerateMessageAsync()
|
||||||
{
|
{
|
||||||
var tank = _entityManager.GetCurrentTankOfPlayer(_player);
|
var tank = _entityManager.GetCurrentTankOfPlayer(_player);
|
||||||
|
|
||||||
|
@ -72,13 +78,21 @@ internal sealed class PlayerInfoConnection : WebsocketServerConnection
|
||||||
tankInfo,
|
tankInfo,
|
||||||
_player.OpenConnections);
|
_player.OpenConnections);
|
||||||
|
|
||||||
// TODO: switch to async version with pre-allocated buffer / IMemoryOwner
|
_tempStream.Position = 0;
|
||||||
return JsonSerializer.SerializeToUtf8Bytes(info, AppSerializerContext.Default.PlayerInfo);
|
await JsonSerializer.SerializeAsync(_tempStream, info, AppSerializerContext.Default.PlayerInfo);
|
||||||
|
|
||||||
|
var messageLength = (int)_tempStream.Position;
|
||||||
|
var owner = _memoryPool.Rent(messageLength);
|
||||||
|
var package = new Package(owner, owner.Memory[..messageLength]);
|
||||||
|
|
||||||
|
_tempStream.Position = 0;
|
||||||
|
await _tempStream.ReadExactlyAsync(package.Memory);
|
||||||
|
return package;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async ValueTask SendAndDisposeAsync(byte[] data)
|
private async ValueTask SendAndDisposeAsync(Package data)
|
||||||
{
|
{
|
||||||
await Socket.SendTextAsync(data);
|
await Socket.SendTextAsync(data.Memory);
|
||||||
Interlocked.Exchange(ref _lastMessage, data);
|
Interlocked.Exchange(ref _lastMessage, data)?.Owner.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue