DCSIMG
On the Risks of Labeling - "Premature Optimization" - All Your Base Are Belong To Us

All Your Base Are Belong To Us

Mostly .NET internals and other kinds of gory details

On the Risks of Labeling - "Premature Optimization"

This post really got me.  The writer describes a system design conversation, when one of the arguments is that inheritance in .NET is a possible cause of performance degradation.  The author then continues to test this "degradation" using the following setup (deduced from the original post):

class Animal {
    private int _legs;
    public virtual int Legs { get { return _legs; }
}
class Dog : Animal { }
...
foreach (Animal a in animals) {
    int i = a.Legs;
}
foreach (Dog d in dogs) {
    int i = d.Legs;
}

He then thoughtfully concludes that inheritance has no performance impact, in view of his measurements.

Let's just ignore all the issues concerning the actual value of this kind of measurement, and try to focus on the original statement.  Why would accessing a property on an object be affected by the inheritance chain of the object's type?

To really understand this kind of thing, you need to have virtual method dispatch memorized by heart.  It's not rocket science really, but few developers (especially .NET developers) are aware of it.  Consider the JITted code generation for accessing a property on the Animal object as opposed to accessing it on a Dog object, in this simplified scenario:

Animal a1 = new Dog();
int i = a1.Legs;
Animal a2 = new Animal();
i = a2.Legs;

...
0000001f mov rax,qword ptr [rbx]
00000022 mov rcx,rbx
00000025 call qword ptr [rax+60h]
...
00000042 mov rax,qword ptr [rbx]
00000045 mov rcx,rbx
00000048 call qword ptr [rax+60h]

(Note that this is 64-bit assembly language; it's not essentially different from 32-bit, so I didn't bother forcing a 32-bit environment.)

I've snipped everything irrelevant to the discussion.  Note how absolutely identical the code is for both properties.  If you have the theory behind you, it's also absolutely obvious why this is so - the method table entry for the Legs property will always be at the same offset for any derived type of Animal.  You can continue the derivation hierarchy forever; it will still be the same code to access the property, and the same slot in the method table.

What if the property discussed in the original post was not virtual?  I considered leaving this as an exercise for the reader...  But here goes.  Accesing a non-virtual property as trivial as this one is obviously going to be inlined.  The property's backing field is stored in the Animal class part; if we have a Dog object, it must be at the same offset.  Here's the relevant code generation:

...
0000001f cmp byte ptr [rbx],0
00000022 mov eax,dword ptr [rbx+8]
...
0000003f cmp byte ptr [rbx],0
00000042 mov eax,dword ptr [rbx+8] 

Surprised?  By now you really shouldn't be.  The property is stored at the very same offset in both cases, and therefore the inlined code to access it is absolutely identical.  (Theoretical side note: the first instruction in each pair merely enforces a null reference check, to ensure that we are not calling a method or accessing a property on a null reference.  Note that we don't have to do anything with the result of the comparison - it's the very fact that we dereference the reference, as in [rbx], which would cause an access violation, which would be trapped by the CLR and converted to a NullReferenceException.)

So what can we conclude from this brief analysis?  That comparing a piece of code to an absolutely identical piece of code will yield identical performance for both pieces of code.  Stunning, really.

Comments

Justice~! said:

You had a good point.  

It might've been great

If you didn't come off

like a nerd full of hate.

It surprises me that a

self-proclaimed MSIL master

Would make such an elementary posting disaster.

A suggestion: if you want to your readers engage,

I'd recommend not writing like you're pent-up with rage.

Making friends through your blogging is "not rocket science",

So why on your anger is there so much reliance?

# November 7, 2007 1:44 AM

Sasha Goldshtein said:

I could hardly imagine someone actually being hurt by my post.  I never claimed to excel in writing; all I try to offer is technical content, hopefully interesting for my readers (and for myself to formalize in written text).

If we were to engage in a serious discussion, I'd probably say that it's much more important for me to correct a technical error in someone else's post (and it doesn't matter if it has higher popularity than mine) than to make friends through my blogging.

Thanks for your time reading this.

# November 7, 2007 8:50 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 


Enter the numbers above: