Welcome to the "C# Performance Improvement Article Series". This is my third presentation. So if you are new to this series of articles then I will recommend you try to go through the following code.
if(!study (First && Second && Third) ){
-
5 tips to improve C# performance
-
5 tips to improve C# performance 1
-
5 tips to improve C# performance 2
}else{
Welcome to "5 tips to improve performance of C# code -part 3";
}
Ha.. Ha.., No, this is not my first point or I am not going to measure performance of this funny pseudo code. And like every article I repeat a few lines. I have tested the following code in my Core i3 CPU, 4GB primary memory and Windows 7 platform. If you are in a different hardware configuration or using a different platform then your output may vary with my output screen and the output may vary depending on your current running process. As all points are performance testing I have tested them in release mode and taken a screen shot in a stable situation for all the code. Let's start with tip number 1.
1. How you check empty string in your code?
In this point I am going to show you three empty or null string checking styles. I hope you are familiar with all styles but may not familiar with their performance. Let's start with a small example. In the following there are three functions (Yes all static. I am lazy, and don't want to create the object again). In the first style I am using the Length property. In the second I am using a space or empty string (" "). And in the third case I am using an Empty property of the string class. The following is my test code.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace Test1
{
public class Compare
{
public static void First(string Value)
{
if (Value.Length != 0)
{
}
}
public static void Second(string Value)
{
if (Value != "")
{
}
}
public static void Third(string Value)
{
if (Value != string.Empty )
{
}
}
}
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
Compare.First("Sourav");
sw.Stop();
Console.WriteLine("Using Length: "+sw.ElapsedTicks);
sw.Restart();
Compare.Second("Sourav");
sw.Stop();
Console.WriteLine("Using != " +sw.ElapsedTicks);
sw.Restart();
Compare.Third("Sourav");
sw.Stop();
Console.WriteLine("Using Empty: " + sw.ElapsedTicks);
Console.ReadLine();
}
}
}
And the output screen is:
We can see the Length measuring style (the first one) is taking the most time. And the String.Empty style is the least time consuming process.
So, the single line conclusion "Use of String.Empty to check whether the string is null or not".
2. Change your style of type casting
Yes, change it if you are not implementing the proper type casting technique. In the following I show two traditional styles of type casting and their performance impact on code. The first style (and the worst) is very simple, by using parenthesees () used by most of developers. And the second style is by the as keyword. In the following code I have implemented both of them. Let's go through the following code.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace Test1
{
public class Base
{
}
public class Derive : Base
{
}
class Program
{
static void Main(string[] args)
{
Derive d = new Derive();
Stopwatch sw = new Stopwatch();
sw.Start();
Base b =(Base) d;
sw.Stop();
Console.WriteLine("Using type cust : "+ sw.ElapsedTicks);
sw.Restart();
Base c = d as Base;
sw.Stop();
Console.WriteLine("Using as keyword : "+ sw.ElapsedTicks);
Console.ReadLine();
}
}
}
And here is the output screen:
Hmm.. Our popular worst technique is 6 times slower than the as keyword. Now, in this point I will not write single line conclusion, it's your choice of how to cast objects.
3. Efficient string comparison method
Yes, one more tip regarding strings. We know there are two popular string comparison methods we frequently use. One is the "operator ==" and another one is using the Equals() method of the String class.
One day I asked one of my colleagues "Which one do you like the most?" He replied the first one (in other words operator ==). And I asked him why? He replied "It's very simple, easy and from my first of C# learning I have been using it and I am happy with it, I will not change my style". Hmm, if you are also in that situation then I suggest you have a look at the output screen first then in the code.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace Test1
{
public class Test
{
public static void First(String Value)
{
for (int i = 0; i < 100; i++)
{
if (Value == "Sourav")
{
continue;
}
}
}
public static void Second(String Value)
{
for (int i = 0; i < 100; i++)
{
if (Value.Equals("Sourav"))
{
continue;
}
}
}
}
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
Test.First("Sourav");
sw.Stop();
Console.WriteLine("Using == : "+ sw.ElapsedTicks);
sw.Restart();
Test.Second("Sourav");
sw.Stop();
Console.WriteLine("Using Equals : "+ sw.ElapsedTicks);
Console.ReadLine();
}
}
}
You I have an attached calculator for quick calculation (Ha..Ha..). And the screen shows that the use of the "==" style is 190 times slower than the String comparison function (Equals()). Again I am not going to write single line conclusion. It's your responsibility to change your style and share the image above (output screen) to your friend in a lazy coffee break.
4. Impalement for loop with a little trick
Before starting I want to let you know something. It's not a very important point. Or it will be a very important trick to adapt. Here I will show how to implement our traditional for loop with a little spice. If you go through the following code then you will find in the second "for" implementation a local variable is using fewer times and that's why consumtion is less time but not very less. So, it's a best practice to use a variable less number of times.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace Test1
{
public class Base
{
public static void First(Int32 limit)
{
for (int i = 0; ++i <= limit; )
{
}
}
public static void Second(Int32 limit)
{
for (int i = limit; -- i >= 0; )
{
}
}
}
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
Base.First(100);
sw.Stop();
Console.WriteLine("First "+ sw.ElapsedTicks);
sw.Restart();
Base.Second(100);
sw.Stop();
Console.WriteLine("Second : "+ sw.ElapsedTicks);
Console.ReadLine();
}
}
}
In the following my output window is:
Let's write the single line conclusion "Be smart both in time of writing loop iteration code. (And with a new girlfriend.This tip is only for junior male developers, those who are my age.)"
5. Inheritance is a good practice but not always
We know one beautiful feature of OOP is inheritance, and it reduces code redundancy, improves code maintenance and so on. I am not denying them but my fifth point is against unnecessarily creating small classes here and there. If it is really not needed then don't create a class hierarchy. Have a look at the following code.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace Test1
{
public class Base
{
}
public class Derive :Base
{
public string name;
}
public class Concrete
{
public string name;
}
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
Derive d = new Derive();
d.name = "Sourav";
sw.Stop();
Console.WriteLine("Derive style : "+ sw.ElapsedTicks);
sw.Restart();
Concrete c = new Concrete();
c.name = "Sourav";
sw.Stop();
Console.WriteLine("Concrete class : "+ sw.ElapsedTicks);
Console.ReadLine();
}
}
}
At first I created two small classes and between them I am not at all using the first one. It's serving as base class. In the second scenario I have created a single concrete class; there is no concept of inheritance on it. And within the main () method I am creating an object of both of them. Let's see the output screen.
As the output screen says, object creation in a concrete class is much faster than a derived class style. Let's conclude with the single line comment "Don't implement class hierarchy if not needed."
Conclusion
Dear reader, thanks for completing this article by wasting your valuable time. (Because most readers do not read top to button, if you read, it's my personal achievement). All types of comments are welcome. (Waiting for dear Sam's comment, -- Dear Sam, this line is only for you".