Groups | Blog | Home
all groups > dotnet performance > april 2006 >

dotnet performance : Local variables Vs Member Variables


Zeeshan Gulzar
4/13/2006 5:00:02 AM
I am writting a performance critical application and want to know about
following:

A method is called at every mouse move or says method calls frequently.
The method is like this

public void form_mouseup(object sender, EventArgs e)
{
int x = y * 12; //Here y is a member variable(int), defined at class
scope
// Process the variable x here
}

Variable x is initialized at every call in the above code. Although it is
created at stack but take some time and suppose x is a user-defined struct
with size of 120 Bytes. Is it best practice Or the following equivalent code.

public void form_mouseup(object sender, EventArgs e)
{
x = y * 12; //Here y is a member variable(int), defined at class scope
// Also x is also defined at class scope
// Process the variable x here
}

Another problem with this code is that every member variable either
reference type or value type which is defined at class scope is allocated at
heap instead of stack (in case of value type).

So, what is the performance penality in this case.

Also, please tell me about large user-defined structs. Suppose the struct
size is 200 Bytes long and pass it to Five methods as an argument so that
these methods update some UI Elements as well as entered it into databases or
perform some other tasks. It is possible to pass these arguments as valuetype
as well as reference type.

Struct's allocation is fast but frequently.
Class's allocation is slow than struct but not frequently because of just
passing a reference.

Please answer me which is best in respect of Speed and memory performance.

Thanks in advance
Marcus Andrén
4/13/2006 3:57:35 PM
Good programming practice is to limit the scope of variables. If it
only is used in one method, make it local. The performance difference
between local and member variables are minimal in most cases.

Only use structs when you need value semantics or if you are dealing
with an extreme amount of small objects.

Class adds an extra overhead of 8 bytes (I think) per instance, which
only makes a difference when dealing with very large amounts of small
objects.

The basic guideline to high performance:

1) Code the application. Don't bother about performance in this phase,
except for obvious architectual performance flaws. Instead make the
code readable and structured.

2) Run the application and measure the time spent in different parts
of the application.

3) If you have written unit tests already, good. Otherwise, you should
atleast write some for the parts of the code that need to be
optimized.

4) Optimize the bottlenecks. Keep the old readable code as a
reference. Make sure the optimized code is well commented.

Optimizing is a subject of its own. There are lots of different things
that can affect speed. The biggest performance gain is however usually
gained by choosing the correct algorithm/datastructure.

--
Goran Sliskovic
4/13/2006 7:34:23 PM

[quoted text, click to view]
....

Hi,

Before you start such optimization, measure the performance impact by
profiler first. Also, I suspect it is same time needed to allocate stack for
1 variable as for 1000, regardles of size. That would of course depend of
implementation. Usually, allocation on stack is only adding/substracting
stack pointer. It can be done once per every block regardless of number of
variables allocated.

Regards,
Goran

Ben Voigt
5/12/2006 6:40:35 PM

[quoted text, click to view]

If x is 120 bytes, it's likely that computing the values within takes a lot
more time than allocating the space. How often is x used? How often does y
change?

Make sure y is a property, not a field. Make a member field "private
Nullable<type x is> cachedx". The setter for y nulls cachedx. Your
function starts with the line:

sometype x = cachedx?? CacheX();

Then write a method CacheX() which creates a new object computed from the
value of y, saves a reference in cachedx and also returns it. CacheX()
shouldn't have side effects because it might not be called exactly once
every time y changes (less than once if y changes often, more than once if
multi-threading), nor every time x is used. Also, CacheX() should return
the object it created, not cachedx, because another thread could set cachedx
back to null meanwhile.

If x is used 10,000 times for each change to y, then you can get rid of the
test for null by caching x immediately when y changes (i.e. y's getter does
CacheX() instead of cachedx = null).

[quoted text, click to view]

AddThis Social Bookmark Button