Posts Tagged Reflection

Faster Invoke for reflected property access and method invocation with AOT compilation



Download

The bane of the iOS programmers life, when working with reflection in Mono, is that you can’t go around making up new generic types to ensure that your reflected properties and methods get called at decent speed. This is because Mono on iOS is fully Ahead Of Time compiled and simply can’t make up new stuff as you go along. That coupled with the dire performance of Invoke when using reflected properties lead me to construct a helper class.

This works by registering a series of method signatures with the compiler, so that they are available to code running on the device. In my tests property access was 4.5x faster and method access with one parameters was 2.4x faster. Not earth shattering but every little helps. If you knew what you wanted ahead of time, then you could probably do a lot better. See here for info.

You have to register signatures inside each class I’m afraid. Nothing I can do about that.

So to register a signature you use:

static MyClass()
{
     //All methods returning string can be accelerated
     DelegateSupport.RegisterFunctionType<MyClass, string>();         
     //All methods returning string and taking an int can be accelerated
     DelegateSupport.RegisterFunctionType<MyClass, int, string>();    
     //All methods returning void and taking a bool can be accelerated
     DelegateSupport.RegisterActionType<MyClass, bool>();             

}

Then when you have a MethodInfo you use the extension method FastInvoke(object target, params object[] parameters) to call it. FastInvoke will default to using normal Invoke if you haven’t accelerated a particular type.

       myObject.GetType().GetProperty("SomeProperty").GetGetMethod().FastInvoke(myObject);
       myObject.GetType().GetMethod("SomeMethod").FastInvoke(myObject, 1, 2);

You can download the source code for FastInvoke from here.

, , , , , ,

Leave a comment

SilverlightSerializer Version 2


SilverlightSerializer version 2

Well, I know it’s been a long wait and I’ve been promising the new version of SilverlightSerializer for months, but it’s finally here, extracted from my core project and working standalone.

This new version of the serializer is a major rewrite – with 2 goals in mind:

1. Performance

Serialization performance is 61% faster (my test harness serializes 100,000 objects in 1.03 seconds compared to 1.72)
Deserialization performance is 27% faster (my test hardness deserializes 100,000 objects in 1.61 seconds compared to 2.04)

These performance gains are on large object graphs containing multiple instances of the same types – it would nominally be slightly slower on small graphs or graphs that contain only one copy of each object – but of course that’s very unlikely in the real world.

2. Extensibility

The new version of SilverlightSerializer abstracts the storage methods behind a new interface, IStorage.  There’s a complete implementation of a BinarySerializer that is compatible with the old version of SilverlightSerializer, but you could add your own.  Alterian has built versions that store data in XML and SQL Server tables.  This means one standard semantic serialization layer can be used with pluggable storage types to put the information where you need it for the application at hand.

That said, writing an IStorage is fairly involved process and I’ll write a post or a page on it if people want me to.

In addition the serializer now handles arrays and enums far better than before and hopefully should avoid the dreaded MissingMethod exception by providing a more developer friendly exception and message while offering the opportunity to construct classes without a parameterless constructor using a new CreateType event that will help some avoid the need to write custom serializers.

You can find the version 2 source code here.  In response to a couple of requests, the project is also accessible on GitHub, see the link at the top of the SilverlightSerializer page.

Why is it faster?

So read on if you’d like to know why it’s faster!

SilverlightSerializer is a reflection based serializer.  It examines an object to identify the available properties and fields. As anyone who is familiar with .NET will know, reflection isn’t exactly the fastest thing in the world.  SS v1 did its level best to cache everything possible, but it still relied on reflection to write and read properties and fields from the underlying objects.  This is why SS didn’t perform as well as the inbuilt serializers in .NET.

Now reflection in this case is a hard thing to get around, I don’t know the types in advance and I have no interest in getting the developer to have to write a custom serialization class for each of their types.

The answer to this performance challenge came from using generic classes and using .NET to construct a new generic class on the fly for each property of each class being serialized.  The generic class accesses the native property access functions directly, rather than have to use reflection.  Fields have to be handled slightly differently, with a reflection function, but at least it’s no slower than the previous method.

First let’s start with the base class that is used for all of the generic classes, it’s called GetSet.


