|
I had to write a function that was essentially "given some random object at RUNTIME as 'object o' and some random property as 'string propertyName' at RUNTIME, return property o.[propertyName] as an object."
First thought was naturally reflection.
for (i = 0; i < 1000000; i++)
{
// get property 1 million times through reflection
}
that took 4.4 seconds on my machine. I unwound the loop a bit and got it down to 2.1 seconds.
Then I switched it over to LINQ expression trees and got it down to 93 MILLSECONDS. 4.4 seconds down to 93 MILLSECONDS...
Now, LINQ expression trees are very poorly documented in MSDN and a search on google and CodeProject turns up very little. It did take me about 5 hours to figure them out (on a super basic level).
But why aren't they used more often? 4.4 seconds vs. 93 millseconds sounds like a big deal to me .
|
|
|
|
|
SledgeHammer01 wrote: But why aren't they used more often? 4.4 seconds vs. 93 millseconds sounds like a big deal to me
Primarily because they are poorly understood, and working with them is more complex than most other areas.
|
|
|
|
|
Hmm... my first reflection version was about 6 lines of code and my final LINQ expression version was also about 6 lines of code.
Reflection is certainly more documented, but its a shame because LINQ expressions seem pretty powerful and they run about 50x faster in my tests.
|
|
|
|
|
Pete O'Hanlon wrote: Primarily because they are poorly understood,
May be, but that won't be the primary reason. Primary reason could be that expression trees can be compiled which gets translated into IL opcodes. This is way faster than reflection looking for a method and invoking it. If the method signature is known at compile time, converting reflection's MethodInfo to a strongly typed delegate will also improve the performance.
Best wishes,
Navaneeth
|
|
|
|
|
I think you misunderstood my response. I was answering the question about why people don't use them more - I'm well aware of the benefits of Expressions.
|
|
|
|
|
My bad, I am sorry.
Best wishes,
Navaneeth
|
|
|
|
|
No problem. Don't worry about it - if you didn't get what I was talking about then I obviously didn't explain it clearly enough. Ergo, the problem was at my end.
|
|
|
|
|
SledgeHammer01 wrote: why aren't they used more often?
SledgeHammer01 wrote: LINQ expression trees are very poorly documented in MSDN
SledgeHammer01 wrote: a search on google and CodeProject turns up very little.
SledgeHammer01 wrote: It did take me about 5 hours to figure them out (on a super basic level).
|
|
|
|
|
It caches, just like your Reflection code should -- getting the same property a million times is where you are wasting your time; rewrite it and then compare.
|
|
|
|
|
Huh? Cache what?
I don't have production code that goes for (int i = 0; i < 1000000; i++) . Its called benchmarking code .
"version 1" didn't cache anything and it took 4.4 seconds to run 1 million times
"version 2" cached the PropertyInfo object and it went down to 2.1 seconds to run 1 million times. I can't cache the propertyInfo.GetValue() call, that would a) defeat the whole point and b) not even work... what if the value changed? How would I get notified in a callback function that it changed? And you want me to cache the values of a million objects? x 2.
"version 3" went to LINQ expression trees and it went down to 93 milliseconds to run 1 million times. I cached the expression tree, but I did NOT cache the "expressiontree.GetValue()" calls. I still get the same property 1 million times.
4.4 seconds (or to be fair 2.1 seconds) vs 93 milliseconds is not because I'm caching anything.
propertyInfo.GetValue() is an expensive call. It gets the getter method and then calls Invoke on it. I suppose I could have gotten the getter method and cached that, but Invoke is still an expensive call.
The expression tree was simply "inline code" that essentially expanded to:
return (object)((SomeType)o).SomeProperty;
Thats a direct call vs. an invoke.
Thats why its tons faster then reflection.
-- Modified Saturday, January 15, 2011 9:23 PM
|
|
|
|
|
Actually, upon looking at it further in Reflector, GetGetMethod() is not expensive at all. Its already cached in the PropertyInfo object. Once you get the PropertyInfo, its already gotten the getter and cached it in a private variable. private RuntimeMethodInfo m_getterMethod; to be exact.
Invoke is very expensive since it doesn't cache a bunch of stuff, validates parameters, checks security, etc.
Expression trees don't do any of that stuff.
|
|
|
|
|
|
|
SledgeHammer01 wrote: for (i = 0; i < 1000000; i++)
{
// get property 1 million times through reflection
}
that took 4.4 seconds on my machine. I unwound the loop a bit and got it down to 2.1 seconds.
How are you making the calls? MethodInfo.Invoke() ? If yes, then this method is slow. Try creating a delegate from MethodInfo using Delegate.CreateDelegate method and use that for invocation. You should get results closer with expression trees. Make sure you don't do delegate creation on each iteration.
Expression trees are faster because they gets translated into IL when you call Compile() on it.
Best wishes,
Navaneeth
|
|
|
|
|
I was using propertyInfo.GetValue() for the 2.1 seconds. Yeah, that uses Invoke() internally .
I looked up Delegate.CreateDelegate(), don't you eventually need to cast it to a callable delegate to do your suggestion? Like say 'object MyGetter(object o)'?
Not sure if I will run into the same problem as I ran into with the expression trees, but originally, I specified an expression tree like:
object lambaFunc(object o)
{
return ((TheType)o).TheProperty;
}
and that worked fine on strings, but threw an exception if "TheProperty" was an int. I had to explicitly do:
object lambaFunc(object o)
{
return (object)((TheType)o).TheProperty;
}
Not sure if the delegate method would have the same issue.
|
|
|
|
|
Kind of curious....
C# compiles to MSIL, but LINQ compiles to something besides MSIL?
Or that LINQ expressions have access to something in MSIL that C# doesn't?
Because if not then the only explanation for the speed differences would be one or both of the following.
1. The C# is not optimal.
2. The LINQ version is caching something or even optimizing the actual method calls away entirely.
|
|
|
|
|
As indicated in another posting, the LINQ expression tree is essentially a dynamically created lambda function that expands to (note: obviously this isn't legal C# code, but this is what the function expands too):
object LambdaFunc(object o)
{
return (object)((o's real type)o).SomeProperty;
}
so there is nothing to really cache because its just an "inline function".
Reflection does a whole bunch of stuff with security, parameter checking, stack checking, etc. before it calls the function via Invoke.
Both are C# / MSIL. Its just that the LINQ call is much lighter weight because its essentially just a direct call to get the property (and it does a lot less).
-- Modified Tuesday, January 18, 2011 1:26 PM
|
|
|
|
|
hi
i have code in php which is used to create a class to generate the XML File using those php class how can i configure API services
or how can i convert those php codes into c shape code?
urgent req
br
|
|
|
|
|
You have already asked this in Q & A. Stick to one forum and be patient.
|
|
|
|
|
As d@nish already said, please don't crosspost.
As well, it doesn't mean anything to us that it is "urgent" for you. That does not make it urgent for us, nor will it get you an answer quicker. Please just ask the question and leave it at that.
Cheers.
I wasn't, now I am, then I won't be anymore.
|
|
|
|
|
(NOTE: I've been programming for over 20 years so please be gentle if I'm just missing something right under my nose)
In C++, it was common to have situations where a method definition would need something like...
void CSomeClass::DoSomething(CAnotherClass* pObject)
{
if (pObject) {
}
}
You could simplify your world by defining the method so that it took a reference to an object...
void CSomeClass::DoSomething(CAnotherClass& object)
{
}
Passing in a reference to an object eliminated the need to put ASSERT statements and/or runtime checks in a ton of locations that would have required it such as when using pointers. I'm finding that with C#, similar designs using reference types are requiring asserts and runtime checks all over the frackin' place.
Someone please tell me there is a way to eliminate all these checks for null references in C# like I could in C++.
|
|
|
|
|
You can either require all parameters to be passed in by ref , which is not too good a practice, or you could use something like Code Contracts to ensure it's not null.
|
|
|
|
|
ref to a reference type is too much like a pointer to a pointer. However, this brings up a question I've had while trying to use C# on occasion for small projects to learn it. Are there equivalent const rules in C# (as acompared to C++) to help prevent the method from modifying the "pointer"?
If there were something like that, ref might not be so bad since it would be a performance increase (at least in theory since I wouldn't need the runtime checks on the reference.
Pete O'Hanlon wrote: which is not too good a practice
My knee-jerk reaction is to agree but if it would save the runtime checks, I'd be game to study the idea more.
None of my books really get into ref with reference types too much except the usual drive-by introduction. The best I've found is Richter's book but he basically says it's like a pointer to a pointer so I'm back to looking for a const solution like I would in C++. I'm not sure, but it seems const isn't really as much of a "thing" like it is in the C++ world.
I'm not familiar with "Code Contracts" so I'll give it some research time.
thanks.
|
|
|
|
|
bob16972 wrote: Are there equivalent const rules in C# (as acompared to C++) to help prevent the method from modifying the "pointer"
No. This has been one of the features I've bemoaned the absence of the most.
|
|
|
|
|
oo ouch. Design by contract...
"When using contracts, a supplier should not try to verify that the contract conditions are satisfied; the general idea is that code should "fail hard""
Hmmm. To be fair, I guess I use this everyday (in an indirect way) now that I think about it since most class libraries seem to conform to this (at least the "fail hard" part). However, I don't think that would work well for me and my pieces of the puzzle since not catching an exception will most likely result in the same behavior as a runtime error. I tend to feel exceptions are over used anymore but I try to keep an open mind about that subject.
|
|
|
|