So I'm working with a lot generic types and using reflection to invoke their various methods. I've noticed that invoking a method via
//Subject is the generic type
Subject.GetType().GetMethod("methodName").Invoke(Subject, args);
seems to work okay and at the same time is dreadfully slower than invoking the methods on the object directly. I understand that I'm trading performance for flexibility and that nothing will ever be as fast the direct approach but I'd like to try and do better.
To this end I though it might be better if I cached the information ahead of time. Perhaps created a bit of front end load on application start up but hopefully reducing the overhead of the calls from there on.
public class TypeCache : IDictionary<Accessor, Dictionary<string, MethodInfo>>
{
public Dictionary<Accessor, Dictionary<string, MethodInfo>> Cache { get; set; }
public TypeCache(Type type)
{
Cache = new Dictionary<Accessor, Dictionary<string, MethodInfo>>();
Cache.Add(Accessor.Method, new Dictionary<string, MethodInfo>());
Cache.Add(Accessor.Get, new Dictionary<string, MethodInfo>());
Cache.Add(Accessor.Set, new Dictionary<string, MethodInfo>());
foreach (var method in type.GetMethods())
{
Cache[Accessor.Method].Add(method.Name, method);
}
var properties = type.GetProperties();
foreach (var property in properties)
{
var getter = property.GetMethod;
var setter = property.SetMethod;
Cache[Accessor.Get].Add(getter.Name, getter);
Cache[Accessor.Set].Add(setter.setter);
}
}
This allows me to replace the reflective call from above with the dictionary call below:
TypeCache[Accessor.Method][binder.Name].Invoke(InnerSubject, args);
Now making the caches singletons and other such efforts aside I'm still coming up a bit short on the performance gains here.
I've noticed that I'm about 15% on average worse than reflection. Is there any way to speed this up? I thought by using a dictionary based approach we might see some improvement. Perhaps if I accessed the three directories (Getters, Setters, and Public Methods) directly instead of flipping through an additional dictionary? To reduce the level of chained calls? Or find some way to assign them all to a single dictionary that gets accessed directory? Would this be worth pursuing?
I attempted to look at libraries like FastMember and I tried my hand at some IL, FastMember only offers access to properties in so far as I've found and IL looks like it would be a study in its own just to get this done.
Aucun commentaire:
Enregistrer un commentaire