Add SerializeDirect/DeserializeDirect to IRobustSerializer.

This matches the NetSerializer API to skip initial type IDs which is a bit more efficient.

Also made RobustSerializer thread safe.
This commit is contained in:
Pieter-Jan Briers
2020-07-29 19:24:12 +02:00
parent 0b302b5171
commit 028453acee
2 changed files with 94 additions and 15 deletions

View File

@@ -9,7 +9,31 @@ namespace Robust.Shared.Interfaces.Serialization
{
void Initialize();
void Serialize(Stream stream, object toSerialize);
/// <summary>
/// Serializes an object with exact known type to skip a type ID header.
/// </summary>
/// <remarks>
/// This is more efficient than <see cref="Serialize"/> because it does not use a few bytes on type ID header.
/// Output from this method is not compatible with <see cref="Deserialize"/> or vice versa.
/// The type argument of the <see cref="DeserializeDirect{T}"/> call must also match, obviously.
/// </remarks>
/// <param name="stream">The stream to write into.</param>
/// <param name="toSerialize">
/// The object to serialize.
/// The object MUST have the exact type of <typeparamref name="T"/>
/// </param>
/// <typeparam name="T">The type of object to serialize.</typeparam>
void SerializeDirect<T>(Stream stream, T toSerialize);
T Deserialize<T>(Stream stream);
/// <summary>
/// Deserialize side of <see cref="DeserializeDirect{T}"/>.
/// </summary>
/// <param name="stream">Stream to read from.</param>
/// <param name="value">Value that was deserialized.</param>
/// <typeparam name="T">Exact type of object to deserialize.</typeparam>
void DeserializeDirect<T>(Stream stream, out T value);
object Deserialize(Stream stream);
bool CanSerialize(Type type);

View File

@@ -7,10 +7,10 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Loader;
using Lidgren.Network;
using Robust.Shared.Interfaces.Log;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Log;
using Robust.Shared.Utility;
namespace Robust.Shared.Serialization
{
@@ -34,6 +34,8 @@ namespace Robust.Shared.Serialization
#region Statistics
private readonly object _statsLock = new object();
public static long LargestObjectSerializedBytes { get; private set; }
public static Type? LargestObjectSerializedType { get; private set; }
@@ -121,37 +123,90 @@ namespace Robust.Shared.Serialization
_serializer.Serialize(stream, toSerialize);
var end = stream.Position;
var byteCount = end - start;
BytesSerialized += byteCount;
++ObjectsSerialized;
if (byteCount <= LargestObjectSerializedBytes)
lock (_statsLock)
{
return;
}
BytesSerialized += byteCount;
++ObjectsSerialized;
LargestObjectSerializedBytes = byteCount;
LargestObjectSerializedType = toSerialize.GetType();
if (byteCount <= LargestObjectSerializedBytes)
{
return;
}
LargestObjectSerializedBytes = byteCount;
LargestObjectSerializedType = toSerialize.GetType();
}
}
public void SerializeDirect<T>(Stream stream, T toSerialize)
{
DebugTools.Assert(toSerialize == null || typeof(T) == toSerialize.GetType(),
"Object must be of exact type specified in the generic parameter.");
var start = stream.Position;
_serializer.SerializeDirect(stream, toSerialize);
var end = stream.Position;
var byteCount = end - start;
lock (_statsLock)
{
BytesSerialized += byteCount;
++ObjectsSerialized;
if (byteCount <= LargestObjectSerializedBytes)
{
return;
}
LargestObjectSerializedBytes = byteCount;
LargestObjectSerializedType = typeof(T);
}
}
public T Deserialize<T>(Stream stream)
=> (T) Deserialize(stream);
public void DeserializeDirect<T>(Stream stream, out T value)
{
var start = stream.Position;
_serializer.DeserializeDirect(stream, out value);
var end = stream.Position;
var byteCount = end - start;
lock (_statsLock)
{
BytesDeserialized += byteCount;
++ObjectsDeserialized;
if (byteCount > LargestObjectDeserializedBytes)
{
LargestObjectDeserializedBytes = byteCount;
LargestObjectDeserializedType = typeof(T);
}
}
}
public object Deserialize(Stream stream)
{
var start = stream.Position;
var result = _serializer.Deserialize(stream);
var end = stream.Position;
var byteCount = end - start;
BytesDeserialized += byteCount;
++ObjectsDeserialized;
if (byteCount <= LargestObjectDeserializedBytes)
lock (_statsLock)
{
return result;
}
BytesDeserialized += byteCount;
++ObjectsDeserialized;
LargestObjectDeserializedBytes = byteCount;
LargestObjectDeserializedType = result.GetType();
if (byteCount <= LargestObjectDeserializedBytes)
{
return result;
}
LargestObjectDeserializedBytes = byteCount;
LargestObjectDeserializedType = result.GetType();
}
return result;
}