Wednesday, 5 June 2013

C# optimization

1. Boxing and unboxing

static private void TestBoxingAndUnboxing()
{
int i = 123;
object o = i; // Implicit boxing

i = 456; // Change the contents of i

int j = (int)o; // Unboxing (may throw an exception if the types are incompatible)
}

//this function is about 2*Log(N) faster
static private void TestNoBoxingAndUnboxing()
{
int i = 123;

i = 456; // Change the contents of i

int j = i; // Compatible types
}

2. Collections


//Using actual size for data rather than some default size increases performance up to 50%
ht = new Hashtable(count); // Creates an Hashtable using size = Count
LoadData(ht, count);


// Display results
Display.Show(1, "Elapsed time: " + t.ElapsedTime.ToString() + " ms \n", 0);

// End of the demo
Display.Show(-1, "Collections demo end.\n", 1);
}

static private void LoadData(Hashtable ht, int Count)
{
// Fill the employee collection with data
for (int i = 0; i < Count; i++)
{
Employee employee = new Employee(i, "Employee" + i.ToString());

ht.Add(i, employee);
}

3. Exceptions


//throwing and catching an exception is 1000 slower than checking for an error code
static void FunctionThatThrows()
{
throw new Exception();
}

static int FunctionThatReturnsErrorCode()
{
return -1;
}

4. Loops

//for loop is twice faster than foreach loop
static private void TestForeachLoop(ArrayList List)
{
int id = 0;

foreach (int i in List)
{
// Do something with the object ...
id = i;
}
}

static private void TestForLoop(ArrayList List)
{
int id = 0;
int count = List.Count;

for (int i = 0; i < List.Count; i++)
{
// Do something with the object ...
id = (int)List[i];
}
}

5. Garbage collection

//80% slower than doing nothing
static private void Test(int count)
{
DisposableObject []obj = new DisposableObject[count];
for(int i=0;i<count;i++)
obj[i]=new DisposableObject();

// Do some work with the object here ...

// Release the object.
obj = null;

// Forcing garbage collection to finalize the object.
Collect();
// Wait for the GC's Finalize thread to finish.
WaitForPendingFinalizers();
}
//150% slower than doing nothing
static private void TestDispose(int count)
{
DisposableObject []obj = new DisposableObject[count];
for(int i=0;i<count;i++)
obj[i]=new DisposableObject();
// Do some work with the object here ...

// Release the object.
for(int i=0;i<count;i++)
obj[i].Dispose();
obj = null;

// Forcing garbage collection to finalize the object.
Collect();
// Wait for the GC's Finalize thread to finish.
WaitForPendingFinalizers();
}
//best solution
static private voide LetDotnetCleanup(int count)
{

// Start performance timing
t.Start();
int count=int.Parse(args[0]);
DisposableObject []obj = new DisposableObject[count];
for(int i=0;i<count;i++)
obj[i]=new DisposableObject();

// Do some work with the object here ...

// Release the object.
obj = null;

t.Stop();
// Stop performance timing
}
 

6. Locks //ReaderWriterLock is 20 times slower than lock

ReaderWriterLock rwl = new ReaderWriterLock();
int m_Value = 0;

public int ReadUsingReadWriteLock(Int32 threadNum)
{
int Value = 0;

Console.WriteLine("Start Resource reading using ReadWriteLock (Thread={0})", threadNum);

t.Start();
rwl.AcquireReaderLock(Timeout.Infinite);

try
{
Value = m_Value;
}
finally
{
rwl.ReleaseReaderLock();
}
t.Stop();

Console.WriteLine("Stop Resource reading using ReadWriteLock (Thread={0})", threadNum);
Display.Show(1, " Elapsed time: " + t.ElapsedTime.ToString() + " ms \n", -1);

return Value;
}
public int ReadUsingLock(Int32 threadNum)
{
int Value = 0;

Console.WriteLine("Start Resource reading using lock(this) (Thread={0})", threadNum);

t.Start();
lock(this)
{
Value = m_Value;
}
t.Stop();

Console.WriteLine("Stop Resource reading using lock(this) (Thread={0})", threadNum);
Display.Show(1, " Elapsed time: " + t.ElapsedTime.ToString() + " ms \n", -1);

return Value;
}

7. Stack and Heap

N structures are Log(N) faster to allocate than N classes
class ClassObject
{
public int x;
}

struct StructObject
{
public int x;
}
//alloc structs
tAllocation.Start();
for (i = 0; i < repeat; i++) // repeat to get more acurate timing
s = new StructObject();
tAllocation.Stop();

//alloc objects
for (i = 0; i < repeat; i++) // repeat to get more acurate timing
c = new ClassObject();
  Reference http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/highperfmanagedapps.asp

C# optimization

How can we optimize a program? We can add performance optimizations to C# programs. High-level considerations, and factors external to your code, are often most important. But there are many low-level performance optimizations we can do that improve performance.
Overview In this overview, we describe the general considerations when optimizing your C# code. First the C# language is compiled, and with the .NET Framework, you can attain performance close to languages such as C or C++. Generally, using the simplest features of the language provides the best performance. For example, using the for-loop and avoiding parameters and return values is typically fastest. You must balance these performance goals with code readability and understandability.
Benchmark At all levels of performance optimization, you should be taking measurements on the changes you make to methods. You can do this with the .NET Framework methods available in the Stopwatch type. It often pays to create a multitude of console programs where the methods are benchmarked repeatedly on data as it changes.
Static methods In the C# language, non-inlined instance methods are always slower than non-inlined static methods. The reason for this is that to call an instance method, the instance reference must be resolved, to determine what method to call. Static methods do not use an instance reference. If you look at the intermediate language, you will see that static methods can be invoked with fewer instructions. You can see an experiment based on the callvirt and call instructions on this site.
Avoid parameters When you call any method that was not inlined, the runtime will actually physically copy the variables you pass as arguments to the formal parameter slot memory in the called method. This causes stack memory operations and incurs a performance hit. It is faster to minimize arguments, and even use constants in the called methods instead of passing them arguments. Avoid local variables When you call a method in your C# program, the runtime allocates a separate memory region to store all the local variable slots. This memory is allocated on the stack even if you do not access the variables in the function call. Therefore: You can call methods faster if they have fewer variables in them. One way you can do this is isolate rarely used parts of methods in separate methods. This makes the fast path in the called method more efficient, which can have a significant performance gain. Arithmetic Expression Optimization
Constants In the .NET Framework, constants are not assigned a memory region, but are instead considered values. Therefore, you can never assign a constant, but loading the constant into memory is more efficient because it can injected directly into the instruction stream. This eliminates any memory accesses outside of the memory, improving locality of reference.
Static fields Static fields are faster than instance fields, for the same reason that static methods are faster than instance methods. When you load a static field into memory, you do not need the runtime to resolve the instance expression. Loading an instance field must have the object instance first resolved. Even in an object instance, loading a static field is faster because no instance expression instruction is ever used.
Inline methods Unlike the C++ language, the C# language does not allow you to suggest a method be inlined into its enclosing method call spots. Often, the .NET Framework is conservative here and will not inline medium-sized or large methods. However: You can manually paste a method body into its call spot. Typically, this improves performance in micro-benchmarks, and it is really easy to do. However, it will make code harder to modify. It is only suggested for a few critical spots in programs.
Switch You will find that the switch statement compiles in a different way than if-statements typically do. For example, if you use a switch on an int, you will often get jump statements, which are similar to a computed goto mechanism. Using jump tables makes switches much faster than some if-statements. Also, using a char switch on a string is fast.

Flatten Array Jagged arrays While flattened arrays are typically most efficient, they are sometimes impractical. In these cases, you can use jagged arrays to improve the lookup performance. The .NET Framework enables faster accesses to jagged arrays than to 2D arrays. Jagged Array Examples Please note: Jagged arrays may cause slower garbage collections, because each jagged array element will be treated separately by the garbage collector.

String concatenation instead of StringBuilder

String concatenation works in such a way that every time when you add something to a string, a new address in the memory is being allocated. The previous string is copied to a new location with the newly added part. This is inefficient. On the other hand we have StringBuilder which keeps the same position in the memory without performing the copy operation. Thanks to the strings’ appending by means of StringBuilder the process is much more efficient, especially in case of hundreds of append operations.
1
2
3
4
5
6
7
//INCORRECT
List values = new List(){"This ","is ","Sparta ","!"};
string outputValue = string.Empty;
foreach (var value in values)
{
   outputValue += value;
}

1
2
3
4
5
6
//CORRECT
StringBuilder outputValueBuilder = new StringBuilder();
foreach (var value in values)
{
   outputValueBuilder.Append(value);
}

2. LINQ – ‘Where’ with ‘First’ instead of FirstOrDefault

A lot of programmers find a certain set of elements by means of ‘Where’ and then return the first occurrence. This is inappropriate, because the ‘First’ method can be also applied with the ‘Where’ condition. What’s more, it shouldn’t be taken for granted that the value will always be found. If “First” is used when no value is found, an exception will be thrown. Thus, it’s better to use FirstOrDefault instead. When using FirstOrDefault, if no value has been found, the default value for this type will be returned and no exception will be thrown.
1
2
3
//INCORRECT
List numbers = new List(){1,4,5,9,11,15,20,21,25,34,55};
return numbers.Where(x => Fibonacci.IsInFibonacciSequence(x)).First();

1
2
//PARTLY CORRECT
return numbers.First(x => Fibonacci.IsInFibonacciSequence(x));

1
2
//CORRECT
return numbers.FirstOrDefault(x => Fibonacci.IsInFibonacciSequence(x));

3. Casting by means of ‘(T)’ instead of ‘as (T)’ when possibly not castable

It’s common that software developers use simple ‘(T)’ casting, instead of ‘as (T)’. And usually it doesn’t have any negative influence because casted objects are always castable. Yet, if there is even a very slight probability that an object can be under some circumstances not castable, „as (T)” casting should be used. See Difference Between C# Cast Syntax and the AS Operators for more details.
1
2
//INCORRECT
var woman = (Woman)person;

1
2
//CORRECT
var woman = person as Woman;

4. Not using mapping for rewriting properties

There are a lot of ready and very powerful C# mappers (e.g. AutoMapper). If a few lines of code are simply connected with rewriting properties, it’s definitely a place for a mapper. Even if some properties aren’t directly copied but some additional logic is performed, using a mapper is still a good choice (mappers enable defining the rules of rewriting properties to a big extend).

5. Incorrect exceptions re-throwing

C# programmers usually forget that when they throw an exception using „throw ex” they loose the stack trace. It is then considerably harder to debug an application and to achieve appropriate log messages. When simply using „throw” no data is lost and the whole exception together with the stack trace can be easily retrieved.
01
02
03
04
05
06
07
08
09
10
//INCORRECT
try
{
   //some code that can throw exception [...]
}
catch (Exception ex)
{
   //some exception logic [...]
   throw ex;
}

01
02
03
04
05
06
07
08
09
10
//CORRECT
try
{
   //some code that can throw exception [...]
}
catch (Exception ex)
{
   //some exception logic [...]
   throw;
}

6. Not using ‘using’ for objects disposal

Many C# software developers don’t even know that ‘using’ keyword is not only used as a directive for adding namespaces, but also for disposing objects. If you know that a certain object should be disposed after performing some operations, always use the ‘using’ statement to make sure that the object will actually be disposed.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
//the below code:
using(SomeDisposableClass someDisposableObject = new SomeDisposableClass())
{
   someDisposableObject.DoTheJob();
}
//does the same as:
SomeDisposableClass someDisposableObject = new SomeDisposableClass();
try
{
   someDisposableObject.DoTheJob();
}
finally
{
   someDisposableObject.Dispose();
}

7. Using ‘foreach’ instead of ‘for’ for anything else than collections

Remember that if you want to iterate through anything that is not a collection (so through e.g. an array), using the ‘for’ loop is much more efficient than using the ‘foreach’ loop. SeeForeach vs For Performance for more details.

8. Retrieving or saving data to DB in more than 1 call

This is a very common mistake, especially among junior developers and especially when using ORMs like Entity Framework or NHibernate. Every DB call consumes some amount of time and therefore it’s crucial to decrease the amount of DB calls as much as possible. There are many ways to do so:
§  Using fetching (Eager Loading)
§  Enclosing DB operations in transactions
§  In case of a really complex logic, just moving it to the DB by building a stored procedure
It goes without saying that there are hundreds of other types of mistakes made by C# programmers. If you know any interesting ones or you want to share your opinion about the subject, feel free to leave a comment below

2 comments:

  1. C# Best Practices: Array iteration in C# best practice
    My last two article covered XML serialization and deserialization in c#. In this c# tutorial let’s take a look at c# best practices of Array iteration in c#. By the end of this article you would be able to use an efficient way of array iteration and you would realize an improvement in your speed/performance of a program.

    This article is basically for beginners.

    Before we continue, I want to ask you a simple question. Do you know about IndexOutOfRangeException and when it occurs? The answer is very simple and I know you guys know this. Yes! The exception occurs when you try to access an index value of an array which is more than the actual length of array.



    See below code for looping array in c# with example –

    try
    {
    int[] simpleArray = new int[10];
    for (int i = 0; i < 12; i++)
    {
    simpleArray[i] = i;
    Console.Write(" " + simpleArray[i]);
    }
    }
    catch (IndexOutOfRangeException ex)
    {
    Console.WriteLine("IndexOutOfRangeException occurs. Check the loop.");
    }


    As you can see in above code snippet, the length of ‘simpleArray’ is declared as 10 and while iterating in ‘for’ loop the iteration count is set to 12. We know that c# supports ‘0’ based index collections. Hence when ‘for’ loop reaches to index value 10 it would throw an IndexOutOfRangeException.

    So is this the efficient way of handling array looping? No, most of the time we may not be sure the length of the array. The best way to iterate thru an array collection is to know the maximum length of an array, so that the iteration never goes beyond that index value. This maximum value is also called as upper bound of an array. Putting a hardcoded value as an upper bound of array iteration is not a good idea.
    There are two ways to efficiently handle the array iteration.

    A) The first way is to get the length of array as an upper bound. Look at below code –
    int[] simpleArray = new int[10];
    for (int i = 0; i < simpleArray.Length; i++)
    {
    simpleArray[i] = i;
    Console.Write(" " + simpleArray[i]);
    }


    Instead of writing hardcoded value as an upper bound of an array looping, I used array.Length. So in this case, the loop would continue to iterate to i=9 and then terminates itself without throwing an IndexOutOfRangeException.

    B) The second best way is to prefer ‘foreach’ loop over a ‘for’ loop. Below example shows how to use ‘foreach’ loop for an array iteration.

    int[] simpleArray = new int[10];
    int j = 0;
    foreach(int i in simpleArray)
    {
    simpleArray[i] = j++;
    Console.Write(" " + simpleArray[i]);
    }


    Above two are efficient ways of using array iteration in c#, because compiler will never throw an IndexOutOfRangeException.

    ReplyDelete
  2. I find your site super brilliant, I wish you every success because you deserve it, good luck and again well done for this superb site!

    Voyance en ligne gratuite et sérieuse

    ReplyDelete

Angular Tutorial (Update to Angular 7)

As Angular 7 has just been released a few days ago. This tutorial is updated to show you how to create an Angular 7 project and the new fe...