Monday, June 15, 2009

Performance

Today I had to solve a common problem. The customer sad that the application is too slow; substantially the data import from an XML file into the object model is too slow. As every developer knows, performance problems are very nasty and it means also that you have to break your nice object oriented structure to gain some performance boosts :-(
So I searched in the imort routine for code parts which can be optimized. I was able to change some code but that brought only a very small performance gain.
After some time I decided to switch off the logging that states how many percent of the elements were already imported. That message was written to the console window and since the operation required about 15 seconds it was interesting to see at which point the import is.
Then the surprise. After switching off the logging the data was imported in about 1,3 seconds. I knew that writing to the console is slow but that it is so slow...
To solve this problem now I tried first to use an asynchronous event logging. It worked also quite well, but when the data was already loaded and displayed the logger wrote for some seconds longer to the console by indicating that 97% of the data was loaded now.
This was also not a choice. Then I decided that it would be a good idea to switch off logging when running in release mode and turn it on when running in debug mode. So I have all informations on hand whenn looking for errors and the performance for the customer.
To realize this I implemented in my logger a the method "LogDebugEvent" and "decorated" it with the "Conditional" attribute:
[Conditional("DEBUG")]
public void LogDebugEvent(LogLevel logLevel, string message, params object[] args)
{
/* some code here*/
}

This means that the compiler decides if the method call is executed or not. If you compile in Release mode than all calls to this method are removed from the code as if they do not exist. If you run in Debug mode then all calls are executed. This can be very usefull especially if you have code which slows down your program and is only for debug purposes.
Important is that it matches exactly the constant that you want to use. It is casesensitive!! In the case of debug it is as you can see in the example above "DEBUG".

More informations about the ConditionalAttribute can be found here and here.

2 comments:

Juri Strumpflohner said...

Good approach. I guess this is also how it should be done.
Breaking down your OO structure is in my idea always a bad approach, except you have very large data object that you have to keep in memory. Before breaking down nice OO structures I would always go/search for alternative solutions first, since 90% the problems lie somewhere else, as you correctly discovered, in your case when writing logs.
But interesting, the Conditional attribute. I usually compile, especially framework dlls in release mode of course, but I didn't know about the conditional attribute. There are #if statements (if I'm not wrong) for checking for release and debug mode, but the attribute is much more elegant.

Manfred said...

Hi,
yeah you are right. Breaking a nice structure is not a good thing; especially not for performance.
Yes the #if statement could also be used to achiev this, but I find the code is afterwards less readable and that is a thing that I try to avoid :-)