public abstract class GetSet
{
public PropertyInfo Info;
public string Name;
public FieldInfo FieldInfo;
public object Vanilla;
public bool CollectionType;
public abstract object Get(object item);
public abstract void Set(object item, object value);

}

From this base class I create a definition of a generic class, called GetSetGeneric.  This class creates Get and Set delegates using the class parameters, these delegates then map to the functions that will be exposed by the property getters and setters on the target class (neat huh).  This happens only once per type/property combination and the resulting code is the same speed as writing a function to get the value.

public class GetSetGeneric<T, TR> : GetSet
{
public delegate TR GetValue(T obj);
public delegate void SetValue(T obj, TR value);
private readonly GetValue _get;
private readonly SetValue _set;

public GetSetGeneric(PropertyInfo info)
{
MethodInfo getMethod;
MethodInfo setMethod = null;
Name = info.Name;
Info = info;
CollectionType = Info.PropertyType.GetInterface("IEnumerable", true) != null;
getMethod = info.GetGetMethod();
setMethod = info.GetSetMethod();
_get = (GetValue)Delegate.CreateDelegate(typeof(GetValue), getMethod);
if (setMethod != null) _set = (SetValue)Delegate.CreateDelegate(typeof(SetValue), setMethod);
}

public GetSetGeneric(FieldInfo info)
{
MethodInfo getMethod;
MethodInfo setMethod = null;
Name = info.Name;
FieldInfo = info;
_get = new GetValue(GetFieldValue);
_set = new SetValue(SetFieldValue);
CollectionType = FieldInfo.FieldType.GetInterface("IEnumerable", true) != null;
return;
}

public GetSetGeneric(string name)
{
Name = name;
MethodInfo getMethod;
MethodInfo setMethod= null;
var t = typeof(T);
var p = t.GetProperty(name);
if (p == null)
{
FieldInfo = typeof(T).GetField(Name);
_get = new GetValue(GetFieldValue);
_set = new SetValue(SetFieldValue);
CollectionType = FieldInfo.FieldType.GetInterface("IEnumerable", true) != null;
return;
}
Info = p;
CollectionType = Info.PropertyType.GetInterface("IEnumerable", true) != null;
getMethod = p.GetGetMethod();
setMethod = p.GetSetMethod();
_get = (GetValue)Delegate.CreateDelegate(typeof(GetValue), getMethod);
if(setMethod != null) _set = (SetValue)Delegate.CreateDelegate(typeof(SetValue), setMethod);
}

private TR GetFieldValue(T obj)
{
return (TR)FieldInfo.GetValue(obj);
}

private void SetFieldValue(T obj, TR value)
{
FieldInfo.SetValue(obj, value);
}

public override object Get(object item)
{
return _get((T)item);
}

public override void Set(object item, object value)
{
_set((T)item, (TR)value);
}
}

Once that’s done it’s just a matter of creating the generic classes. Deserialization does this one property at a time form the input stream:

entryConfiguration = new EntryConfiguration();

var pi = entry.OwningType.GetProperty(entry.Name);
if (pi != null)
{
entryConfiguration.Type = pi.PropertyType;
var gs = typeof(GetSetGeneric<,>);
var tp = gs.MakeGenericType(new Type[] { entry.OwningType, pi.PropertyType });
entryConfiguration.Setter = (GetSet)Activator.CreateInstance(tp, new object[] { pi });
}
else
{
var fi = entry.OwningType.GetField(entry.Name);
if (fi != null)
{
entryConfiguration.Type = fi.FieldType;
var gs = typeof(GetSetGeneric<,>);
var tp = gs.MakeGenericType(new Type[] { entry.OwningType, fi.FieldType });
entryConfiguration.Setter = (GetSet)Activator.CreateInstance(tp, new object[] { fi });
}
}

Here you can see I get either the property or the field information, use the type of the containing class and the property in a call to MakeGenericType to construct the correct class, then create an instance of that class that can be used to get and set properties on the object.
Serialization works by creating a list of getters and setters for every sensible property on the object, in SilverlightSerializer that creates a few different flavours depending on whether you are using Checksums etc. If you want to see how I do that, have a look at the GetWriteableAttributes class and the GetAccessors() function.

, , , , , , , , , ,

10 Comments