Skip to content

Commit

Permalink
Small perf improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
eswann committed Aug 1, 2014
1 parent 0a2212b commit ef192fb
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 362 deletions.
15 changes: 1 addition & 14 deletions src/Fpr/Utils/Activator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,11 @@

namespace Fpr.Utils
{
public static class Activator<T> where T : class, new()
{
public static Func<T> CreateInstance { get; private set; }
static Activator()
{
CreateInstance = typeof(T).GetConstructorDelegate<T>();
}
}


public static class ActivatorExtensions
{
private static readonly ConcurrentDictionary<Type, Func<object>> _constructors = new ConcurrentDictionary<Type, Func<object>>();

public static Func<TBase> GetConstructorDelegate<TBase>(this Type type)
{
return (Func<TBase>)GetConstructorDelegate(type, typeof(Func<TBase>));
}

public static Func<object> GetConstructorDelegate(this Type type)
{
return (Func<object>)GetConstructorDelegate(type, typeof(Func<object>));
Expand Down
45 changes: 14 additions & 31 deletions src/Fpr/Utils/FastObjectFactory.cs
Original file line number Diff line number Diff line change
@@ -1,51 +1,34 @@
using System;
using System.Collections.Generic;
using System.Reflection.Emit;

namespace Fpr.Utils
{
public static class FastObjectFactory
{
private static readonly object _syncLock = new object();
private static readonly Dictionary<Type, object> _creatorCache = new Dictionary<Type, object>();

public static void ClearObjectFactory<T>() where T : class
{
_creatorCache.Remove(typeof (T));
}

/// <summary>
/// Create a new instance of the specified type
/// </summary>
/// <returns></returns>
public static Func<T> CreateObjectFactory<T>(Func<T> factory = null)
public static Func<T> CreateObjectFactory<T>(Func<T> factory = null)
{
Type type = typeof(T);
Type type = typeof (T);
object createDelegate;
if (!_creatorCache.TryGetValue(type, out createDelegate))

if (factory != null)
{
createDelegate = factory;
}
else
{
lock (_syncLock)
{
if (!_creatorCache.TryGetValue(type, out createDelegate))
{
if (factory != null)
{
createDelegate = factory;
}
else
{
var dynMethod = new DynamicMethod("DM$OBJ_FACTORY_" + type.Name, type, null, type);
ILGenerator ilGen = dynMethod.GetILGenerator();
var dynMethod = new DynamicMethod("DM$OBJ_FACTORY_" + type.Name, type, null, type);
ILGenerator ilGen = dynMethod.GetILGenerator();

ilGen.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
ilGen.Emit(OpCodes.Ret);
createDelegate = dynMethod.CreateDelegate(typeof(Func<T>));
}
_creatorCache.Add(type, createDelegate);
}
}
ilGen.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
ilGen.Emit(OpCodes.Ret);
createDelegate = dynMethod.CreateDelegate(typeof (Func<T>));
}
return (Func<T>)createDelegate;
return (Func<T>) createDelegate;
}
}
}
262 changes: 1 addition & 261 deletions src/Fpr/Utils/PropertyCaller.cs
Original file line number Diff line number Diff line change
@@ -1,213 +1,19 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;

namespace Fpr.Utils
{
public static class PropertyCaller<TClass, TReturn> where TClass : class
{
private static readonly object _getterLock = new object();
private static readonly object _setterLock = new object();

private static readonly Dictionary<Type, Dictionary<Type, Dictionary<string, GenGetter>>> _getterCache =
new Dictionary<Type, Dictionary<Type, Dictionary<string, GenGetter>>>();

private static readonly Dictionary<Type, Dictionary<Type, Dictionary<string, GenSetter>>> _setterCache =
new Dictionary<Type, Dictionary<Type, Dictionary<string, GenSetter>>>();

public delegate void GenSetter(TClass target, TReturn value);
public delegate TReturn GenGetter(TClass target);

public static GenGetter CreateGetMethod(PropertyInfo pi)
{
//Create the locals needed.
Type classType = typeof(TClass);
Type returnType = typeof(TReturn);

string propertyName = pi.Name;

Dictionary<Type, Dictionary<string, GenGetter>> classGetters;
if (_getterCache.TryGetValue(classType, out classGetters))
{
Dictionary<string, GenGetter> propertyTypeGetters;
if (classGetters.TryGetValue(returnType, out propertyTypeGetters))
{
GenGetter cachedGetter;
if (propertyTypeGetters.TryGetValue(propertyName, out cachedGetter))
{
return cachedGetter;
}
}
}

//If there is no getter, return nothing
MethodInfo getMethod = pi.GetGetMethod();

if (getMethod == null)
return null;

//Create the dynamic method to wrap the internal get method
var getter = new DynamicMethod(String.Concat("Get", pi.Name, "_"), typeof(TReturn), new[] { typeof(TClass) }, pi.DeclaringType);

ILGenerator gen = getter.GetILGenerator();

gen.DeclareLocal(typeof(TReturn));
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Castclass, pi.DeclaringType);
gen.EmitCall(OpCodes.Callvirt, getMethod, null);
gen.Emit(OpCodes.Ret);

//Create the delegate and return it
var genGetter = (GenGetter)getter.CreateDelegate(typeof(GenGetter));

lock (_getterLock)
{
//Cache the delegate for future use.
Dictionary<string, GenGetter> tempPropDict;

if (!_getterCache.ContainsKey(classType))
{
tempPropDict = new Dictionary<string, GenGetter> {{propertyName, genGetter}};

var tempDict = new Dictionary<Type, Dictionary<string, GenGetter>> {{returnType, tempPropDict}};

_getterCache.Add(classType, tempDict);
}
else
{
if (!_getterCache[classType].ContainsKey(returnType))
{
tempPropDict = new Dictionary<string, GenGetter> {{propertyName, genGetter}};
_getterCache[classType].Add(returnType, tempPropDict);
}
else
{
if (!_getterCache[classType][returnType].ContainsKey(propertyName))
_getterCache[classType][returnType].Add(propertyName, genGetter);
}
}
}
//Return delegate to the caller.
return genGetter;

}


public static GenSetter CreateSetMethod(PropertyInfo pi)
{
//Create the locals needed.
Type classType = typeof(TClass);
Type returnType = typeof(TReturn);
string propertyName = pi.Name;

//Let’s return the cached delegate if we have one.
Dictionary<Type, Dictionary<string, GenSetter>> classSetters;
if (_setterCache.TryGetValue(classType, out classSetters))
{
Dictionary<string, GenSetter> propertyTypeSetters;
if (classSetters.TryGetValue(returnType, out propertyTypeSetters))
{
GenSetter cachedSetter;
if (propertyTypeSetters.TryGetValue(propertyName, out cachedSetter))
{
return cachedSetter;
}
}
}

//If there is no setter, return nothing
MethodInfo setMethod = pi.GetSetMethod(true);

if (setMethod == null)
return null;

//Create dynamic method

Type[] arguments = { classType, returnType };

var setter = new DynamicMethod(String.Concat("_Set", pi.Name, "_"), typeof(void), arguments, pi.DeclaringType);

ILGenerator gen = setter.GetILGenerator();

gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Castclass, pi.DeclaringType);
gen.Emit(OpCodes.Ldarg_1);

if (pi.PropertyType.IsClass)
gen.Emit(OpCodes.Castclass, pi.PropertyType);

gen.EmitCall(OpCodes.Callvirt, setMethod, null);

gen.Emit(OpCodes.Ret);

//Create the delegate
var genSetter = (GenSetter)setter.CreateDelegate(typeof(GenSetter));

lock (_setterLock)
{
//Cache the delegate for future use.
Dictionary<string, GenSetter> tempPropDict;

if (!_setterCache.ContainsKey(classType))
{
tempPropDict = new Dictionary<string, GenSetter> {{propertyName, genSetter}};

var tempDict = new Dictionary<Type, Dictionary<string, GenSetter>> {{returnType, tempPropDict}};

_setterCache.Add(classType, tempDict);
}
else
{
if (!_setterCache[classType].ContainsKey(returnType))
{
tempPropDict = new Dictionary<string, GenSetter> {{propertyName, genSetter}};

_setterCache[classType].Add(returnType, tempPropDict);
}
else
{
if (!_setterCache[classType][returnType].ContainsKey(propertyName))
_setterCache[classType][returnType].Add(propertyName, genSetter);
}
}
}
//Return delegate to the caller.
return genSetter;

}
}


public static class PropertyCaller<T>
{
public delegate void GenSetter(T target, Object value);
public delegate Object GenGetter(T target);

private static readonly object _getterLock = new object();
private static readonly object _setterLock = new object();

private static readonly Dictionary<Type, Dictionary<Type, Dictionary<string, GenGetter>>> _getterCache = new Dictionary<Type, Dictionary<Type, Dictionary<string, GenGetter>>>();
private static readonly Dictionary<Type, Dictionary<Type, Dictionary<string, GenSetter>>> _setterCache = new Dictionary<Type, Dictionary<Type, Dictionary<string, GenSetter>>>();

public static GenGetter CreateGetMethod(PropertyInfo pi)
{
var classType = typeof(T);
var propType = pi.PropertyType;
var propName = pi.Name;

Dictionary<Type, Dictionary<string, GenGetter>> classGetters;
if (_getterCache.TryGetValue(classType, out classGetters))
{
Dictionary<string, GenGetter> propertyTypeGetters;
if (classGetters.TryGetValue(propType, out propertyTypeGetters))
{
GenGetter cachedGetter;
if (propertyTypeGetters.TryGetValue(propName, out cachedGetter))
{
return cachedGetter;
}
}
}

//If there is no getter, return nothing
var getMethod = pi.GetGetMethod();
Expand All @@ -229,53 +35,13 @@ public static GenGetter CreateGetMethod(PropertyInfo pi)
//Create the delegate and return it
var genGetter = (GenGetter)getter.CreateDelegate(typeof(GenGetter));

lock (_getterLock)
{
Dictionary<string, GenGetter> tempPropDict;
if (!_getterCache.ContainsKey(classType))
{
tempPropDict = new Dictionary<string, GenGetter> {{propName, genGetter}};
var tempDict = new Dictionary<Type, Dictionary<string, GenGetter>> {{propType, tempPropDict}};
_getterCache.Add(classType, tempDict);
}
else
{
if (!_getterCache[classType].ContainsKey(propType))
{
tempPropDict = new Dictionary<string, GenGetter> {{propName, genGetter}};
_getterCache[classType].Add(propType, tempPropDict);
}
else
{
if (!_getterCache[classType][propType].ContainsKey(propName))
{
_getterCache[classType][propType].Add(propName, genGetter);
}
}
}
}
return genGetter;
}

public static GenSetter CreateSetMethod(PropertyInfo pi)
{
Type classType = typeof(T);
Type propType = pi.PropertyType;
string propName = pi.Name;

Dictionary<Type, Dictionary<string, GenSetter>> classSetters;
if (_setterCache.TryGetValue(classType, out classSetters))
{
Dictionary<string, GenSetter> propertyTypeSetters;
if (classSetters.TryGetValue(propType, out propertyTypeSetters))
{
GenSetter cachedSetter;
if (propertyTypeSetters.TryGetValue(propName, out cachedSetter))
{
return cachedSetter;
}
}
}

//If there is no setter, return nothing
MethodInfo setMethod = pi.GetSetMethod(true);
Expand Down Expand Up @@ -304,32 +70,6 @@ public static GenSetter CreateSetMethod(PropertyInfo pi)
//Create the delegate and return it
var genSetter = (GenSetter)setter.CreateDelegate(typeof(GenSetter));

lock (_setterLock)
{
Dictionary<string, GenSetter> tempPropDict;
if (!_setterCache.ContainsKey(classType))
{
tempPropDict = new Dictionary<string, GenSetter> {{propName, genSetter}};
var tempDict = new Dictionary<Type, Dictionary<string, GenSetter>> {{propType, tempPropDict}};
_setterCache.Add(classType, tempDict);
}
else
{
if (!_setterCache[classType].ContainsKey(propType))
{
tempPropDict = new Dictionary<string, GenSetter> {{propName, genSetter}};
_setterCache[classType].Add(propType, tempPropDict);
}
else
{
if (!_setterCache[classType][propType].ContainsKey(propName))
{
_setterCache[classType][propType].Add(propName, genSetter);
}
}
}
}

return genSetter;
}
}
Expand Down
Loading

0 comments on commit ef192fb

Please sign in to comment.