Merge pull request #7141 from RoosterDragon/sync-less-tostring

Generate sync reports faster
This commit is contained in:
Paul Chote
2014-12-22 09:01:08 +13:00

View File

@@ -17,7 +17,7 @@ using OpenRA.Primitives;
namespace OpenRA.Network
{
using NamesValuesPair = Pair<string[], string[]>;
using NamesValuesPair = Pair<string[], object[]>;
class SyncReport
{
@@ -35,10 +35,10 @@ namespace OpenRA.Network
TypeInfo typeInfo;
lock (typeInfoCache)
typeInfo = typeInfoCache[type];
var values = new string[typeInfo.Names.Length];
var values = new object[typeInfo.Names.Length];
var index = 0;
foreach (var func in typeInfo.MemberToStringFunctions)
foreach (var func in typeInfo.SerializableCopyOfMemberFunctions)
values[index++] = func(sync);
return Pair.New(typeInfo.Names, values);
@@ -166,7 +166,7 @@ namespace OpenRA.Network
static ParameterExpression syncParam = Expression.Parameter(typeof(ISync), "sync");
static ConstantExpression nullString = Expression.Constant(null, typeof(string));
public readonly Func<ISync, string>[] MemberToStringFunctions;
public readonly Func<ISync, object>[] SerializableCopyOfMemberFunctions;
public readonly string[] Names;
public TypeInfo(Type type)
@@ -182,14 +182,25 @@ namespace OpenRA.Network
"Invalid Property: " + prop.DeclaringType.FullName + "." + prop.Name);
var sync = Expression.Convert(syncParam, type);
MemberToStringFunctions = fields
.Select(fi => MemberToString(Expression.Field(sync, fi), fi.FieldType, fi.Name))
.Concat(properties.Select(pi => MemberToString(Expression.Property(sync, pi), pi.PropertyType, pi.Name)))
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)))
.ToArray();
Names = fields.Select(fi => fi.Name).Concat(properties.Select(pi => pi.Name)).ToArray();
}
static Func<ISync, object> SerializableCopyOfMember(MemberExpression getMember, Type memberType, string name)
{
if (memberType.IsValueType)
{
// We can get a copy just by accessing the member since it is a value type.
var boxedCopy = Expression.Convert(getMember, typeof(object));
return Expression.Lambda<Func<ISync, object>>(boxedCopy, name, new[] { syncParam }).Compile();
}
return MemberToString(getMember, memberType, name);
}
static Func<ISync, string> MemberToString(MemberExpression getMember, Type memberType, string name)
{
// The lambda generated is shown below.
@@ -197,10 +208,13 @@ namespace OpenRA.Network
var toString = memberType.GetMethod("ToString", Type.EmptyTypes);
Expression getString;
if (memberType.IsValueType)
{
// (ISync sync) => { return ((TSync)sync).Foo.ToString(); }
getString = Expression.Call(getMember, toString);
}
else
{
// (ISync sync) => { var foo = ((TSync)sync).Foo; return foo == null ? null : foo.ToString()); }
// (ISync sync) => { var foo = ((TSync)sync).Foo; return foo == null ? null : foo.ToString(); }
var memberVariable = Expression.Variable(memberType, getMember.Member.Name);
var assignMemberVariable = Expression.Assign(memberVariable, getMember);
var member = Expression.Block(new[] { memberVariable }, assignMemberVariable);