Thursday, January 04, 2007

C# Problem..

I know the title looks strange.. but this issue is provoking me to a very high extent...
I'll tell u why I wrote so...well, When we were testing our Algo project b4 delivering it, we noticed a strange behavior in the performance of our code..
Let me explain wt we were doing first... well, we wanted to calculate the approximate time taken to run the algorithm.. so we made an object from Stopwatch class.. our code looked sth like those lines:

Stopwatch s = new StopWatch();
s.Start();
OurFunction();
s.Stop();

Then later on we display the elapsed time.... Where's the problem then??.. well I will tell u.. the first time we try calling this function, the elapsed time is 4.xxx ms.. while when we try the same input once again (while the exe is still running).. the elapsed time is 0.xxxx.. a gr8 difference !!!!
well.. we noticed sth in our function like creating an object from a class we created.. ex:
Class c = new Class(Var1,Var2); //inside function's body

we thought that this was the reason (sth related with memory allocation , variables initialization.. etc..) we tried initializing everything globally, but still the same thing happened.. we thought about many things (We with the help of Dr Karim), but all in vain..

So, I still don't know why that happens.. mm.. Maybe C# is googling for the place of the function in the memory when we call it for the first time ,so it takes more time !!???

Anyway, please, If anyone has any idea about why this may happen.. Comments are very welcomed..

17 comments:

Mohammed ElMorsy said...

al salamo 3alikom...

I couldn't imagine a programming lanuage is searching for function, it's something as simple as a table of fnction name pointing to it's address
I've tried that code and it result an acceptable output (kan nefsy yb2a formatted :D):

class ProgramClass
{
public void Run()
{
int x = 0;
while (x < 10000000)
{
x++;
}
}
}
static void Main(string[] args)
{
ProgramClass p = new ProgramClass();
Stopwatch s = new Stopwatch();
for (int i = 0; i < 5; i++)
{
s.Start();
p.Run();
s.Stop();
Console.WriteLine(s.Elapsed.TotalMilliseconds);
s.Reset();
}
}

output:
21.0328
23.2551
25.7764
21.2756
27.556

If u could send ur code, that would be nice

al salamo 3alikm wa ra7mato Allah

Asmaa Magdi said...

Well, I have a small idea that mieght be useless but I'll say it anyway :D.
lamma garrabty el input twice, kano wara b3d?? if so, try to put a different input in the middle.
Maybe el C# is so clever that it knew this input was exactly as the previous one so it remembered the answer so quickly ;)

Mohammed ElMorsy said...

al salamo 3alikom wa ra7mato Allah,

asmaa comment reminded me with some code i've seen on some website :D that memoize function calls in .net..ma 3alena..
I've just recognized that difference of 4 milliseconds is not a deal (i've 5 milli differene in my program), as i guess, in multi-processing environment (Windows OS), try running ur code more than twice.

al salamo 3alikom wa ra7mato Allah

Haytham Alaa said...

Alsalam Alikom wa ra7mat Allah wa barakatoh,

Actually, as far as I know ya3nee, .NET has something called "Lazy Binding" or "Lazy Loading".. something like this..

el mohem,
You know that all ur code is compiled to MSIL code (Microsoft Intermediate Language).. it's a readable code that can't be executed on the Processor Directly, that's why we need the .NET framework to run our .NET Application..

When you double-click your exe, the .NET Framework loads the main class and the main function (loads here mean converts them into native Assembly and puts them somewhere in RAM so that the processor can execute them)
let's say it "recompiles" your MSIL into native code to be executed..

but it's smart enough that it doesn't recompile everything, it compiles the part that will be needed soon... and so on..

So I guess it's clear what happens in ur case..

you call function X (which is not yet native assembly) so .NET Framework takes some time till it convert it to native assembly.
Once done, any later calls will be faster than the first one..

So, if you did what Asmaa suggested about running a different input, I guess that it'll be fast too..

Haza wallahu a3lam..

Alsalam alikom wa ra7mat Allah wa barakatoh

Haytham Alaa said...

Alsalam alikom wa ra7mat Allah wa barakatoh

I did a test keda which I guess proves what I say (howa tab3an law 7ad dawar online hayla2ee el mofeed... bas ne3mel eih b2a a7'oko lazy)

this is my Main class :
class Program
{
static void Main(string[] args)
{
Class1 c = new Class1();
Stopwatch s = new Stopwatch();
for (int i = 0; i < 2; i++)
{
s.Start();
c.Run();
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);
s.Reset();
}
}
}

More or less, it's like Zezo's..
Then I have this as Class1 :
class Class1
{
public void Run()
{
for (int i = 0; i < 10000000; i++)
;
}
}

