Delegates calling overhead  
Author Message
aghoneim





PostPosted: Visual C# Language, Delegates calling overhead Top

Hello,
I need to retrieve the value of an object’s property but the member property is not known at compile time e.g. I have object of Type Foo with properties FirstX, SecondX and ThirdX.
So instead of having multiple if-else statements then having x = foo.SecondX (depending on some condition) , now I have something like x = pfoo.X where pfoo is simply a type that dynamically maps to a set of properties on Foo. The X property on pfoo is nothing more than an open instance method delegate that explicitly supplies the hidden first argument as the instance of Foo. Here is how pfoo looks like:

class FooMapper
{
private Foo foo;

private TypeUtility<Foo>.MemberCallback<int> x;

public Foo Foo {
get { return this.foo; }
set { this.foo = value; }
}

public int X {
get { return x (foo); }
}

public FooMapper (string xtype) {
x = TypeUtility<Foo>.GetMemberCallback<int> (xtype + "X");
}
}

Where TypeUtility is a nice class that I’ve found on CodeProject http://www.hide-link.com/ that simply (generically and dynamically) generates a delegate for a member like that:

public class TypeUtility<T>
{
public delegate R MemberCallback<R> (T obj);

public static MemberCallback<R> GetMemberCallback<R> (string memberName) {
Type objectType = typeof (T);
PropertyInfo pi = objectType.GetProperty (memberName);
MethodInfo mi = pi.GetGetMethod ();
return (MemberCallback<R>)
Delegate.CreateDelegate (typeof (MemberCallback<R>), pmi);
}

}

I simply create an instance of FooMapper with the type that I want, pfoo = new FooMapper(“Second”), Then before using it I set it’s Foo property to the foo instance I want, pfoo.Foo = foo .
Now everything works fine, but the problem I am having is the performance, as I have to get pfoo.x in a loop, right now I am seeing a difference in performance of 10 times! i.e. the old code executes in 2 seconds while the new dynamic code in 20!
Is this due to the overhead of calling the delegates Anyway to improve this As I understand, right now the calls are made to the properties getters using late bound Callvirt on the object, will it make a difference if instead of using Delegate.CreateDelegate I used dynamic methods and used something like

il.Emit (OpCodes.Ldarg_0);
il.Emit (OpCodes.Call, mi);
il.Emit (OpCodes.Ret);

Please forgive me if this question sounds stupid, as I have close to no experience with IL.
Any ideas what I’m doing wrong Or if this situation can’t be improved Can the overhead of calling delegates be really that high


Thanks.



Visual C#17  
 
 
cverdon





PostPosted: Visual C# Language, Delegates calling overhead Top

Hi,

Instead of going through that route I would suggest using the PropertyDescriptor object. Let's suppose you have a string containing the name of the property you want the value:

MyObject obj = new MyObject();

string propName = "FirstX";

PropertyDescriptorCollection properties = TypeDescriptor.GetProperties( typeof( MyObject ) );

PropertyDescriptor prop = properties.Find( propName, false );

object value = prop.GetValue( obj );

All you have to do is map the conditions to a string containing the name of the property using a constant array, then you can access the value of the instance with the code above.

Good luck,
Charles


 
 
aghoneim





PostPosted: Visual C# Language, Delegates calling overhead Top

Hi charles,

Thank you for your reply.

Reflection API is very costly, that's what i was trying to avoid from the beginning, your suggestion means calling prop.GetValue inside a loop. This is much slower!

try running something like this to get a feeling of the performance hit the reflection api will do:

string propName = "SecondX";

PropertyDescriptorCollection props = TypeDescriptor.GetProperties (typeof (Foo));

PropertyDescriptor prop = props.Find (propName, false);

for (int i = 0;i < SIZE;i++)

a [ i ] = (int)prop.GetValue (f [ i ]);

where a is an array of int, and f is an array of Foo, you will see a difference of about 400 times between this and normal proeprty getter (YMMV) .

with my solution, you have a delegate to the property gettere, my understanding is that the performance hit is due to late binding.

My question was, is there is way (code generation and custom IL perhaps ) to make this early-bound as i know the type of the object, i.e. something like the call instructions emitted by the compiler

