mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-16 07:12:27 +02:00
* Create serialization copy benchmark * Optimize copy generic method call Before | Method | Mean | Error | StdDev | Median | |----------------------------------- |-------------:|-----------:|-----------:|-------------:| | CreateCopyString | 43.54 ns | 0.918 ns | 0.859 ns | 43.74 ns | | CreateCopyInteger | 19.33 ns | 0.388 ns | 0.860 ns | 19.24 ns | | CreateCopyDataDefinitionWithString | 3,971.42 ns | 78.974 ns | 213.512 ns | 3,902.54 ns | | CreateCopySeedDataDefinition | 49,916.69 ns | 264.992 ns | 221.280 ns | 49,950.53 ns | After | Method | Mean | Error | StdDev | |----------------------------------- |-------------:|-----------:|-----------:| | CreateCopyString | 43.15 ns | 0.917 ns | 1.766 ns | | CreateCopyInteger | 17.91 ns | 0.366 ns | 0.305 ns | | CreateCopyDataDefinitionWithString | 544.20 ns | 8.137 ns | 7.611 ns | | CreateCopySeedDataDefinition | 18,233.34 ns | 357.861 ns | 397.761 ns | * Change populate delegate to use IL | Method | Mean | Error | StdDev | |----------------------------- |------------:|----------:|----------:| | ReadString | 190.7 ns | 3.48 ns | 5.63 ns | | ReadInteger | 218.8 ns | 4.29 ns | 6.01 ns | | ReadDataDefinitionWithString | 677.5 ns | 13.34 ns | 24.06 ns | | ReadSeedDataDefinition | 11,067.0 ns | 219.19 ns | 260.93 ns | | Method | Mean | Error | StdDev | |----------------------------------- |-------------:|-----------:|-----------:| | CreateCopyString | 42.69 ns | 0.926 ns | 1.414 ns | | CreateCopyInteger | 18.02 ns | 0.268 ns | 0.237 ns | | CreateCopyDataDefinitionWithString | 556.80 ns | 11.206 ns | 21.589 ns | | CreateCopySeedDataDefinition | 13,797.07 ns | 256.011 ns | 367.163 ns | * Make copying use IL to get values | Method | Mean | Error | StdDev | |------------------------------------- |------------:|-----------:|-----------:| | CreateCopyString | 42.55 ns | 0.889 ns | 1.357 ns | | CreateCopyInteger | 18.72 ns | 0.394 ns | 0.740 ns | | CreateCopyDataDefinitionWithString | 398.98 ns | 7.853 ns | 12.682 ns | | CreateCopySeedDataDefinition | 5,996.60 ns | 118.724 ns | 181.304 ns | | BaselineCreateCopySeedDataDefinition | 340.85 ns | 6.811 ns | 12.281 ns | * Rest in peace the fast path For now * Fix serialization copying not passing the target ref properly * Fix field assigners for structs
192 lines
5.3 KiB
C#
192 lines
5.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Reflection.Emit;
|
|
|
|
namespace Robust.Shared.Utility
|
|
{
|
|
public static class ILGeneratorExt
|
|
{
|
|
public static RobustILGenerator GetRobustGen(this DynamicMethod dynamicMethod) =>
|
|
new(dynamicMethod.GetILGenerator());
|
|
public static RobustILGenerator GetRobustGen(this ILGenerator generator) => new (generator);
|
|
|
|
}
|
|
|
|
public class RobustILGenerator
|
|
{
|
|
private ILGenerator _generator;
|
|
private List<(object, object?)> _log = new();
|
|
private List<(Type, int)> _locals = new();
|
|
|
|
public RobustILGenerator(ILGenerator generator)
|
|
{
|
|
_generator = generator;
|
|
}
|
|
|
|
public string[] GetStringLog()
|
|
{
|
|
var full = _locals.Select(e => $"LOCAL: {e.Item1} at {e.Item2}").ToList();
|
|
full.Add("===== CODE =====");
|
|
full.AddRange(_log.Select(e => $"{e.Item1} - {e.Item2}"));
|
|
return full.ToArray();
|
|
}
|
|
|
|
private void Log(object opcode, object? arg = null)
|
|
{
|
|
_log.Add((opcode, arg));
|
|
}
|
|
|
|
public virtual LocalBuilder DeclareLocal(Type localType)
|
|
{
|
|
return DeclareLocal(localType, false);
|
|
}
|
|
|
|
public virtual LocalBuilder DeclareLocal(Type localType, bool pinned)
|
|
{
|
|
var loc = _generator.DeclareLocal(localType, pinned);
|
|
_locals.Add((localType, loc.LocalIndex));
|
|
return loc;
|
|
}
|
|
|
|
public virtual void ThrowException([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type excType)
|
|
{
|
|
//this just calls emit
|
|
_generator.ThrowException(excType);
|
|
}
|
|
|
|
public virtual Label DefineLabel()
|
|
{
|
|
var label = _generator.DefineLabel();
|
|
//Log("DefineLabel", label);
|
|
return label;
|
|
}
|
|
|
|
public virtual void MarkLabel(Label loc)
|
|
{
|
|
_generator.MarkLabel(loc);
|
|
Log("MarkLabel", loc.GetHashCode());
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode)
|
|
{
|
|
_generator.Emit(opcode);
|
|
Log(opcode);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, byte arg)
|
|
{
|
|
_generator.Emit(opcode, arg);
|
|
Log(opcode, arg);
|
|
}
|
|
|
|
public void Emit(OpCode opcode, sbyte arg)
|
|
{
|
|
_generator.Emit(opcode, arg);
|
|
Log(opcode, arg);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, short arg)
|
|
{
|
|
_generator.Emit(opcode, arg);
|
|
Log(opcode, arg);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, int arg)
|
|
{
|
|
_generator.Emit(opcode, arg);
|
|
Log(opcode, arg);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, MethodInfo meth)
|
|
{
|
|
_generator.Emit(opcode, meth);
|
|
Log(opcode, meth);
|
|
}
|
|
|
|
// public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention,
|
|
// Type? returnType, Type[]? parameterTypes, Type[]? optionalParameterTypes)
|
|
// {
|
|
// }
|
|
//
|
|
// public virtual void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type? returnType, Type[]? parameterTypes)
|
|
// {
|
|
// }
|
|
//
|
|
|
|
public virtual void EmitCall(OpCode opcode, MethodInfo methodInfo, params Type[]? optionalParameterTypes)
|
|
{
|
|
_generator.EmitCall(opcode, methodInfo, optionalParameterTypes);
|
|
Log(opcode, methodInfo);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, SignatureHelper signature)
|
|
{
|
|
_generator.Emit(opcode, signature);
|
|
Log(opcode, signature);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, ConstructorInfo con)
|
|
{
|
|
_generator.Emit(opcode, con);
|
|
Log(opcode, con);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, Type cls)
|
|
{
|
|
_generator.Emit(opcode, cls);
|
|
Log(opcode, cls);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, long arg)
|
|
{
|
|
_generator.Emit(opcode, arg);
|
|
Log(opcode, arg);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, float arg)
|
|
{
|
|
_generator.Emit(opcode, arg);
|
|
Log(opcode, arg);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, double arg)
|
|
{
|
|
_generator.Emit(opcode, arg);
|
|
Log(opcode, arg);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, Label label)
|
|
{
|
|
_generator.Emit(opcode, label);
|
|
Log(opcode, label.GetHashCode());
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, Label[] labels)
|
|
{
|
|
_generator.Emit(opcode, labels);
|
|
Log(opcode, labels);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, FieldInfo field)
|
|
{
|
|
_generator.Emit(opcode, field);
|
|
Log(opcode, field);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, string str)
|
|
{
|
|
_generator.Emit(opcode, str);
|
|
Log(opcode, str);
|
|
}
|
|
|
|
public virtual void Emit(OpCode opcode, LocalBuilder local)
|
|
{
|
|
_generator.Emit(opcode, local);
|
|
Log(opcode, local);
|
|
}
|
|
}
|
|
}
|