No overhead for a "get" accessor...

G

Guest

This is probably common knowledge to .Net gurus, but please bear with me
while I share a discovery with the group...

I needed to create a public lock on a class, as follows...

class Locked
{
.....
public object lockObject = new object();
}

Next I wanted to consider hiding the lockObject, according to good OO
practice, by making it private, and putting a public "get" accessor on it,...

class Locked
{
.....
private object lockObject = new object();
public object LockObject
{
get {return lockObject;}
}
}

However, I hesitated, because I didn't want the "overhead" of the accesor
each time a client gets a lock. I was curious as to whether there really is
an overhead, so ran ildasm on both versions of the exe. The dissasembled code
for the client was identical in both cases!

ie.

Locked l = new l;

lock (l.lockObject) {..}; // public member, no accessor

lock (l.LockObject()) {...}; // private member, "get" accessor

both compile to the same code. In other words, the compiler removes the
method call associated with the "get", and does it "in-line" (in C++
parlance).

The lesson... don't avoid accessors because of any perceived performance
issues.

Regards,

Javaman
 
D

Daniel O'Connell [C# MVP]

Javaman59 said:
This is probably common knowledge to .Net gurus, but please bear with me
while I share a discovery with the group...

I needed to create a public lock on a class, as follows...

class Locked
{
....
public object lockObject = new object();
}

Next I wanted to consider hiding the lockObject, according to good OO
practice, by making it private, and putting a public "get" accessor on
it,...

class Locked
{
....
private object lockObject = new object();
public object LockObject
{
get {return lockObject;}
}
}

However, I hesitated, because I didn't want the "overhead" of the accesor
each time a client gets a lock. I was curious as to whether there really
is
an overhead, so ran ildasm on both versions of the exe. The dissasembled
code
for the client was identical in both cases!

ie.

Locked l = new l;

lock (l.lockObject) {..}; // public member, no accessor

lock (l.LockObject()) {...}; // private member, "get" accessor

both compile to the same code. In other words, the compiler removes the
method call associated with the "get", and does it "in-line" (in C++
parlance).

The lesson... don't avoid accessors because of any perceived performance
issues.

It is a good lesson. I don't recall the compiler doing this myself, but the
JIT will inline simple properties pretty often if the compiler doesn't as
well. The only caveat is that the property cannot be virtual.
 
J

Jon Skeet [C# MVP]

Javaman59 said:
This is probably common knowledge to .Net gurus, but please bear with me
while I share a discovery with the group...

I needed to create a public lock on a class, as follows...

class Locked
{
....
public object lockObject = new object();
}

Next I wanted to consider hiding the lockObject, according to good OO
practice, by making it private, and putting a public "get" accessor on it,...

However, I hesitated, because I didn't want the "overhead" of the accesor
each time a client gets a lock. I was curious as to whether there really is
an overhead, so ran ildasm on both versions of the exe. The dissasembled code
for the client was identical in both cases!

both compile to the same code.

Hang on - what exactly are you talking about? They won't compile to the
same IL, but they *will* be JITted (in release mode, anyway) to the
same assembler code. Is that what you meant?
 
G

Guest

Apologies. I was wrong.

I've had another look at the IL code and found that in fact their is a
difference. I was looking at the wrong section of the code before.

The code with the accessor has this line, which I assume is calling the
accessor...

IL_0009: callvirt instance object Locked::get_LockObject()

and the code without the accessor has the following, which I assume is
loading the value of the "lockObject" variable.

IL_0009: ldfld object Locked::lockObject

Sorry to mislead you,

Javaman
 
G

Guest

Thanks Jon,
but they *will* be JITted (in release mode, anyway) to the
same assembler code. Is that what you meant?

No, that's not what I meant, but i was wrong. So, if we get back to the
original purpose of my little investigation, which was to determine whether
there is an overhead for using accessors, can I take it that the answer is
"no", for release mode?

Javaman
 
J

Jon Skeet [C# MVP]

Javaman59 said:
No, that's not what I meant, but i was wrong. So, if we get back to the
original purpose of my little investigation, which was to determine whether
there is an overhead for using accessors, can I take it that the answer is
"no", for release mode?

Indeed. You can easily check with cordbg though. Basically, the JIT is
free to inline method calls (and a property is basically a method or
two) below a certain size, and which don't do certain things.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top