diff --git a/Apex.Serialization/Apex.Serialization.csproj b/Apex.Serialization/Apex.Serialization.csproj index 27bfb88..40e7813 100644 --- a/Apex.Serialization/Apex.Serialization.csproj +++ b/Apex.Serialization/Apex.Serialization.csproj @@ -15,10 +15,11 @@ enable enable true + $(DefineConstants);LIGHT_EXPRESSION - TRACE;DEV + $(DefineConstants);TRACE;DEV @@ -48,6 +49,7 @@ + diff --git a/Apex.Serialization/Binary.Internal.cs b/Apex.Serialization/Binary.Internal.cs index b273fad..d885929 100644 --- a/Apex.Serialization/Binary.Internal.cs +++ b/Apex.Serialization/Binary.Internal.cs @@ -4,7 +4,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq.Expressions; +// using System.Linq.Expressions; +using FastExpressionCompiler.LightExpression; using System.Reflection; namespace Apex.Serialization @@ -455,22 +456,24 @@ public override int GetHashCode() private static Func CreateCloneFunc() { var p = Expression.Parameter(typeof(object)); - return Expression.Lambda>( + var f = Expression.Lambda>( Expression.Call(p, typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)!) , p - ).Compile(); + ).CompileFast(); + return f; } private static Action CreateSetTargetAction() { var p = Expression.Parameter(typeof(Delegate)); var t = Expression.Parameter(typeof(object)); - return Expression.Lambda>( + var f = Expression.Lambda>( Expression.Assign( Expression.MakeMemberAccess(p, typeof(Delegate).GetField("_target", BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.NonPublic)!), t) , p, t - ).Compile(); + ).CompileFast(); + return f; } internal Delegate ReadFunction() diff --git a/Apex.Serialization/Internal/DynamicCode.Arrays.cs b/Apex.Serialization/Internal/DynamicCode.Arrays.cs index b7acae1..164fcea 100644 --- a/Apex.Serialization/Internal/DynamicCode.Arrays.cs +++ b/Apex.Serialization/Internal/DynamicCode.Arrays.cs @@ -3,7 +3,8 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Linq.Expressions; +using static System.Linq.Expressions.ExpressionType; +using FastExpressionCompiler.LightExpression; namespace Apex.Serialization.Internal { @@ -44,7 +45,7 @@ internal static partial class DynamicCode var skipLabel = Expression.Label("skipWrite"); statements.Add( Expression.IfThen( - Expression.Equal(Expression.Constant(0), lengths.Aggregate((Expression)Expression.Empty(), (a,b) => a.NodeType == ExpressionType.Default ? (Expression)b : Expression.Or(a,b))), + Expression.Equal(Expression.Constant(0), lengths.Aggregate((Expression)Expression.Empty(), (a,b) => a.NodeType == Default ? (Expression)b : Expression.Or(a,b))), Expression.Goto(skipLabel) ) ); diff --git a/Apex.Serialization/Internal/DynamicCode.Helpers.cs b/Apex.Serialization/Internal/DynamicCode.Helpers.cs index 6c62e6f..d61e922 100644 --- a/Apex.Serialization/Internal/DynamicCode.Helpers.cs +++ b/Apex.Serialization/Internal/DynamicCode.Helpers.cs @@ -3,7 +3,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; +using FastExpressionCompiler.LightExpression; using System.Reflection; using System.Runtime.InteropServices; using System.Runtime.Serialization; diff --git a/Apex.Serialization/Internal/DynamicCode.cs b/Apex.Serialization/Internal/DynamicCode.cs index a69632e..8585a77 100644 --- a/Apex.Serialization/Internal/DynamicCode.cs +++ b/Apex.Serialization/Internal/DynamicCode.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Linq.Expressions; +using FastExpressionCompiler.LightExpression; using System.Reflection; using System.Threading; using Apex.Serialization.Extensions; @@ -62,7 +62,8 @@ internal static DynamicCodeMethods.GeneratedDelegate GenerateWriteMethodImpl( GetWriteFieldExpression(x, isolatedSource, stream, output, settings, visitedTypes, 0))); var isolatedBody = Expression.Block(writeStatements); - var isolatedLambda = Expression.Lambda(isolatedBody, $"Apex.Serialization.Write_Isolated_{type.FullName}", new[] { isolatedSource, stream, output }).Compile(); + var isolatedLambda = Expression.Lambda(isolatedBody, $"Apex.Serialization.Write_Isolated_{type.FullName}", new[] { isolatedSource, stream, output }) + .CompileFast(); return new DynamicCodeMethods.GeneratedDelegate { Delegate = isolatedLambda, SerializedVersionUniqueId = GetSerializedVersionUniqueId(type, isolatedBody) }; } @@ -93,7 +94,8 @@ internal static DynamicCodeMethods.GeneratedDelegate GenerateWriteMethodImpl( var finalBody = Expression.Block(localVariables, writeStatements); - var lambda = Expression.Lambda(finalBody, $"Apex.Serialization.Write_{type.FullName}", new[] { source, stream, output }).Compile(); + var lambdaExpr = Expression.Lambda(finalBody, $"Apex.Serialization.Write_{type.FullName}", new[] { source, stream, output }); + var lambda = lambdaExpr.CompileFast(); var uniqueId = GetSerializedVersionUniqueId(type, finalBody); @@ -587,7 +589,8 @@ internal static DynamicCodeMethods.GeneratedDelegate GenerateReadMethodImpl(T readStatements.AddRange(isolatedFields.Select(x => GetReadFieldExpression(x, isolatedResult, stream, output, settings, localVariables, visitedTypes, 0))); var isolatedBody = Expression.Block(localVariables, readStatements); - var isolatedLambda = Expression.Lambda(isolatedBody, $"Apex.Serialization.Read_Isolated_{type.FullName}", new[] { isolatedResult, stream, output }).Compile(); + var isolatedLambda = Expression.Lambda(isolatedBody, $"Apex.Serialization.Read_Isolated_{type.FullName}", new[] { isolatedResult, stream, output }) + .CompileFast(); return new DynamicCodeMethods.GeneratedDelegate { Delegate = isolatedLambda, SerializedVersionUniqueId = GetSerializedVersionUniqueId(type, isolatedBody) }; } @@ -613,7 +616,8 @@ internal static DynamicCodeMethods.GeneratedDelegate GenerateReadMethodImpl(T } var finalBody = Expression.Block(localVariables, readStatements); - var lambda = Expression.Lambda(finalBody, $"Apex.Serialization.Read_{type.FullName}", new [] {stream, output}).Compile(); + var lambdaExpr = Expression.Lambda(finalBody, $"Apex.Serialization.Read_{type.FullName}", new [] {stream, output}); + var lambda = lambdaExpr.CompileFast(); return new DynamicCodeMethods.GeneratedDelegate { Delegate = lambda, SerializedVersionUniqueId = GetSerializedVersionUniqueId(type, finalBody) }; } @@ -863,7 +867,7 @@ private static List GetReadStatementsForType(Type type, ImmutableSet Expression.Block( methods.Select(m => AfterDeserializeCallExpression(type, m, objectParameter, contextParameter)) ) - , $"AfterDeserialize_{type.FullName}", new[] {objectParameter, contextParameter}).Compile(); + , $"AfterDeserialize_{type.FullName}", new[] {objectParameter, contextParameter}).CompileFast(); readStatements.Add(Expression.Call(output, QueueAfterDeserializationHook, Expression.Constant(action), result)); diff --git a/Apex.Serialization/Internal/Reflection/FieldInfoModifier.cs b/Apex.Serialization/Internal/Reflection/FieldInfoModifier.cs index 4256ab8..55792ac 100644 --- a/Apex.Serialization/Internal/Reflection/FieldInfoModifier.cs +++ b/Apex.Serialization/Internal/Reflection/FieldInfoModifier.cs @@ -1,6 +1,6 @@ using System; using System.IO; -using System.Linq.Expressions; +using FastExpressionCompiler.LightExpression; using System.Reflection; using System.Security; @@ -47,7 +47,7 @@ static FieldInfoModifier() Expression.Label(returnLabel) ) , fieldInfoParam - ).Compile(); + ).CompileFast(); SetFieldInfoReadonly = (Action)Expression.Lambda( Expression.Block( Expression.Assign(Expression.MakeMemberAccess(castedType, fieldInfo_m_Attributes), @@ -58,7 +58,7 @@ static FieldInfoModifier() Expression.Label(returnLabel) ) , fieldInfoParam - ).Compile(); + ).CompileFast(); var s = Binary.Create(new Settings()); try diff --git a/Apex.Serialization/Internal/Reflection/TypeFields.cs b/Apex.Serialization/Internal/Reflection/TypeFields.cs index a58b074..9fb1330 100644 --- a/Apex.Serialization/Internal/Reflection/TypeFields.cs +++ b/Apex.Serialization/Internal/Reflection/TypeFields.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Linq.Expressions; +using FastExpressionCompiler.LightExpression; using System.Reflection; using System.Runtime.CompilerServices; @@ -23,11 +23,11 @@ static TypeFields() var logicallyNullMethod = typeof(MulticastDelegate).GetMethod("InvocationListLogicallyNull", BindingFlags.Instance | BindingFlags.NonPublic)!; - getInvocationCount = Expression.Lambda>(Expression.Field(delegateParam, "_invocationCount"), delegateParam).Compile(); - getInvocationList = Expression.Lambda>(Expression.Field(delegateParam, "_invocationList"), delegateParam).Compile(); - setInvocationCount = Expression.Lambda>(Expression.Assign(Expression.Field(delegateParam, "_invocationCount"), intPtrParam), delegateParam, intPtrParam).Compile(); - setInvocationList = Expression.Lambda>(Expression.Assign(Expression.Field(delegateParam, "_invocationList"), objectParam), delegateParam, objectParam).Compile(); - getInvocationListLogicallyNull = Expression.Lambda>(Expression.Call(delegateParam, logicallyNullMethod), delegateParam).Compile(); + getInvocationCount = Expression.Lambda>(Expression.Field(delegateParam, "_invocationCount"), delegateParam).CompileFast(); + getInvocationList = Expression.Lambda>(Expression.Field(delegateParam, "_invocationList"), delegateParam).CompileFast(); + setInvocationCount = Expression.Lambda>(Expression.Assign(Expression.Field(delegateParam, "_invocationCount"), intPtrParam), delegateParam, intPtrParam).CompileFast(); + setInvocationList = Expression.Lambda>(Expression.Assign(Expression.Field(delegateParam, "_invocationList"), objectParam), delegateParam, objectParam).CompileFast(); + getInvocationListLogicallyNull = Expression.Lambda>(Expression.Call(delegateParam, logicallyNullMethod), delegateParam).CompileFast(); } private static DictionarySlim> _cache = new DictionarySlim>(); diff --git a/Apex.Serialization/Internal/VersionUniqueIdExpressionVisitor.cs b/Apex.Serialization/Internal/VersionUniqueIdExpressionVisitor.cs index 5929ee5..9240e70 100644 --- a/Apex.Serialization/Internal/VersionUniqueIdExpressionVisitor.cs +++ b/Apex.Serialization/Internal/VersionUniqueIdExpressionVisitor.cs @@ -1,5 +1,5 @@ using System; -using System.Linq.Expressions; +using FastExpressionCompiler.LightExpression; using System.Reflection; namespace Apex.Serialization.Internal @@ -196,7 +196,7 @@ protected override Expression VisitLabel(LabelExpression node) Combine(node.Name); Combine(node.Type); } - return base.VisitLabelTarget(node); + return base.VisitLabelTarget(node!); } protected override Expression VisitLambda(Expression node) @@ -341,7 +341,6 @@ protected override Expression VisitUnary(UnaryExpression node) protected override Expression VisitDebugInfo(DebugInfoExpression node) { Combine(node.Document.FileName); - return base.VisitDebugInfo(node); } } diff --git a/Benchmark/BufferedStream.cs b/Benchmark/BufferedStream.cs index 79ba01b..2816d10 100644 --- a/Benchmark/BufferedStream.cs +++ b/Benchmark/BufferedStream.cs @@ -3,8 +3,7 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq.Expressions; -using System.Text; +using FastExpressionCompiler.LightExpression; using BufferedStream = Apex.Serialization.Internal.BufferedStream; namespace Benchmark @@ -22,8 +21,8 @@ private static writeSig CreateWriteByteMethod() var p = Expression.Parameter(typeof(BufferedStream).MakeByRefType(), "stream"); var b = Expression.Parameter(typeof(byte), "b"); var lambda = Expression.Lambda(Expression.Call(p, BinaryStreamMethods.GenericMethods.WriteValueMethodInfo, b), p, b); - var compiledLamda = lambda.Compile(); - return (writeSig)compiledLamda; + var compiledLambda = lambda.CompileFast(); + return (writeSig)compiledLambda; } [Benchmark] diff --git a/Benchmark/Program.cs b/Benchmark/Program.cs index 717c6de..1ad6f99 100644 --- a/Benchmark/Program.cs +++ b/Benchmark/Program.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.IO; using System.Linq; -using System.Linq.Expressions; +using FastExpressionCompiler.LightExpression; using System.Reflection; using Apex.Serialization; using BenchmarkDotNet.Columns;