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.

Saturday, September 6, 2008

Writing Fast Code the easy way Part II

Writing If conditions

The way we write If conditions can dramatically affect the performance, especially if its in a loop churning out lot of data.

Check out following two sample code (the If conditions are meaningless and are just put to simulate some conditional processing)

public void IfNested()

{

int i = 0;

while (LOOPCOUNT >= i++)

{

if (i > 20)

{

if (i > 40)

{

if (i > 60)

{

}

}

}

}

}

public void IfCombined()

{

int i = 0;

while (LOOPCOUNT >= i++)

{

if (i > 20 && i > 40 && i > 60)

{

}

}

}

Out of the above two, combined condition is a winner as it benefits from conditional short circuiting optimization in .net. It’s also always a good move to put such conditions first in order which can help the runtime to skip executing unnecessary code blocks in advance.

If( CondA && CondB && CondC) is a good one if we know that CondA can be false most of the times. If CondC is the one which can be false most of the times, the if block should be written as If( CondC && CondB && CondA).


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.



Writing Fast Code the easy way Part I


String or StringBuilder?


Which is better string or StringBuilder? We all know that StringBuilder is the better choice. Really? If yes, then by what ratio.

Let’s check it out.

We have following code blocks which perform exactly same, but are written in different ways

private const int LOOPCOUNT = 1000;

private void StringBuilderAppend()

{

StringBuilder _subElementValue = new StringBuilder();

int i = 0;

while (i++ <= LOOPCOUNT)

{

_subElementValue.Append("_xmlStart");

_subElementValue.Append("nav3Name");

_subElementValue.Append("_xmlEnd");

_subElementValue.Append("nav3.Value");

_subElementValue.Append("_xmlEndStart");

_subElementValue.Append("nav3Name");

_subElementValue.Append("_xmlEnd");

}

}

private void StringConcatenate()

{

int i = 0;

string sTemp = "";

while (i++ <= LOOPCOUNT)

{

sTemp += "_xmlStart";

sTemp += "nav3Name";

sTemp += "_xmlEnd";

sTemp += "nav3.Value";

sTemp += "_xmlEndStart";

sTemp += "nav3Name";

sTemp += "_xmlEnd";

}

}

As expected code block using StringBuilder.Append is quite fast compared to the string += operations. It’s 347 times faster than the string += operations! It’s a clear choice when concatenating multiple strings. What if we need the fastest code to be a little faster without killing the code readability and jumping into unsafe codes?

The following code is much faster than the StringBuilderAppend method. It’s faster by a factor of 2.4 times. What we simply did was used multiple string + operations (note there is no +=) and appended it in a StringBuilder.

private void StringBuilderAndStringConcatenate()

{

StringBuilder _subElementValue = new StringBuilder();

int i = 0;

while (i++ <= LOOPCOUNT)

{

_subElementValue.Append("_xmlStart" + "nav3Name" + "_xmlEnd" + "nav3.Value" + "_xmlEndStart" +

"nav3Name" + "_xmlEnd");

}

}



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.

Tuesday, May 27, 2008

Get Corners of a Rectangle, given the center,height and Width

Following code will draw a rectangle on a graphics context, when a valid center, height and width is provided.


int CenterX, CenterY;

public void DrawRect(Graphics g, int Width, int Height)

{

Point[] RectPts;

double Theta;

int HalfWidth, HalfHeight;

double Radius;

RectPts = new Point[4];

HalfWidth = Width / 2;

HalfHeight = Height / 2;

Radius = Math.Sqrt(HalfWidth * HalfWidth + HalfHeight * HalfHeight);

Theta = Math.Acos(HalfWidth / Radius);

RectPts[0] = GetPt(Theta, Radius);

RectPts[1] = GetPt(Math.PI - Theta,Radius);

RectPts[2] = GetPt(Math.PI + Theta,Radius);

RectPts[3] = GetPt(-Theta,Radius);

Pen PenColor = new Pen(Color.Red, 2);

g.DrawPolygon( PenColor, RectPts);

PenColor.Dispose();

}

private Point GetPt(double Offset, double Radius)

{

double tAngle;

Point temp = new Point();

double Rotation = 30;

tAngle = Rotation / 180 * Math.PI + Offset;

temp.X = CenterX + (int)(Radius * Math.Cos(tAngle));

temp.Y = CenterY + (int)(Radius * Math.Sin(tAngle));

return temp;

}

The code idea is copied from some site and converted to C# in a compilable and working format. Hope it helps.


Tuesday, April 15, 2008

How to use CompuWare DevPartner for Memory profiling of .net Windows Services

I have been using the Compuware Devpartner studio for quite some time for profiling our application for memory and performance, and I found it quite useful. Recently we had a memory leak issue in one of our windows service. I tried using the DevPartner profiling for memory on it, but alas I could not profile a service!!

