mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
breaking: perf: remove NetworkWriter.Length/SetLength/EnsureLength. Position is enough. (#2731)
* NetworkWriter: obsolete .Length and .SetLength() * breaking: perf: remove NetworkWriter.Length/SetLength/EnsureLength. Position is enough.
This commit is contained in:
parent
e823de74bd
commit
8a4416e3b5
@ -92,7 +92,7 @@ internal void SendBatch(int channelId, Batch batch)
|
|||||||
{
|
{
|
||||||
// flush & reset writer
|
// flush & reset writer
|
||||||
Transport.activeTransport.ServerSend(connectionId, writer.ToArraySegment(), channelId);
|
Transport.activeTransport.ServerSend(connectionId, writer.ToArraySegment(), channelId);
|
||||||
writer.SetLength(0);
|
writer.Position = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now add to writer in any case
|
// now add to writer in any case
|
||||||
@ -114,7 +114,7 @@ internal void SendBatch(int channelId, Batch batch)
|
|||||||
if (writer.Position > 0)
|
if (writer.Position > 0)
|
||||||
{
|
{
|
||||||
Transport.activeTransport.ServerSend(connectionId, writer.ToArraySegment(), channelId);
|
Transport.activeTransport.ServerSend(connectionId, writer.ToArraySegment(), channelId);
|
||||||
writer.SetLength(0);
|
writer.Position = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,61 +24,15 @@ public class NetworkWriter
|
|||||||
// => 1500 bytes by default because on average, most packets will be <= MTU
|
// => 1500 bytes by default because on average, most packets will be <= MTU
|
||||||
byte[] buffer = new byte[1500];
|
byte[] buffer = new byte[1500];
|
||||||
|
|
||||||
// 'int' is the best type for .Position. 'short' is too small if we send >32kb which would result in negative .Position
|
|
||||||
// -> converting long to int is fine until 2GB of data (MAX_INT), so we don't have to worry about overflows here
|
|
||||||
int position;
|
|
||||||
int length;
|
|
||||||
|
|
||||||
/// <summary>Number of bytes writen to the buffer</summary>
|
|
||||||
public int Length => length;
|
|
||||||
|
|
||||||
/// <summary>Next position to write to the buffer</summary>
|
/// <summary>Next position to write to the buffer</summary>
|
||||||
public int Position
|
public int Position;
|
||||||
{
|
|
||||||
get => position;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
position = value;
|
|
||||||
EnsureLength(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Reset both the position and length of the stream</summary>
|
/// <summary>Reset both the position and length of the stream</summary>
|
||||||
// Leaves the capacity the same so that we can reuse this writer without
|
// Leaves the capacity the same so that we can reuse this writer without
|
||||||
// extra allocations
|
// extra allocations
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
position = 0;
|
Position = 0;
|
||||||
length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Sets length, moves position if it is greater than new length</summary>
|
|
||||||
/// Zeros out any extra length created by setlength
|
|
||||||
public void SetLength(int newLength)
|
|
||||||
{
|
|
||||||
int oldLength = length;
|
|
||||||
|
|
||||||
// ensure length & capacity
|
|
||||||
EnsureLength(newLength);
|
|
||||||
|
|
||||||
// zero out new length
|
|
||||||
if (oldLength < newLength)
|
|
||||||
{
|
|
||||||
Array.Clear(buffer, oldLength, newLength - oldLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
length = newLength;
|
|
||||||
position = Mathf.Min(position, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
void EnsureLength(int value)
|
|
||||||
{
|
|
||||||
if (length < value)
|
|
||||||
{
|
|
||||||
length = value;
|
|
||||||
EnsureCapacity(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@ -91,33 +45,33 @@ void EnsureCapacity(int value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Copies buffer to new array of size 'Length'. Ignores 'Position'.</summary>
|
/// <summary>Copies buffer until 'Position' to a new array.</summary>
|
||||||
public byte[] ToArray()
|
public byte[] ToArray()
|
||||||
{
|
{
|
||||||
byte[] data = new byte[length];
|
byte[] data = new byte[Position];
|
||||||
Array.ConstrainedCopy(buffer, 0, data, 0, length);
|
Array.ConstrainedCopy(buffer, 0, data, 0, Position);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Returns allocatin-free ArraySegment which points to buffer up to 'Length' (ignores 'Position').</summary>
|
/// <summary>Returns allocation-free ArraySegment until 'Position'.</summary>
|
||||||
public ArraySegment<byte> ToArraySegment()
|
public ArraySegment<byte> ToArraySegment()
|
||||||
{
|
{
|
||||||
return new ArraySegment<byte>(buffer, 0, length);
|
return new ArraySegment<byte>(buffer, 0, Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteByte(byte value)
|
public void WriteByte(byte value)
|
||||||
{
|
{
|
||||||
EnsureLength(position + 1);
|
EnsureCapacity(Position + 1);
|
||||||
buffer[position++] = value;
|
buffer[Position++] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for byte arrays with consistent size, where the reader knows how many to read
|
// for byte arrays with consistent size, where the reader knows how many to read
|
||||||
// (like a packet opcode that's always the same)
|
// (like a packet opcode that's always the same)
|
||||||
public void WriteBytes(byte[] buffer, int offset, int count)
|
public void WriteBytes(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
EnsureLength(position + count);
|
EnsureCapacity(Position + count);
|
||||||
Array.ConstrainedCopy(buffer, offset, this.buffer, position, count);
|
Array.ConstrainedCopy(buffer, offset, this.buffer, Position, count);
|
||||||
position += count;
|
Position += count;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Writes any type that mirror supports. Uses weaver populated Writer(T).write.</summary>
|
/// <summary>Writes any type that mirror supports. Uses weaver populated Writer(T).write.</summary>
|
||||||
|
@ -52,7 +52,7 @@ public void ByteIsSentForByteEnum()
|
|||||||
writer.Write(msg);
|
writer.Write(msg);
|
||||||
|
|
||||||
// should be 1 byte for data
|
// should be 1 byte for data
|
||||||
Assert.That(writer.Length, Is.EqualTo(1));
|
Assert.That(writer.Position, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -64,7 +64,7 @@ public void ShortIsSentForShortEnum()
|
|||||||
writer.Write(msg);
|
writer.Write(msg);
|
||||||
|
|
||||||
// should be 2 bytes for data
|
// should be 2 bytes for data
|
||||||
Assert.That(writer.Length, Is.EqualTo(2));
|
Assert.That(writer.Position, Is.EqualTo(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -58,7 +58,7 @@ public void SendsVauesInParentAndChildClass()
|
|||||||
Assert.AreEqual(3, received.parentValue);
|
Assert.AreEqual(3, received.parentValue);
|
||||||
Assert.AreEqual(4, received.childValue);
|
Assert.AreEqual(4, received.childValue);
|
||||||
|
|
||||||
int writeLength = writer.Length;
|
int writeLength = writer.Position;
|
||||||
int readLength = reader.Position;
|
int readLength = reader.Position;
|
||||||
Assert.That(writeLength == readLength, $"OnSerializeAll and OnDeserializeAll calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
Assert.That(writeLength == readLength, $"OnSerializeAll and OnDeserializeAll calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ public void SendsVauesWhenUsingAbstractClass()
|
|||||||
Assert.AreEqual(message, received.message);
|
Assert.AreEqual(message, received.message);
|
||||||
Assert.AreEqual(responseId, received.responseId);
|
Assert.AreEqual(responseId, received.responseId);
|
||||||
|
|
||||||
int writeLength = writer.Length;
|
int writeLength = writer.Position;
|
||||||
int readLength = reader.Position;
|
int readLength = reader.Position;
|
||||||
Assert.That(writeLength == readLength, $"OnSerializeAll and OnDeserializeAll calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
Assert.That(writeLength == readLength, $"OnSerializeAll and OnDeserializeAll calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ public void SendsVauesWhenUsingAbstractClassReverseDefineOrder()
|
|||||||
Assert.AreEqual(message, received.message);
|
Assert.AreEqual(message, received.message);
|
||||||
Assert.AreEqual(responseId, received.responseId);
|
Assert.AreEqual(responseId, received.responseId);
|
||||||
|
|
||||||
int writeLength = writer.Length;
|
int writeLength = writer.Position;
|
||||||
int readLength = reader.Position;
|
int readLength = reader.Position;
|
||||||
Assert.That(writeLength == readLength, $"OnSerializeAll and OnDeserializeAll calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
Assert.That(writeLength == readLength, $"OnSerializeAll and OnDeserializeAll calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
||||||
}
|
}
|
||||||
|
@ -104,36 +104,6 @@ public void TestWritingSegmentAndReadingSegment()
|
|||||||
Assert.That(deserialized.Array[deserialized.Offset + i], Is.EqualTo(segment.Array[segment.Offset + i]));
|
Assert.That(deserialized.Array[deserialized.Offset + i], Is.EqualTo(segment.Array[segment.Offset + i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestSetLengthZeroes()
|
|
||||||
{
|
|
||||||
NetworkWriter writer = new NetworkWriter();
|
|
||||||
writer.WriteString("I saw");
|
|
||||||
writer.WriteInt64(0xA_FADED_DEAD_EEL);
|
|
||||||
writer.WriteString("and ate it");
|
|
||||||
int position = writer.Position;
|
|
||||||
|
|
||||||
writer.SetLength(10);
|
|
||||||
Assert.That(writer.Position, Is.EqualTo(10), "Decreasing length should move position");
|
|
||||||
|
|
||||||
// lets grow it back and check there's zeroes now.
|
|
||||||
writer.SetLength(position);
|
|
||||||
byte[] data = writer.ToArray();
|
|
||||||
for (int i = 10; i < data.Length; i++)
|
|
||||||
{
|
|
||||||
Assert.That(data[i], Is.EqualTo(0), $"index {i} should have value 0");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestSetLengthInitialization()
|
|
||||||
{
|
|
||||||
NetworkWriter writer = new NetworkWriter();
|
|
||||||
|
|
||||||
writer.SetLength(10);
|
|
||||||
Assert.That(writer.Position, Is.EqualTo(0), "Increasing length should not move position");
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestResetSetsPotionAndLength()
|
public void TestResetSetsPotionAndLength()
|
||||||
{
|
{
|
||||||
@ -144,7 +114,6 @@ public void TestResetSetsPotionAndLength()
|
|||||||
writer.Reset();
|
writer.Reset();
|
||||||
|
|
||||||
Assert.That(writer.Position, Is.EqualTo(0));
|
Assert.That(writer.Position, Is.EqualTo(0));
|
||||||
Assert.That(writer.Length, Is.EqualTo(0));
|
|
||||||
|
|
||||||
byte[] data = writer.ToArray();
|
byte[] data = writer.ToArray();
|
||||||
Assert.That(data, Is.Empty);
|
Assert.That(data, Is.Empty);
|
||||||
|
@ -28,7 +28,7 @@ public void SerializeAreAddedWhenEmptyInStruct()
|
|||||||
|
|
||||||
Assert.AreEqual(someValue, received.someValue);
|
Assert.AreEqual(someValue, received.someValue);
|
||||||
|
|
||||||
int writeLength = writer.Length;
|
int writeLength = writer.Position;
|
||||||
int readLength = reader.Position;
|
int readLength = reader.Position;
|
||||||
Assert.That(writeLength == readLength, $"OnSerializeAll and OnDeserializeAll calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
Assert.That(writeLength == readLength, $"OnSerializeAll and OnDeserializeAll calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ public static void SerializeAllTo<T>(T fromList, T toList) where T : SyncObject
|
|||||||
NetworkReader reader = new NetworkReader(writer.ToArray());
|
NetworkReader reader = new NetworkReader(writer.ToArray());
|
||||||
toList.OnDeserializeAll(reader);
|
toList.OnDeserializeAll(reader);
|
||||||
|
|
||||||
int writeLength = writer.Length;
|
int writeLength = writer.Position;
|
||||||
int readLength = reader.Position;
|
int readLength = reader.Position;
|
||||||
Assert.That(writeLength == readLength, $"OnSerializeAll and OnDeserializeAll calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
Assert.That(writeLength == readLength, $"OnSerializeAll and OnDeserializeAll calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ public static void SerializeDeltaTo<T>(T fromList, T toList) where T : SyncObjec
|
|||||||
toList.OnDeserializeDelta(reader);
|
toList.OnDeserializeDelta(reader);
|
||||||
fromList.Flush();
|
fromList.Flush();
|
||||||
|
|
||||||
int writeLength = writer.Length;
|
int writeLength = writer.Position;
|
||||||
int readLength = reader.Position;
|
int readLength = reader.Position;
|
||||||
Assert.That(writeLength == readLength, $"OnSerializeDelta and OnDeserializeDelta calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
Assert.That(writeLength == readLength, $"OnSerializeDelta and OnDeserializeDelta calls write the same amount of data\n writeLength={writeLength}\n readLength={readLength}");
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ public static bool ServerWrite<T>(T serverObject, bool initialState, out ArraySe
|
|||||||
{
|
{
|
||||||
NetworkWriter writer = new NetworkWriter();
|
NetworkWriter writer = new NetworkWriter();
|
||||||
bool written = serverObject.OnSerialize(writer, initialState);
|
bool written = serverObject.OnSerialize(writer, initialState);
|
||||||
writeLength = writer.Length;
|
writeLength = writer.Position;
|
||||||
data = writer.ToArraySegment();
|
data = writer.ToArraySegment();
|
||||||
|
|
||||||
return written;
|
return written;
|
||||||
|
Loading…
Reference in New Issue
Block a user