|
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.
|
|
|
|
|
bob16972 wrote: are requiring asserts and runtime checks all over the frackin' place
I suppose that depends on what you mean by "all over the ...place" and what exactly your intent is.
In C++ I put parameter validation checks in public API methods.
In C# I put parameter validation checks in public API methods.
In either I might put some validation checks in other locations, but rarely do.
The API would decide what sort of parameters are needed - not whether I need to check it or not. Especially since in C++ it is possible to pass a reference to a pointer.
Your example code however doesn't suggest a parameter validation check but rather optional behavior it the parameter is null. That of course must be dealt with regardless.
Finally null pointer exceptions in C# have stack traces on them. So arbitrary programming errors show up that way. Especially with sufficient unit testing.
|
|
|
|
|
jschell wrote: I suppose that depends on what you mean by "all over the ...place" and what exactly your intent is.
All over the place meaning, I use objects (all over the place) which require references which can be null. Any internal, public, protected methods can be called by code that does not necessarily know my assertions inside the method. Because of this, all references that could be null need to be checked (private methods can sometimes omit this as I stated) before they are used (unless it's just passing through of course).
jschell wrote: In either I might put some validation checks in other locations, but rarely do.
Good luck with that.
jschell wrote: Finally null pointer exceptions in C# have stack traces on them. So arbitrary programming errors show up that way. Especially with sufficient unit testing.
That's assuming your debug sessions will take a particular code path; unit tests can get stale as code changes. Since this might not be reliable, the runtime checks are usually the last stand to prevent runtime errors and replace them with graceful hickups or alternative behavior.
This coding style is MFC 101 and can be applied where ever pointers are sold. Since the C# references can be null, this approach almost appears mandatory but that is the question at hand.
|
|
|
|
|
bob16972 wrote: Good luck with that.
Been programming 40 years myself. And my delivered software tends to have much lower bug counts compared to peers.
It has nothing to do with luck and everything to do with attention to detail. Assertions "all over the place" would not help with that.
Should note as well that I can't recall the last time I had to deal with a null pointer reference in my code. I can however remember dealing with them in other peoples code.
bob16972 wrote: That's assuming your debug sessions will take a particular code path
Code coverage tools. Great investment.
bob16972 wrote: unit tests can get stale as code changes.
That is a process problem not a technology problem.
And the unit tests on the code that I maintain do not get stale.
bob16972 wrote: Since this might not be reliable, the runtime checks are usually the last stand to prevent runtime errors and replace them with graceful hickups or alternative behavior.
The behavior of asserts do not fall into that categorization.
You can write a class easily in C# and C++ for that matter that provides a rudimentary Aspect programming context for checking a modest number rules including null pointers.
bob16972 wrote: This coding style is MFC 101 and can be applied where ever pointers are sold.
Pointer bugs which occur in C++ do not apply to C# (nor to java for that matter). A system OS exception is only one possibility that might occur due to a C++ pointer bug and is actually one of the easiest to locate and fix.
Other than that having written C++ for 20 years I got by quite comfortably without scattering asserts all over my code - and again with a much lower bug rate for my code base that others.
bob16972 wrote: Since the C# references can be null, this approach almost appears mandatory but that is the question at hand.
And perhaps you would be better off with an Aspect type language. A quick google suggests that that exists in some form for C# from different sources. Java has AspectJ which is a full Aspect language. Something similar might exist for C#.
|
|
|
|
|
bob16972 wrote: Someone please tell me there is a way to eliminate all these checks for null references in C# like I could in C++.
Hm, there is nothing like "null reference" in a C++ program. This would require dereferencing a null-pointer which immediately results in undefined behaviour of the rest of the program. If you pass an object by reference in C++, you implicitly state that this object cannot be a reference to null object by definition.
In managed code you can use explicit code contracts. CCs allow you to make explicit assumptions about pre-, post- or state-conditions which are verifiable at compile- and run-time. You formulate contracts at metadata level so they get injected into IL in AOP manner:
[ContractClass(typeof(ISomethingContract))]
public interface ISomething {
public void DoSomething(AnotherClass pObject);
}
[ContractClassFor(typeof(ISomething))]
internal abstract class SomethingContract : ISomething {
public void DoSomething(AnotherClass pObject) {
Contract.Requires(pObject != null);
}
}
}
|
|
|
|
|
That's because C++ references are syntactic sugar to make C++ easier for VB developers who wander over.
|
|
|
|
|
Hey now. I like C++ references and I despise VB with a passion.
|
|
|
|
|
Hi.
I don't think that passing as a reference really gets rid of the need for null checks. You can satisfy the rule for an actual object by dereferencing a pointer. That satisfies the compiler but the pointer could still be NULL. Consider this working C++ code.
void NameList::Append(NameList *ToBeAdded)
{
Members->Append(*ToBeAdded->Members);
ToBeAdded->Members->RemoveAll();
} where "Members" is defined as
CObArray *Members and the CObArray member Append is defined as
INT_PTR Append(const CObArray& src); so if the "ToBeAdded" Namelist Object has a Members field that contains NULL, the compiler is OK with that and the Append function should really do ASSERT and/or runtime checks.
In any event, I don't think you can rely on the & to protect against somebody passing NULL.
Chuck (45 years coding and counting)
|
|
|
|
|
Are you referring to what is described in the C++ Specification, Section 8.3.3, page 179 ?
"A reference shall be initialized to refer to a valid object or function. [ Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer, which causes undefined behavior. As described in 9.6, a reference cannot be bound directly to a bit-field. —end note ]"
Your point is taken but I think in the case you described, the violation occurs by the caller and before the prolog of the method completes. If the caller violates the standard definition of a reference, there is nothing I can do about it. I'm not even sure there is a way to check the reference for validity since the result of the action you described would be undefined (or at least, so it seems).
|
|
|
|
|
Well, I was simply reacting to your statement in the original post,
In my experience, when some code assumes things cannot be null, that's exactly where to start looking for bugs. And if you're assuming that a "by reference" specification removes some level of bug enough that you can remove the ASSERT / checks, then I wanted to show an example (real, not concocted) that shows the assumption to be false.
And then you asked for a way to eliminate such checks from C# code like you could from C++ code, which I infer to mean that you have such checks, find them somewhat inefficient and/or redundant in well behaved programs, and would like to remove them using some help from the language. Again, I wanted to point out that the C++ language does not give you any help either and that your trust in it was misplaced.
Now your reply says
bob16972 wrote: the violation occurs by the caller and before the prolog of the method completes. If the caller violates the standard definition of a reference, there is nothing I can do about it. I'm not even sure there is a way to check the reference for validity since the result of the action you described would be undefined (or at least, so it seems).
which seems like an reasonable argument to remove all checks anyway since there's nothing you can do when the caller violates some rules, including the assumed rule that they'll pass something reasonable.
Look, all I'm saying is that if you are writing public API entries, for other programmers to call, you're better off including the checks all the time. Yes, "null pointers" are just one element in the set of all possible bad arguments and checking for them will never catch the case of the pointer being 0x00000001 or 0xcdcdcdcd (assuming 32-bit pointers) but ASSERTs may catch enough during debugging that may make debugging easier.
|
|
|
|