This was a setback and now I was in a fix. Either I have to explore new profiling tools to get my job done or dive into the vast code and find the issue. I decided to spend some time on finding if there is some other way to profile the windows services using DevPartner. I Googled a lot and could not find anything :(

Later out of frustration I looked into the installation directory, and found lots of exe’s and out of curiosity I opened them one by one. To my pleasant surpise I found one exe DPAnalysis.exe which was what I wanted. It was a command line tool for doing all sorts of supported Analysis

  • Performance
  • Coverage
  • Memory
  • Performance expert

Following is the help output from that exe, which explains all the different command line arguments.

Usage:

1) DPAnalysis [a] [b] [c] [d] {e} target [target args]

2) DPAnalysis /config config.xml

a) AnalysisType: Set the run-time analysis type. Performance is default.

/PERF[ORMANCE] Set analysis type to DevPartner Performance Analysis

/COV[ERAGE] Set analysis type to DevPartner Coverage Analysis

/MEM[ORY] Set analysis type to DevPartner Memory Analysis

/EXP[ERT] Set analysis type to DevPartner Performance Expert

b) DataCollection: Enable/Disable data collection for a given target.

DOES NOT LAUNCH the target.

/E[NABLE] Enable data collection for the specified process or service

/D[ISABLE] Disable data collection for the specified process or service

c) OtherOptions:

/O[UTPUT] Specify the session file output directory and/or name with optional extension (.dpprf, .dpcov, .dpmem, or .dppxp)

/W[ORKINGDIR] Specify the process' working directory

/H[OST] Specify target's host machine

/NOWAIT Don't wait for process to exit, just wait for it to start

/N[EWCONSOLE] Run the process in its own command window

d) AnalysisOptions:

/NO_MACH5 Disables excluding time spent on other threads

/NM_METHOD_GRANULARITY Set data collection granularity to method-level (line-level is default)

/EXCLUDE_SYSTEM_DLLS Exclude data collection for system dlls (Perf only)

/NM_ALLOW_INLINING Enable run-time instrumentation of inline methods

/NO_OLEHOOKS Disable collection of COM

/NM_TRACK_SYSTEM_OBJECTS Track system object allocation (Memory only)

e) TargetType: Identify target process or service. MUST BE LAST OPTION.

All arguments after the target name/path are passed directly to the target.

/P[ROCESS] Target is an exe filename (followed by arguments to the process)

/S[ERVICE] Target is a service name (followed by arguments to the service)

2)

/C[ONFIG] Path to configuration file that includes all startup information. Note: no other options can be used with /Config



For profiling the windows service I used the following command”

DPAnalysis /MEM /E /S “my service name”

After running the above using a command prompt, I started the service from service controller, and let the service do its job. I monitored the memory usage and VM Size of service using task manager, and when I was convinced that the memory leak condition is reached, I stopped the service. I was prompted for saving the memory analysis file :), which could be easily opened up in VS2005 (of course because DevPartner was installed)


Thursday, March 20, 2008

Check List for Creating/updating a Installer

A simple checklist that i see quite helpful before one start on updating or creating a installer.

Assembly Name
Installation Path
Component Name
Parent Component
Mandatory Component?
COM component?
Requires Registration?
Install in GAC
Pre-Requisites
Supported OS
Supported .Net Platform
Special Service Pack requirement
Third Party Product Dependencies
Any Specific Requirements
Remove on Un-Install
Default Configuration (registry keys)
Shortcut Required?

Background Threads and Thread priority

Background Threads

When we create a thread, often we don’t change the IsBackground property, so by default it’s created as a foreground thread. A foreground thread and a background thread are identical in all respects, except that the foreground thread has a message pump to handle UI messages. A choice of making a thread FG (foreground) or BG (background) may affect how your application behaves when it’s terminated. A FG thread may keep the application alive if it’s not stopped from what its doing, however the managed runtime will close all BG threads cleanly without throwing any exceptions. This is true only if it’s a process shutdown. A BG thread will throw same ThreadAbortException as FG when its terminated using Abort() or due to some other error in code its executing.

Thread priority

Setting thread priorities is a tricky job and it’s not recommended to change it for fun unless the requirements dictate to do so. .net provides 5 states in thread priority

A thread can be assigned any one of the following priority values:

  • Highest
  • AboveNormal
  • Normal
  • BelowNormal
  • Lowest

By default a thread is created with Normal priority. Setting thread priorities does not guarantee that the OS will not change the priorities dynamically; it’s just a recommendation from our end to the OS to run the thread on specified priority, which generally the OS honors.

Even when running two threads with same priority and one set as a FG and other as BG, the threads will be scheduled differently. I have observed that running one FG and other in BG in tight loop (no sleeps and joins in the thread) will have a drastic change in scheduling based on if the application window is in focus or not.

