Files
RobustToolbox/Robust.Shared/Serialization/Manager/SerializationManager.FlagsAndConstants.cs
T
DrSmugleafandGitHub 2a349eb023 Optimize serialization reading, create benchmarks (#1679)
* Add Robust.Benchmarks and read string benchmark

* Separate serialization manager methods, use compiled lambdas to call manager read

4 us > 200 ns

* Add int and data definition with string benchmarks

* Make serialization population use expressions to create definitions

* Make benchmark classes internal and create seed data definition

* Add complex data definition read benchmark

* Create primitive serializers, remove primitive special case

|                 Method |        Mean |     Error |    StdDev |
|----------------------- |------------:|----------:|----------:|
|             ReadString |    227.1 ns |   4.47 ns |   5.65 ns |
|            ReadInteger |    245.4 ns |   4.82 ns |   6.26 ns |
|  ReadDataDefWithString |    804.7 ns |  15.27 ns |  16.34 ns |
| ReadSeedDataDefinition | 15,846.8 ns | 312.89 ns | 773.39 ns |

* Remove testing code

* Setup delegates during initialize

* Revert "Setup delegates during initialize"

This reverts commit 7ff4d4eaaa.

* Store delegates in a concurrent dictionary because I really cannot be arsed to generate them on initialize at this point
2021-04-05 14:50:33 +02:00

78 lines
2.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Robust.Shared.Serialization.Manager
{
public partial class SerializationManager
{
private readonly Dictionary<Type, Type> _constantsMapping = new();
private readonly Dictionary<Type, Type> _flagsMapping = new();
private void InitializeFlagsAndConstants()
{
foreach (Type constType in _reflectionManager.FindTypesWithAttribute<ConstantsForAttribute>())
{
if (!constType.IsEnum)
{
throw new InvalidOperationException($"Could not create ConstantMapping for non-enum {constType}.");
}
if (Enum.GetUnderlyingType(constType) != typeof(int))
{
throw new InvalidOperationException($"Could not create ConstantMapping for non-int enum {constType}.");
}
foreach (var constantsForAttribute in constType.GetCustomAttributes<ConstantsForAttribute>(true))
{
if (_constantsMapping.ContainsKey(constantsForAttribute.Tag))
{
throw new NotSupportedException($"Multiple constant enums declared for the tag {constantsForAttribute.Tag}.");
}
_constantsMapping.Add(constantsForAttribute.Tag, constType);
}
}
foreach (var bitflagType in _reflectionManager.FindTypesWithAttribute<FlagsForAttribute>())
{
if (!bitflagType.IsEnum)
{
throw new InvalidOperationException($"Could not create FlagSerializer for non-enum {bitflagType}.");
}
if (Enum.GetUnderlyingType(bitflagType) != typeof(int))
{
throw new InvalidOperationException($"Could not create FlagSerializer for non-int enum {bitflagType}.");
}
if (!bitflagType.GetCustomAttributes<FlagsAttribute>(false).Any())
{
throw new InvalidOperationException($"Could not create FlagSerializer for non-bitflag enum {bitflagType}.");
}
foreach (var flagType in bitflagType.GetCustomAttributes<FlagsForAttribute>(true))
{
if (_flagsMapping.ContainsKey(flagType.Tag))
{
throw new NotSupportedException($"Multiple bitflag enums declared for the tag {flagType.Tag}.");
}
_flagsMapping.Add(flagType.Tag, bitflagType);
}
}
}
public Type GetFlagTypeFromTag(Type tagType)
{
return _flagsMapping[tagType];
}
public Type GetConstantTypeFromTag(Type tagType)
{
return _constantsMapping[tagType];
}
}
}