Sunday, September 28, 2008

Writing Fast Code the easy way Part IV

Using Variables

Initializing

We all have a habit of initializing variables with their default values as soon as we declare them. We also have a tendency to assign the object variables to null when we think we don’t need the variable any more.

Well I thought the above procedure to be correct and a standard way, and I myself had advocated the way for quite some time in past until I found the following.

Once space for the object is allocated, it remains to initialize it (construct it). The CLR guarantees that all object references are pre-initialized to null, and all primitive scalar types are initialized to 0, 0.0, false, etc. (Therefore it is unnecessary to redundantly do so in your user-defined constructors. Feel free, of course. But be aware that the JIT compiler currently does not necessarily optimize away your redundant stores.)

What will we benefit if we don’t redundantly initialize the variable? Well it will be the CPU cycles that go into loading the variable in memory and assigning a value. Redundant Initializing is nothing but variable assignment! Same is true when we assign null to object references when they are supposed to go out of scope. GC will automatically collect those variables that have gone out of scope. If the object reference implements IDisposable, call the dispose() for sure, if its has close(), clear(), Stop(), and you don't need the object reference, make sure to call that method which is supposed to release the resources. Not doing above and setting it to null is leaking memory and in addition wasting CPU cycles.

Scope

When we write a function block we normally declare variables on top of the function, some people nicely declaring the primitive types in a section and object variable in a separate, which make the code look beautiful (I agree on that)

However when we want the GC to work efficiently for us and memory usage/leak is a concern, it’s always better to declare variables very near to the scope the variable will have.

Benefit,

  1. The memory allocation will take place only when required.
  2. The memory de-allocation will take sooner as GC will known that variable is no longer required as soon the variable will exit his scope.

Caching

Caching values is one of the best optimization techniques that I have found so far (of course writing efficient code has no match and I believe caching is part of that).

Always cache a property value if it’s used more more than once, and make a habit to cache a value returned from a function even more as generally the function has to do some data churning, may be DB access to get you the desired output. You can save those CPU cycles and memory allocations/de-allocations if you cache those values.


LOH (Large Object Heap)

I read on MSDN that LOH is not compacted like other generations. On another site I read that heavy allocation and de-allocation of large objects (size more than ~85K) will fragment LOH heavily and sooner or later a time will come that even though we will have sufficient free memory available, but all fragmented with no contiguous block. Requesting large object memory from GC at this juncture will result in OutOfMemory exception.

To address this problem currently I can think of the following:

  1. Don’t create objects which can possibly land up in LOH. Break them into smaller units.
  2. Don’t allocate and de-allocate large objects frequently, especially for server end applications as they are supposed to run 24x7 and they are sure candidate to fall in this trap.
  3. I don’t know for sure if reusing large object variable variables (without de-allocating and re-allocating) will help in this aspect, I will have to test this to be sure. You are welcome to post your comments if you have tried this before.

Sunday, September 7, 2008

Writing Fast Code the easy way Part III

Switch Vs If

Use of Switch instead of If whenever possible can be quite helpful, especially if its inside a loop or any code block which is executed frequently. It can give a performance boost up to 4 times !

Check out the sample skeleton code below and the performance readings for the same.

public void SwitchTest()

{

int i = 0;

while (LOOPCOUNT >= i++)

{

switch (i)

{

case 10:

break;

case 20:

break;

case 30:

break;

case 40:

break;

case 50:

break;

case 60:

break;

case 70:

break;

}

}

}

public void IfTest()

{

int i = 0;

while (LOOPCOUNT >= i++)

{

if (i == 10)

{

}

else if (i == 20)

{

}

else if (i == 30)

{

}

else if (i == 40)

{

}

else if (i == 50)

{

}

else if (i == 60)

{

}

else if (i == 70)

{

}

}

}



The above readings were generated with exact same code listed above and measured using DevPartner Performance expert. Its highly recommended that before applying any performance tips in your project, make sure to measure the performance yourself.