Following image shows that when the application is not a foreground window, both the threads are scheduled with equal time slice and we can see messages printing from both threads in succession.

The behavior changes when the application receives focus as can be seen from image below.

This can be considered normal as a foreground application received a dynamic priority boost by the OS, which allows for more CPU time slice for all the threads in the application.

Sunday, February 17, 2008

Use of EventWaitHandle

Ever faced a problem where the application does not close even after the main form is closed? If yes, one reason could be the threads you are using. If you are using some threads that run a infinite loop which perform some operation at some intervals with a interval of some minutes or more, and you are using Thread.Sleep(), read further.

Consider the following class code snippet.

public class ThreadTest

{

Thread thSettingsMonitor = null;

bool _stopTimeOutProcessing = false;

public override string ToString()

{

return "Thread running state is : " + this._stopTimeOutProcessing.ToString();

}

public void Start()

{

thSettingsMonitor = new Thread(new ThreadStart(ReloadSettings));

thSettingsMonitor.Start();

Debug.WriteLine("~~~ Starting the thread. Hash code: " + this.GetHashCode().ToString());

}

public void Stop()

{

try

{

//set the variable so that the loop breaks and thread terminates

_stopTimeOutProcessing = true;

}

catch { }

}

private void ReloadSettings()

{

while (!_stopTimeOutProcessing)

{

try

{

//do some operation in the thread

//Mimic by a sleep of 2 seconds

Thread.Sleep(2000);

//wait for 5 minutes

Debug.WriteLine("~~~ reload thread waiting on sleep for 5 min. Hash code: " + GetHashCode().ToString());

Thread.Sleep(30000);

Debug.WriteLine("~~~ Sleep period completed");

}

catch (Exception ex)

{

Debug.WriteLine(ex);

}

}

}

}

Now in a windows application form write the following code

private ThreadTest othTest = new ThreadTest();

private void button1_Click(object sender, EventArgs e)

{

//Start the reloadsettings thread

othTest.Start();

}

private void FrmTest_FormClosing(object sender, FormClosingEventArgs e)

{

othTest.Stop();

}

Run the code, click on the button so that the thread starts running. Try closing the form. Note that the form closes but the .net IDE does not breaks until some time. This means that some code is still executing. Click on the pause button of .net IDE to see which code is running. You will notice that the thread code Thread.Sleep(30000); is still executing.

Now try the updated code.

public class ThreadTest

{

Thread thSettingsMonitor = null;

bool _stopTimeOutProcessing = false;

private EventWaitHandle _exitEvent = new EventWaitHandle(false, EventResetMode.ManualReset);

public override string ToString()

{

return "Thread running state is : " + this._stopTimeOutProcessing.ToString();

}

public void Start()

{

thSettingsMonitor = new Thread(new ThreadStart(ReloadSettings));

thSettingsMonitor.Start();

Debug.WriteLine("~~~ Starting the thread. Hash code: " + this.GetHashCode().ToString());

}

public void Stop()

{

try

{

//set the variable so that the loop breaks and thread terminates

_stopTimeOutProcessing = true;

if (_exitEvent != null)

{

Debug.WriteLine("~~~ Signalling the timeout thread. Hash code: " + this.GetHashCode().ToString());

_exitEvent.Set();

Debug.WriteLine("~~~ Signalling the timeout thread done. Hash code: " + this.GetHashCode().ToString());

}

}

catch { }

}

private void ReloadSettings()

{

while (!_stopTimeOutProcessing)

{

try

{

//do some operation in the thread

//Mimic by a sleep of 2 seconds

Thread.Sleep(2000);

//wait for 5 minutes

Debug.WriteLine("~~~ reload thread waiting on eventwait object for 5 min. Hash code: " + GetHashCode().ToString());

_exitEvent.WaitOne(300000, true);

Debug.WriteLine("~~~ done waiting or the eventwait object was signaled");

}

catch (Exception ex)

{

Debug.WriteLine(ex);

}

}

}

}

Run the code and note the difference. This time the application closes immediately.

Let’s understand what was different.

private EventWaitHandle _exitEvent = new EventWaitHandle(false, EventResetMode.ManualReset);

Here we created a thread synchronization object with initial state as non signaled and mode as manual.

Instead of Thread.Sleep(2000); we have now used _exitEvent.WaitOne(300000, true); this instructs the thread to wait for 5 minutes (30000 msec) and exit the wait before the time is elapsed if the event object is signaled.

During form close we have used _exitEvent.Set();. This code signals the event object. When the event object is signaled the thread comes out of wait immediately even before the wait time is completed. The EventWaitHandle is a versatile object when it comes to thread synchronization. Explore it if you are writing multi threaded applications.

PS: The above problem can be easily worked out in normal scenario by setting the thread as a background thread. The only problem it will have is it will be aborted immediately during application close.


Happy coding!