Skip to content

Commit ec60312

Browse files
author
jayt
committed
Optimized more to beat new unit tests for speed.
1 parent cca3d86 commit ec60312

File tree

6 files changed

+114
-11
lines changed

6 files changed

+114
-11
lines changed

ImpromptuInterface.Silverlight/ImpromptuInterface.Silverlight.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@
122122
<Compile Include="..\ImpromptuInterface\Impromptu.cs">
123123
<Link>Impromptu.cs</Link>
124124
</Compile>
125+
<Compile Include="..\ImpromptuInterface\Optimization\BinderHash.cs">
126+
<Link>Optimization\BinderHash.cs</Link>
127+
</Compile>
125128
<Compile Include="..\ImpromptuInterface\Optimization\InvokeHelper.cs">
126129
<Link>Optimization\InvokeHelper.cs</Link>
127130
</Compile>

ImpromptuInterface/Impromptu.cs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ namespace ImpromptuInterface
3030
/// </summary>
3131
public static class Impromptu
3232
{
33-
private static readonly IDictionary<Tuple<Type, string, Type>, CallSite> _binderCache = new Dictionary<Tuple<Type, string, Type>, CallSite>();
33+
private static readonly IDictionary<BinderHash, CallSite> _binderCache = new Dictionary<BinderHash, CallSite>();
3434
private static readonly object _binderCacheLock = new object();
3535

3636

37+
38+
3739
/// <summary>
3840
/// Creates a cached call site at runtime.
3941
/// </summary>
@@ -49,7 +51,7 @@ public static class Impromptu
4951
public static CallSite CreateCallSite(Type delegateType, CallSiteBinder binder, string name, Type context)
5052
{
5153

52-
var tHash = Tuple.Create(delegateType, name, context);
54+
var tHash = BinderHash.Create(delegateType, name, context);
5355
lock (_binderCacheLock)
5456
{
5557
CallSite tOut = null;
@@ -101,7 +103,7 @@ public static CallSite CreateCallSite(Type delegateType, CallSiteBinder binder,
101103
/// <seealso cref="CreateCallSite"/>
102104
public static CallSite<T> CreateCallSite<T>(CallSiteBinder binder, string name, Type context) where T: class
103105
{
104-
var tHash = Tuple.Create(typeof(T), name, context);
106+
var tHash = BinderHash<T>.Create(name, context);
105107
lock (_binderCacheLock)
106108
{
107109
CallSite tOut = null;
@@ -145,9 +147,13 @@ public static dynamic InvokeMember(object target, string name, params object[] a
145147
{
146148
CSharp.CSharpArgumentInfo.Create(CSharp.CSharpArgumentInfoFlags.None, null)
147149
};
148-
tList.AddRange(args.Select(
149-
it =>
150-
CSharp.CSharpArgumentInfo.Create(CSharp.CSharpArgumentInfoFlags.UseCompileTimeType, null)));
150+
151+
//Optimization: linq statement creates a slight overhead in this case
152+
// ReSharper disable LoopCanBeConvertedToQuery
153+
for (int i = 0; i < args.Length; i++)
154+
tList.Add(CSharp.CSharpArgumentInfo.Create(CSharp.CSharpArgumentInfoFlags.UseCompileTimeType, null));
155+
// ReSharper restore LoopCanBeConvertedToQuery
156+
151157
var tBinder =CSharp.Binder.InvokeMember(CSharp.CSharpBinderFlags.None, name, null,
152158
tContext,tList);
153159

@@ -187,9 +193,11 @@ public static void InvokeMemberAction(object target, string name, params object[
187193
{
188194
CSharp.CSharpArgumentInfo.Create(CSharp.CSharpArgumentInfoFlags.None, null)
189195
};
190-
tArgs.AddRange(args.Select(
191-
it =>
192-
CSharp.CSharpArgumentInfo.Create(CSharp.CSharpArgumentInfoFlags.UseCompileTimeType, null)));
196+
//Optimization: linq statement creates a slight overhead in this case
197+
// ReSharper disable LoopCanBeConvertedToQuery
198+
for (int i = 0; i < args.Length; i++)
199+
tArgs.Add(CSharp.CSharpArgumentInfo.Create(CSharp.CSharpArgumentInfoFlags.UseCompileTimeType, null));
200+
// ReSharper restore LoopCanBeConvertedToQuery
193201
var tContext = target.GetType();
194202
var tBinder = CSharp.Binder.InvokeMember(CSharp.CSharpBinderFlags.ResultDiscarded, name, null,
195203
tContext,tArgs);

ImpromptuInterface/ImpromptuInterface.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
<Compile Include="EmitProxy\BuildProxy.cs" />
7373
<Compile Include="EmitProxy\EmitExtensions.cs" />
7474
<Compile Include="Dynamic\ImpromptuObject.cs" />
75+
<Compile Include="Optimization\BinderHash.cs" />
7576
<Compile Include="Optimization\InvokeHelper.cs" />
7677
<Compile Include="Properties\AssemblyInfo.cs" />
7778
<Compile Include="EmitProxy\TypeHash.cs" />
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
6+
namespace ImpromptuInterface.Optimization
7+
{
8+
internal class BinderHash
9+
{
10+
protected BinderHash(Type delegateType, string name, Type context)
11+
{
12+
DelegateType = delegateType;
13+
Name = name;
14+
Context = context;
15+
}
16+
17+
public static BinderHash Create(Type delType, string name, Type context)
18+
{
19+
return new BinderHash(delType, name, context);
20+
}
21+
22+
23+
24+
public Type DelegateType { get; protected set; }
25+
public string Name { get; protected set; }
26+
public Type Context { get; protected set; }
27+
28+
29+
public virtual bool Equals(BinderHash other)
30+
{
31+
if (ReferenceEquals(null, other)) return false;
32+
if (ReferenceEquals(this, other)) return true;
33+
return Equals(other.DelegateType, DelegateType) && Equals(other.Name, Name) && Equals(other.Context, Context);
34+
}
35+
36+
public override bool Equals(object obj)
37+
{
38+
if (ReferenceEquals(null, obj)) return false;
39+
if (ReferenceEquals(this, obj)) return true;
40+
if (!(obj is BinderHash)) return false;
41+
return Equals((BinderHash)obj);
42+
}
43+
44+
public override int GetHashCode()
45+
{
46+
unchecked
47+
{
48+
int result = DelegateType.GetHashCode();
49+
result = (result * 397) ^ Name.GetHashCode();
50+
result = (result * 397) ^ Context.GetHashCode();
51+
return result;
52+
}
53+
}
54+
}
55+
56+
internal class GenericBinderHashBase : BinderHash
57+
{
58+
protected GenericBinderHashBase(Type delegateType, string name, Type context)
59+
: base(delegateType, name, context)
60+
{
61+
}
62+
}
63+
64+
internal class BinderHash<T> : GenericBinderHashBase where T : class
65+
{
66+
67+
public static BinderHash<T> Create(string name, Type context)
68+
{
69+
return new BinderHash<T>(name, context);
70+
}
71+
72+
protected BinderHash(string name, Type context)
73+
: base(typeof(T), name, context)
74+
{
75+
}
76+
77+
78+
public override bool Equals(BinderHash other)
79+
{
80+
if (other is GenericBinderHashBase)
81+
{
82+
if (other is BinderHash<T>)
83+
{
84+
return Equals(other.Name, Name) && Equals(other.Context, Context);
85+
}
86+
return false;
87+
}
88+
return base.Equals(other);
89+
}
90+
}
91+
}

ImpromptuInterface/Properties/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,4 @@
5252
// You can specify all the values or you can default the Build and Revision Numbers
5353
// by using the '*' as shown below:
5454
// [assembly: AssemblyVersion("1.0.*")]
55-
[assembly: AssemblyVersion("3.0.0.*")]
55+
[assembly: AssemblyVersion("3.0.1.*")]

nuget/ImpromptuInterface.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>ImpromptuInterface</id>
5-
<version>3.0.0</version>
5+
<version>3.0.1</version>
66
<authors>Jay Tuley</authors>
77
<owners>Jay Tuley</owners>
88
<description>A Lightweight Duck Casting Framework for dynamic C# 4.0 (.net4 &amp; silverlight4). Includes helper methods for dynamic invocation via method and property names known only at runtime (runs faster than reflection).</description>

0 commit comments

Comments
 (0)