Now when I run it, it prints out
17
18
or
18
19

Things like this, which is not good at all... just wait and c..
Now I put another "depth" in the program..
The main class is not changed
class1 is like this :
class Class1
{
public void Run()
{
Class2 c = new Class2();
c.Run();
}
}
and class2 is like this
class Class2
{
public void Run()
{
for (int i = 0; i < 10000000; i++)
;
}
}

as u c the first program what like this
Main -> Class1
now it's
Main -> Class1 -> Class2

now the results is somehow accepted
19
18
or
19
17
good enough..
now I added another depth
Main -> Class1 -> Class2 -> Class3
I'll not put more code.. u what I mean already.

Now the results r
32
20
or
22
17

And things like this.. which is more and more accepted..

What I was trying to do is to "deceive" the CLR.. I'm trying to let it "don't" load all my classes at once....

mmm ta2reeban kan hayb2a ashal law dawwar online... yalla msh adyah..

Hope that was useful (and/or) right..

Alsalam alikom wa ra7mat Allah wa barakatoh

Mohammed ElMorsy said...

al salamo 3alikom..

jazak Allah 7'ayran ya haytham for the "Lazy" information ;)
could u plz try running ur code more than twice :D .. timespan increases..
if u have any links about lazy technique with IL plz send it..as I've found "how to lazy loading in ur code"
very good info, al salamo 3alikom wa ra7mato Allah

Roaa Mohammed said...

Al Salamo 3alikom..

To Mohammed a.aziz:
First, SURE I'm joking about the 'googling' thing..

Second, Maybe 4ms is not a big difference, but when all the other outputs are 0.3:0.2.. at least,it doesn't look good when displaying that to the user (for example)
yeah, I tried running my code more than 100 times, The time differs each time for sure, but still the 4.xxx ms difference..

Third, thx for ur help.. if u still want to have a look at the code,tell me & I will upload it & send u a link..

To Asmaaa:
Actually we tried all possible things, & it has nth to do with the input.. (also in our code, we can't try the exact same input 2we..so we'r just approximating)

To Haytham Alaa:
Actually, this is wt I thought about, But I thought it doesn't turn our Class functions & variables to native code except when we use them.. so that's y I tried to make an object from it & use its functions b4 usage (which didn't make a big difference -maybe 1.xx ms difference only-..
I didn't think & know that it doesn't execute my main function too..(turn it to native assembly code)

Jazak Allaho 7'ayran for this info & for the sample code..

Thanks all for ur help..

Mohammed ElMorsy said...

al salamo 3alikom..

ezzaher enny ba2et ba-comment pairs!
el mohem.. i've tried the code on C++ (unmanaged) and resulted the same thing.

al salamo 3alikom wa ra7mato Allah

Mohammed ElMorsy said...

commenting bel-triple :¦

jazana wa eyakom,
first, i knew u were joking..sorry for the tough entry :$
second, yes i wanna have a look at ur code, wish u best luck :)

al salamo 3alikom wa ra7mato Allah

Roaa Mohammed said...

Uploaded the code here
http://www.box.net/public/4hyam17hqh

Mohammed ElMorsy said...

strange!

Roaa Mohammed said...

:)

Mohamed Moshrif said...

About why C++ is also late in doing this, it's something similar, when you load you native image in the memory, it's not loaded completely in the memory, but it's loaded according to the code segments, in other words if you have a function which is not used so much, it'll be thrown to the dead zone of the code segment (usually on the v.memory) and when you use it, it'll be in the main segment, and may be in the cashe.

Refer to a topic called "Profile Guided Optimization" for more information about this

Roaa Mohammed said...

Thanks Meshref for this piece of info...

Mahmoud Hossam said...

asalam 3alikom
did you hear about "native .net assembly images" ?

Actually the issue that haytham said about converting functions or classes to native code at run-time is true.

so, If the native conversion is the problem of the code u mentioned, I guess here is a solution (as haytham said, I am lazy, just guess!), anyway:

Microsoft made a utility called "ngen.exe"(Native Image Generator) shipped with the .net framework, it makes a native image of a given .net assembly (exe or dll), and installs it to the (native images cache), which you will see in the "Assembly cache" in "Microsoft .NET Framework 2.0 Configuration", so that The runtime can use native images from the cache instead of using the just-in-time (JIT) compiler to compile the original assembly

does this solve your problem ?

Roaa Mohammed said...

Thanks for the comment...
I will try that soon isAllah & tell u the feedback..

cialis said...

Interesting article, added his blog to Favorites