|
Generic Do<T>() method's IL:
.method public hidebysig instance void Do(!T 'value') cil managed
{
// Code size 58 (0x3a)
.maxstack 2
.locals init ([0] int32 intV,
[1] bool V_1)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: box !T
IL_0007: isinst [mscorlib]System.Int32
IL_000c: brfalse.s IL_0022
IL_000e: ldarg.1
IL_000f: box !T
IL_0014: isinst [mscorlib]System.Int32
IL_0019: unbox.any [mscorlib]System.Int32
IL_001e: stloc.0
IL_001f: ldc.i4.1
IL_0020: br.s IL_0023
IL_0022: ldc.i4.0
IL_0023: stloc.1
IL_0024: ldloc.1
IL_0025: brfalse.s IL_0031
IL_0027: ldarg.0
IL_0028: ldloc.0
IL_0029: call instance void class ConsoleApp1.A`1<!T>::Do(int32)
IL_002e: nop
IL_002f: br.s IL_0039
IL_0031: ldarg.0
IL_0032: ldarg.1
IL_0033: call instance void class ConsoleApp1.A`1<!T>::DoDefault(!0)
IL_0038: nop
IL_0039: ret
} // end of method A`1::Do
|
|
|
|
|
yep, that's a call to the runtime to do a type check. See isinst?
i'll consider our bet a gentleman's bet =D
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
adding ugh - it's not only doing that, it has to box the value first!
i forgot about that. Ugh. It makes a copy of the int on the heap just to do a type check
No. Just no. Moral of this story is do not trust the C# compiler to significantly optimize your code.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
I have to say I am a little confused..
They have numerous intelligent blog about performance...
They have fair performance comparison against C++ code with well know perf test with many close call and sometimes better performance...
Though when one occasionally check the IL or assembly it seems not really good...
All of that leave me quite bewildered....
|
|
|
|
|
last i checked it's about 30% slower and that's according to their own benchmarks. I expect real world performance to be somewhat worse, if only because of the unconscious tendency to want to test the fast parts of the code.
occasionally you get better performance because of the JITs ability to do smart register allocation but the performance difference between that and C++ is barely significant in virtually all cases, and it doesn't crop up as regularly as MS would perhaps suggest.
There used to be some really good in depth articles about .NET performance that covered a lot of this stuff but as .NET has matured, it seems there are less of these today.
I don't normally care about cycle counting, but I do when the code has to be tight. Here it does, in my case.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
In general I've found a lot of my old habits I picked up in the 80s and 90s before i had access to really smart C++ compilers have served me well under .NET.
They say you don't have to be careful about heap allocation, and that's kind of true because of the way their garbage collected heap works, but it still costs. They claim the cost is "incrementing a pointer" - in reality that pointer gets incremented enough if forces the .NET host to do a garbage collection and reallocation which costs significantly. So basically all it's really doing is pushing the costs of each heap allocation down the road - and then "batches" the individual costs together when it does the mark, sweep and allocate.
They do too much heap allocation in .NET IMO. the IEnumerator pattern is a big culprit but not as much as boxing. Boxing/Unboxing just floors me. That slams the heap.
Fortunately the new reference types and stackalloc can alleviate this somewhat, but not nearly enough.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
you know what? I'm still kind of curious about this but I think I'm scrapping the specialization.
I'm not sure what I'm going to do about maintenance though. =( This will almost double the code size.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
|
Oops forget my previous example, I was confused.. the debug assembly code does indeed look atrocious...
Gotta try to check the release version
|
|
|
|
|
if there's a call in the resulting asm I'd need to see the IL to find out where it leads. I think the "is" comparison would result in a call to the CLR to type check
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
adding, my solution to the object creation was to have a method in the base class called CreateFA() that could be overloaded in order to force the base class to create the derived class. Unfortunately to get it to work I had to remove every static method that created objects from the base class =(
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
This has always worked.
You can't do that with static and/or non virtual method though, maybe that's what mislead you?!
|
|
|
|
|
oh i see what you did.
that's not template specialization. that's method overloading
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
yeah but... it behave quite similarly...
|
|
|
|
|
not really. only in the specific scenario where all you need is method overloading.
and even then it's not the same, because you have two separate classes in your code now instead of one.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
here let me give you an example of where it's not the same
...
FooBase DerivedMethod() {
return BaseMethod()
}
...
FooBase BaseMethod() {
return new FooBase();
}
...
in a specialization there are no base methods, so above would always return the fully derived class
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
You shouldn't look at object oriented programming as if you're working with objects. You should look at it objectively.
|
|
|
|
|
i know how to code OO. i just don't like OO because it requires a lot of code to do a little bit.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
When I was growin' up, I was the laziest kid I knew and I knew a lot of people. I'm still one of the laziest devs I know, but I make my deadlines and I know how to code myself out of a job.
Your problem might not be OO, but design patterns that contain more layers than lasagna like MVVM or have dependency injection.
Another issue might be .NET (assuming its what you work in)
I've started playing with python. If you wanted to get stuff done by doing as little as possible as often as possible with maximum results, Python is it.
|
|
|
|
|
In practice I agree with you about python
On principle I refuse to use a language with significant whitespace.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
Functional programing even worse.....
But it all started going wrong when we moved away from the abacus!
No one ever hacked my abacus!
Actually not quite true, think someone removed a bead....
|
|
|
|
|
Alan Kay, the father of OOP, says we're doing it all wrong and regrets using the word "object" as it emphasizes the secondary concern of OOP and ignores the primary concern of messaging. Lots of very smart computer scientists say modern OOP makes programming more complex and prone to error rather than simplifying it.
If you think 'goto' is evil, try writing an Assembly program without JMP.
|
|
|
|
|
i like message/signal based systems but most runtimes don't include some basics that should be "primitives/intrinsics" or otherwise first class, like thread safe priority queues and circular buffers and such. At the very least they should be runtime libraries provided with the base framework.
But I really think if Alan Kay had wanted a message based programming environment it should have been done somewhat differently than OOP.
think something a bit more along lines of parallel programming style constructs and the like, except instead of dealing with iterations of loops you're dealing with signalling.
honestly, it's easy enough to create a domain-specific set of "language extension" style headers in C++ to enable this. I love C++ for that. about 1/3 of the language is the headers and because of the way the preprocessor and template system works you can create your own pseudo language constructs. There's nothing else like it in major programming languages but I really wish their was.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|
|
Speaking of Alan Kay and C++...
Quote:
I made up the term 'object-oriented', and I can tell you I didn't have C++ in mind.
-- Alan Kay, OOPSLA '97
If you think 'goto' is evil, try writing an Assembly program without JMP.
|
|
|
|
|
if you're using OOP as your primary paradigm in C++ you're almost certainly Doing It Wrong(TM)
However, C++ is a truly multi-paradigm language and is fully capable of doing OOP programming.
But like I said, if Kay had messaging in mind, OOP probably wasn't the way to go.
You can implement a signal passing psuedo language extension in C++ to elegantly handle messaging passing.
You can implement an OOP system too, but I wouldn't recommend that.
When I was growin' up, I was the smartest kid I knew. Maybe that was just because I didn't know that many kids. All I know is now I feel the opposite.
|
|
|
|