From fbf6f45b11f6e73953d8a2ec1800c2b1f58c7e1f Mon Sep 17 00:00:00 2001 From: RoosterDragon Date: Wed, 11 Jan 2017 21:11:56 +0000 Subject: [PATCH] Avoid boxing Booleans when dumping sync traits. We can return the resulting strings directly. --- OpenRA.Game/Network/SyncReport.cs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/OpenRA.Game/Network/SyncReport.cs b/OpenRA.Game/Network/SyncReport.cs index 48cdecc2ad..e1f45c9d55 100644 --- a/OpenRA.Game/Network/SyncReport.cs +++ b/OpenRA.Game/Network/SyncReport.cs @@ -166,8 +166,10 @@ namespace OpenRA.Network struct TypeInfo { - static ParameterExpression syncParam = Expression.Parameter(typeof(ISync), "sync"); - static ConstantExpression nullString = Expression.Constant(null, typeof(string)); + static readonly ParameterExpression SyncParam = Expression.Parameter(typeof(ISync), "sync"); + static readonly ConstantExpression NullString = Expression.Constant(null, typeof(string)); + static readonly ConstantExpression TrueString = Expression.Constant(bool.TrueString, typeof(string)); + static readonly ConstantExpression FalseString = Expression.Constant(bool.FalseString, typeof(string)); public readonly Func[] SerializableCopyOfMemberFunctions; public readonly string[] Names; @@ -184,7 +186,7 @@ namespace OpenRA.Network "Properties using the Sync attribute must be readable and must not use index parameters.\n" + "Invalid Property: " + prop.DeclaringType.FullName + "." + prop.Name); - var sync = Expression.Convert(syncParam, type); + var sync = Expression.Convert(SyncParam, type); SerializableCopyOfMemberFunctions = fields .Select(fi => SerializableCopyOfMember(Expression.Field(sync, fi), fi.FieldType, fi.Name)) .Concat(properties.Select(pi => SerializableCopyOfMember(Expression.Property(sync, pi), pi.PropertyType, pi.Name))) @@ -203,8 +205,16 @@ namespace OpenRA.Network // just box a copy of the current value into an object. This is faster than calling ToString. We // can call ToString later when we generate the report. Most of the time, the sync report is never // generated so we successfully avoid the overhead to calling ToString. + if (memberType == typeof(bool)) + { + // PERF: If the member is a Boolean, we can also avoid the allocation caused by boxing it. + // Instead, we can just return the resulting strings directly. + var getBoolString = Expression.Condition(getMember, TrueString, FalseString); + return Expression.Lambda>(getBoolString, name, new[] { SyncParam }).Compile(); + } + var boxedCopy = Expression.Convert(getMember, typeof(object)); - return Expression.Lambda>(boxedCopy, name, new[] { syncParam }).Compile(); + return Expression.Lambda>(boxedCopy, name, new[] { SyncParam }).Compile(); } // For reference types, we have to call ToString right away to get a snapshot of the value. We cannot @@ -231,10 +241,10 @@ namespace OpenRA.Network var member = Expression.Block(new[] { memberVariable }, assignMemberVariable); getString = Expression.Call(member, toString); var nullMember = Expression.Constant(null, memberType); - getString = Expression.Condition(Expression.Equal(member, nullMember), nullString, getString); + getString = Expression.Condition(Expression.Equal(member, nullMember), NullString, getString); } - return Expression.Lambda>(getString, name, new[] { syncParam }).Compile(); + return Expression.Lambda>(getString, name, new[] { SyncParam }).Compile(); } } }