|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionIn my experience, there are two kinds of programmers. Those who write something to get the work done and those who want to write good code. But, here we get a big question. What is good code? Good code comes from good programming practices. What are good programming practices? Actually, my aim here is not to talk about good programming practices (I’m planning to write something related to that in future!), rather to talk more about writing something which will be more effective. I'm only going to look more deeper of two loops which are commonly used nowadays, and their differences in the aspect of performance. BackgroundMust be familiar with IL and assembly code. Also, better to have a good knowledge on how .NET framework works. Some knowledge of JIT is also needed to understand what is exactly happening. Using the codeI’m going to take a very small piece of code for two popular looping statements FORint[] myInterger = new int[1];
int total = 0;
for(int i = 0; i < myInterger.Length; i++)
{
total += myInterger[i];
}
foreachint[] myInterger = new int[1];
int total = 0;
foreach(int i in myInterger)
{
total += i;
}
Both codes will produce the same result. The IL code produced by C# compiler is optimized up to certain extend, while leaving some part to JIT. Anyway, this is not really what matters to us. So, when we talk about the optimization, two things we must consider. First is C# compiler and the second is JIT. So, rather than looking more deep into IL code, we will see more about the code which is emitted by JIT. That is the code which will run on our machine. I’m now using AMD Athlon 1900+. The code highly depends on our hardware. Therefore, what you may get from your machine may differ from mine up to a certain extend. Anyway, the algorithms wont change that much. In variable declaration, Here, I’m going into the exact difference between the codes. FORInstruction Effectcmp dword ptr [eax+4],0 i<myInterger.Length
jle 0000000F
mov ecx,dword ptr [eax+edx*4+8] total += myInterger[i]
inc edx ++i
cmp esi,dword ptr [eax+4] i<myInterger.Length
jl FFFFFFF8
I’ll explain what is happening here. The foreachInstruction Effectcmp esi,dword ptr [ebx+4] i<myInterger.Length
jl FFFFFFE3
cmp esi,dword ptr [ebx+4] i<myInterger.Length
jb 00000009
mov eax,dword ptr [ebx+esi*4+8]
mov dword ptr [ebp-0Ch],eax
mov eax,dword ptr [ebp-0Ch]
add dword ptr [ebp-8],eax total += i
inc esi ++i
cmp esi,dword ptr [ebx+4] i<myInterger.Length
jl FFFFFFE3
Anyone will say that both are not the same. But we will look why it differs from the cmp esi,dword ptr [ebx+4]
jl FFFFFFE3
cmp esi,dword ptr [ebx+4]
It also uses some unnecessary move statements which also may (not always, but depends) reduce the performance of the code. Therefore, I strongly feel if you are planning to write high performance code that is not for collections, use Points of InterestActually, I did a small research on the performance issue of codes mainly on .NET languages. While I was testing, I found that it was really a must to know how JIT works and to debug the code generated by JIT compiler. It took some time to understand the code. HistoryThis is submitted on 19th of April 2004.
|
||||||||||||||||||||||