i guess my error was thinking of delegates as normal C/C++ pointer to functions :(

Thanks,

Ahmed Ghoneim


 
 
cverdon





PostPosted: Visual C# Language, Delegates calling overhead Top

Can you explain the the scenario in which this is an issue

Can you share the reason why you need the flexibility of a delegate to different properties of a list of objects based on conditions

What type of application are you working on

Charles


 
 
aghoneim





PostPosted: Visual C# Language, Delegates calling overhead Top

Can you explain the the scenario in which this is an issue

Can you share the reason why you need the flexibility of a delegate to different properties of a list of objects based on conditions

What type of application are you working on

Charles

I would think many other scenarios other than my specific one, do exist. ORM being a good example.

as for my own, think insurance planes, accounts and rates, think patient, insured, guarantors and responsible parties. Now how about a Policy number is the patient the insured or the spouse what plan is this is it primary or secondary

instead of having differsnt cases/if-else for these (and lots of redundant assignment code along with them), wouldn't it be much better to have all the cases in pre built array of mapper object so you would have pfoo = map[First, Rate2, Guarantor] then use policy = pfoo.PolicyNumber. now you have all of your assignment code in one place and the codes looks much more elegant.

anyways, thank you for your interest,

Ahmed Ghoneim


 
 
cverdon





PostPosted: Visual C# Language, Delegates calling overhead Top

So basically you want to abstract the business logic from the code.

Have you looked into using a full featured rule engine such as the one in WF With such a rule engine, the business logic would not be hard-coded in the array of mapper object and you could create a UI to let business users change the ruleset.

With your solution I would be concerned about the maintainability in the long run of your business logic. If there is a new requirement that the policy number depends also the geographic location of the client, you will have to go through all your mappings to add an additional dimension to the table

pfoo = map[First, Rate2, Guarantor]
policy = pfoo.PolicyNumber

In the code above, if I understand it correctly, the mapper pfoo will map the PolicyNumber to a property of a different class with a delegate that is generated. But what does the delegate point to A client's first policy number with rate2 and a Guarantor In that case why not a simple FindPolicy on the client with 3 parameters, first, rate2 and guarantor

Or maybe you have a class with all the policy numbers (unlikely)

class PolicyNumbers

{

    int First_Rate1_Guarantor1 { get; }

    int First_Rate2_Guarantor1 { get; }

    int Second_Rate1_Guarantor1 { get; }

    int Second_Rate2_Guarantor1 { get; }

    int First_Rate1_Guarantor2 { get; }

    int First_Rate2_Guarantor2 { get; }

    int Second_Rate1_Guarantor2 { get; }

    int Second_Rate2_Guarantor2 { get; }

}

Can you rewrite the 2 lines above with if statements, maybe I would understand better :)
I think that there is a simple solution but maybe I don't understand the problem fully.

Charles


 
 
aghoneim





PostPosted: Visual C# Language, Delegates calling overhead Top

With your solution I would be concerned about the maintainability in the long run of your business logic. If there is a new requirement that the policy number depends also the geographic location of the client, you will have to go through all your mappings to add an additional dimension to the table

Actually maintainability is what we're trying to improve now ;), please note that this is NOT design phase, that's a large, old inherited code base, that we're trying to make more maintainable, mainly through extension. you have to work with what you have.

pfoo = map[First, Rate2, Guarantor]
policy = pfoo.PolicyNumber

In the code above, if I understand it correctly, the mapper pfoo will map the PolicyNumber to a property of a different class with a delegate that is generated. But what does the delegate point to A client's first policy number with rate2 and a Guarantor In that case why not a simple FindPolicy on the client with 3 parameters, first, rate2 and guarantor

Or maybe you have a class with all the policy numbers (unlikely)

nop, that's one big class with too many properties that for a certain condition we only need a subset of. We're somehow restricted with what we can do, but fresh ideas are always welcomed, thank you for mentioning WF, we haven;t looked at that, we'll give it a try if its fast enough (speed is a HUGE factor)

Thanks,

Ahmed Ghoneim


 
 
cverdon





PostPosted: Visual C# Language, Delegates calling overhead Top

You should probably post your question about MSIL generation in the CLR forum:
http://forums.microsoft.com/MSDN/ShowForum.aspx ForumID=44&SiteID=1

People there are probably more knowledgeable about this sort of thing.

Good luck,
Charles