Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why MC++ is faster then C# ?

1 view
Skip to first unread message

Gawelek

unread,
Mar 15, 2004, 6:29:52 PM3/15/04
to
I made some benchmarks and MC++ is much faster then C#.
They should be compiled to the same TYPE of code and therefore
their performance should be +- equal. Can sombody explain me this thing ?


--
Gawel
-------------------------------
Pierwszy łyk z pucharu nauk przyrodniczych czyni ateistą, ale na dnie
pucharu czeka Bóg.
Werner Heisenberg

Jerry Pisk

unread,
Mar 15, 2004, 9:45:13 PM3/15/04
to
Because you're probably good in C++ but don't know how to write efficient
managed code. The same code does not necessarily translate to same
performance.

Jerry

"Gawelek" <gaw...@NOSPAMEKpoczta.gazeta.pl> wrote in message
news:OetBuVuC...@TK2MSFTNGP11.phx.gbl...

Alvin Bruney [MVP]

unread,
Mar 16, 2004, 10:00:19 AM3/16/04
to

--
Regards,
Alvin Bruney [ASP.NET MVP]
Got tidbits? Get it here...
http://tinyurl.com/3he3b
"Jerry Pisk" <jerr...@hotmail.com> wrote in message
news:%23h2%230CwCE...@TK2MSFTNGP12.phx.gbl...

Alvin Bruney [MVP]

unread,
Mar 16, 2004, 10:00:49 AM3/16/04
to
That is exactly what it is. nail on the head there. nail right on the head.

--
Regards,
Alvin Bruney [ASP.NET MVP]
Got tidbits? Get it here...
http://tinyurl.com/3he3b
"Jerry Pisk" <jerr...@hotmail.com> wrote in message
news:%23h2%230CwCE...@TK2MSFTNGP12.phx.gbl...

Michael Giagnocavo [MVP]

unread,
Mar 16, 2004, 11:54:33 AM3/16/04
to
If you have specific scenarios that you think are unknown to the JIT team,
then you should post them. Rememver that the MC++ compiler is very mature,
while the JIT is still a relatively new product. Managed code doesn't
necesarily need to be slow (and in some cases we can get even more
performance out of a JIT than "pre"-compiled native code).

Quake II was recompiled as a managed application and I believe the
performance was around 95% of the native version.

-mike
MVP

"Gawelek" <gaw...@NOSPAMEKpoczta.gazeta.pl> wrote in message
news:OetBuVuC...@TK2MSFTNGP11.phx.gbl...

Lord Crc

unread,
Mar 17, 2004, 4:24:50 PM3/17/04
to
On Tue, 16 Mar 2004 00:29:52 +0100, "Gawelek"
<gaw...@NOSPAMEKpoczta.gazeta.pl> wrote:

>I made some benchmarks and MC++ is much faster then C#.
>They should be compiled to the same TYPE of code and therefore
>their performance should be +- equal. Can sombody explain me this thing ?

I just found that it was VERY easy to write very slow C# code using
the style i'd learned from Delphi with regards to what was fast in
delphi. To start with it was around 6x as slow. After i explored other
options, i got the code within 10-15% of the native delphi code.

I learned then (with a big duh) that c#/.net is a totally new
language/framework where i basically shouldnt assume that what was
quick in native lang's would be quick in c#

- Asbjørn

ThomasR

unread,
Mar 18, 2004, 11:36:22 AM3/18/04
to
> I just found that it was VERY easy to write very slow C# code using
> the style i'd learned from Delphi with regards to what was fast in
> delphi. To start with it was around 6x as slow. After i explored other
> options, i got the code within 10-15% of the native delphi code.
>

Could you post some more information on what you found? Specifically,
what approach was slow to begin with, and what did you change to
improve the speed?

Thanks.

Lord Crc

unread,
Mar 18, 2004, 7:18:08 PM3/18/04
to
On 18 Mar 2004 08:36:22 -0800, trnews...@earthlink.net (ThomasR)
wrote:

In delphi, my vector lib looked like this (roughly)

type
Vector = array[0..3] of double;

so basically what would have been "double[4]" had c# allowed static
arrays. i then had a bunch of functions like (in c#-ish code)

Vector vectorAdd(Vector v1, Vector v2) { ... }

I ported this to the following

struct Vector
{
double[] _v = new double[4];

static Vector Add(Vector v1, Vector v2)
{
return new Vector(v1._v[0] + v2._v[0] ... );
}
}

I used the Add() because then i could neatly use operator overloading.
This was very nice, but dog slow...

Firstly, array's arent very good for that kind of access, and since i
seldom have to iterate over them, i change the struct to hold 4 local
fields instead. I then made an indexer which just does a switch() in
case i need to iterate over it, or otherwise dynamically access either
field.

Next i extended the class to also have methods that operate on the
vector instance, ala

void Add(Vector otherVector)

It was now quite a bit faster than what i started out as. If speed is
of the essence, making it (ref Vector otherVector) makes it even
faster, but its "naughty", and less flexible.

I tried making it a class instead of a struct, which seemed to speed
it up, however in the real world, it ended up killing the GC, making
the GC work overtime.

That was the major things i can rememeber.

- Asbjørn

Lord Crc

unread,
Mar 20, 2004, 1:51:41 PM3/20/04
to
On 18 Mar 2004 08:36:22 -0800, trnews...@earthlink.net (ThomasR)
wrote:

>Could you post some more information on what you found? Specifically,


>what approach was slow to begin with, and what did you change to
>improve the speed?

Oh, and i found that Environment.TickCount is S L O W. My code spent
some 60% of the time in that function to see if it was time to do a
status report...

- Abjørn

Maoni Stephens

unread,
Mar 22, 2004, 1:50:21 AM3/22/04
to
Do you mind telling me how you concluded that it's taking 60% of the time?
What is your app doing?

Thanks.

--------------------
>From: Lord Crc <lor...@hotmail.com>
>Newsgroups: microsoft.public.dotnet.framework.performance
>Subject: Re: Why MC++ is faster then C# ?
>Date: Sat, 20 Mar 2004 19:51:41 +0100
>Message-ID: <hk4p50p8kpdg3vtpl...@4ax.com>
>References: <OetBuVuC...@TK2MSFTNGP11.phx.gbl>
<4dgh509h4cmj0h5dv...@4ax.com>
<778aa68e.04031...@posting.google.com>
>X-Newsreader: Forte Agent 1.93/32.576 English (American)
>MIME-Version: 1.0
>Content-Type: text/plain; charset=ISO-8859-1
>Content-Transfer-Encoding: 8bit
>NNTP-Posting-Host: 242.80-203-36.nextgentel.com
>X-Original-NNTP-Posting-Host: 242.80-203-36.nextgentel.com
>X-Trace: news.broadpark.no 1079809264 242.80-203-36.nextgentel.com (20 Mar
2004 20:01:04 +0100)
>Lines: 12
>Path:
cpmsftngxa06.phx.gbl!TK2MSFTNGXA01.phx.gbl!TK2MSFTNGP08.phx.gbl!newsfeed00.s
ul.t-online.de!t-online.de!border2.nntp.ash.giganews.com!nntp.giganews.com!n
ntp1.phx1.gblx.net!nntp.gblx.net!nntp.gblx.net!nntp3.phx1!news.broadpark.no
>Xref: cpmsftngxa06.phx.gbl
microsoft.public.dotnet.framework.performance:6960
>X-Tomcat-NG: microsoft.public.dotnet.framework.performance


--

This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm

Note: For the benefit of the community-at-large, all responses to this
message are best directed to the newsgroup/thread from which they
originated.

Lord Crc

unread,
Mar 22, 2004, 7:43:44 AM3/22/04
to
On Mon, 22 Mar 2004 06:50:21 GMT, mao...@online.microsoft.com (Maoni
Stephens) wrote:

>Do you mind telling me how you concluded that it's taking 60% of the time?
>What is your app doing?

I used a performance monitor app thingy. And when i removed it, my app
got significantly faster.

Basically the looped looked like this:

for each pixel in image do
compute pixel
store pixel
check time
if over 250ms since last time then
call DoEvents()

For scenes where the time to compute each pixel was low, the TickCount
became the bottleneck. Obviously for other scenes it wouldnt have
mattered, but now i have a solution that's independent of that (im
using a Timer() object)

- Asbjørn

Bob

unread,
Mar 22, 2004, 2:48:57 PM3/22/04
to

"Lord Crc" <lor...@hotmail.com> wrote in message
news:dlnt509ft7tp63duq...@4ax.com...


This code does not tell anything about TickCount. If you do:

while (true)
{
int i = Environment.TickCount;
}

TickCount *will* appear high in a profiler. However, that does
*not* mean that TickCount is slow. It's simply because your
code is busy-waiting.

Thus I'd say your problem was your own design. Busy-waiting *will*
eat CPU. A timer is a good way to avoid busy-waiting (as you seem
to have noticed).


Lord Crc

unread,
Mar 22, 2004, 3:46:26 PM3/22/04
to
On Mon, 22 Mar 2004 20:48:57 +0100, "Bob" <b...@somewhere.ch> wrote:

>
>
>This code does not tell anything about TickCount. If you do:
>
> while (true)
> {
> int i = Environment.TickCount;
> }

The code was similar to this

int ticks = Environment.TickCount;

for (int y = 0; y < bmp.Heigth; y++)
{
for (int x = 0; x < bmp.Width; x++)
{
pix:= TracePixel(x, y);
// involves walking a bounding hierarchy
// calculating the intesection variables
// perform lighting and shading

Output.Store(x, y, pix); // uses lock() to be thread safe

if (Enviroment.TickCount - ticks > 250)
{
Application.DoEvents();
ticks = Enviroment.TickCount;
}
}
}

TracePixel is on the top of my rendering class hierarchy, one call
involves several dozens of methods, many virtual ones.

For simple scenes, i got the high numbers for tickcount, and when i
removed it, it was indeed much faster (didnt bother to calc the diff
though, but it was certainly over 40% faster)

- Asbjørn

Michel André

unread,
Mar 22, 2004, 4:35:36 PM3/22/04
to
> The code was similar to this
>
> int ticks = Environment.TickCount;
>
> for (int y = 0; y < bmp.Heigth; y++)
> {
> for (int x = 0; x < bmp.Width; x++)
> {
> pix:= TracePixel(x, y);
> // involves walking a bounding hierarchy
> // calculating the intesection variables
> // perform lighting and shading
>
> Output.Store(x, y, pix); // uses lock() to be thread safe
>
> if (Enviroment.TickCount - ticks > 250)
> {
> Application.DoEvents();
> ticks = Enviroment.TickCount;
> }
> }
> }
>
> TracePixel is on the top of my rendering class hierarchy, one call
> involves several dozens of methods, many virtual ones.
>
> For simple scenes, i got the high numbers for tickcount, and when i
> removed it, it was indeed much faster (didnt bother to calc the diff
> though, but it was certainly over 40% faster)

Is there some specific reason why this code/algrithm doesn't run in an
own thread that can be interupted. My best guess is that you are doing
the DoEvents to implement somekind of cancel functionality. I would put
the code in an own thread and check if an cancel event is every nth
iteration in the loop (choose n to be something good considering
performance and usability). You don't want to check the event in every
loop since there is overhead in going to the kernel and back and
checking the state of the event which you don't want to do in every loop.

/Michel

/Michel

Lord Crc

unread,
Mar 22, 2004, 7:45:06 PM3/22/04
to
On Mon, 22 Mar 2004 22:35:36 +0100, Michel André
<michel...@swipnet.se> wrote:

>Is there some specific reason why this code/algrithm doesn't run in an
>own thread that can be interupted. My best guess is that you are doing
>the DoEvents to implement somekind of cancel functionality.

Well, I found it much easier to debug one thread. The DoEvents is so i
can move the form and minimize it while it's rendering.

Don't worry, the code is in its separate thread since long ago.
However, that's how i stumbled on TickCount's slowness. But by all
means, be your own judge. Im not claiming any authority on the issue.

- Asbjørn

Bob

unread,
Mar 23, 2004, 3:52:11 PM3/23/04
to
Hello. I tried to construct a sample showing
that TickCount was slow, but with not success.

Would it be possible for you to construct a
sample that people here can test and verify
the problem? It shouldn't be necessary to
bring any graphics in, if TickCount is slow
you should be able to prove it easily.

"Lord Crc" <lor...@hotmail.com> wrote in message

news:nlju50tr5l4aio5o1...@4ax.com...

Eric Gunnerson [MS]

unread,
Mar 23, 2004, 4:40:40 PM3/23/04
to
How are you looping through the image? If you're using the Bitmap class,
GetPixel and SetPixel are *slow*.

This class is much faster:

http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=6699aa41-7b59-40ec-a30d-da3afe63bd05

Oh, and make sure that you're using a release build and you aren't using F5
from within the IDE.

--
Eric Gunnerson

Visit the C# product team at http://www.csharp.net
Eric's blog is at http://weblogs.asp.net/ericgu/

This posting is provided "AS IS" with no warranties, and confers no rights.

"Lord Crc" <lor...@hotmail.com> wrote in message

news:dlnt509ft7tp63duq...@4ax.com...

Lord Crc

unread,
Mar 23, 2004, 6:31:35 PM3/23/04
to
On Tue, 23 Mar 2004 13:40:40 -0800, "Eric Gunnerson [MS]"
<eri...@online.microsoft.com> wrote:

>How are you looping through the image? If you're using the Bitmap class,
>GetPixel and SetPixel are *slow*.

By no means, my own bitmap class (that writes floating point images),
and it stores entire scanlines at a time.

- Asbjørn

Lord Crc

unread,
Mar 23, 2004, 6:44:44 PM3/23/04
to
On Tue, 23 Mar 2004 21:52:11 +0100, "Bob" <b...@somewhere.ch> wrote:

>Would it be possible for you to construct a
>sample that people here can test and verify
>the problem?

Ok, so it's not as bad as i though, however still significant enough
that you would prob want to keep it out of any inner loops imho.

I get around 12000 with, and 9300 without.

#define TickCount
using System;

namespace TickCountSpeed
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
int n = (1 << 28) - 1;
bool p = true;
int st = Environment.TickCount;
int t = st;

for (int i = 2; i < n; i++)
{
p &= (n % i) != 0;
#if TickCount
if (Environment.TickCount-t > 250)
t = Environment.TickCount;
#endif
}

int tt = Environment.TickCount - st;

Console.WriteLine("{0} {1}", tt, p);
}
}
}

Jon Skeet [C# MVP]

unread,
Mar 24, 2004, 2:45:49 AM3/24/04
to
Lord Crc <lor...@hotmail.com> wrote:
> On Tue, 23 Mar 2004 21:52:11 +0100, "Bob" <b...@somewhere.ch> wrote:
>
> >Would it be possible for you to construct a
> >sample that people here can test and verify
> >the problem?
>
> Ok, so it's not as bad as i though, however still significant enough
> that you would prob want to keep it out of any inner loops imho.
>
> I get around 12000 with, and 9300 without.

Given how little else you're doing in the loop, I'm surprised it's
*that* quick. If it's basically on the same order of magnitude as doing
a single integer modulo operation and a comparison, then that's really
cheap as far as I'm concerned.

Yes, you should avoid doing it on every iteration of a loop which does
pretty much nothing else, but I don't think that really shows it to be
slow at all - it just shows it to be "non-free".

--
Jon Skeet - <sk...@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Bob

unread,
Mar 24, 2004, 3:05:16 AM3/24/04
to
Hello,

Could it be that you were runnning under the debugger
when doing the tests?

I modified your sample slightly and made one function
that calls Environment.TickCount and one that does not.
First I call both functions to make sure they're JITed.
Then I call them again. I did this a few times.

Then I made the same thing in C++ and compared the results.

C++ With: 6672
C++ Without: 6094

C# With: 6828
C# Without: 6266

All tests above I started with CTRL-F5, i.e. *not* under
the debugger. The samples above are from a single run,
but I tried quite a few times with similar results.

(Tested on an Intel P4 2.4GHz)

The TickCount version takes somewhat longer time in
both C++ and C#. However, I don't think it's correct
to say that Environment.TickCount or GetTickCount()
is slow. Calling an additional function takes a few
cycles, but doesn't imply that the function is slow.


Then I tried the C# version under the debugger, which
means that JIT optimizations are disabled.

Please refer to the MSDN article "Writing High-Performance
Managed Applications : A Primer"

http://msdn.microsoft.com/library/en-us/dndotnet/html/highperfmanagedapps.asp

"When a managed application is started by a debugger,
even if it is not a Debug build of the application,
the JIT will emit non-optimized x86 instructions"

Running under the debugger made a significant difference:

C# With: 8156
C# Without: 6110


This is similar to the results you are showing. Could
it be that you were running under the debugger?

Here is the code:


**************************************************

using System;

class Class1
{
[STAThread]
static void Main(string[] args)
{

WithTickCount();
WithoutTickCount();

WithTickCount();
WithoutTickCount();

Console.ReadLine();
}

static void WithoutTickCount()


{
int n = (1 << 28) - 1;
bool p = true;
int st = Environment.TickCount;

for (int i = 2; i < n; i++)
{
p &= (n % i) != 0;
}

int tt = Environment.TickCount - st;

Console.WriteLine("C# Without: {0} {1}",
tt, p);
}

static void WithTickCount()


{
int n = (1 << 28) - 1;
bool p = true;
int st = Environment.TickCount;
int t = st;

for (int i = 2; i < n; i++)
{
p &= (n % i) != 0;

if (Environment.TickCount-t > 250)
t = Environment.TickCount;
}

int tt = Environment.TickCount - st;

Console.WriteLine("C# With: {0} {1}",
tt, p);
}
}


**************************************************

#include <windows.h>
#include <iostream>

static void WithoutTickCount()


{
int n = (1 << 28) - 1;
bool p = true;

int st = GetTickCount();

for (int i = 2; i < n; i++)
{
p &= (n % i) != 0;
}

int tt = GetTickCount() - st;

std::cout << "Without: " << tt << " "
<< p << std::endl;
}

static void WithTickCount()


{
int n = (1 << 28) - 1;
bool p = true;

int st = GetTickCount();
int t = st;

for (int i = 2; i < n; i++)
{
p &= (n % i) != 0;

if (GetTickCount()-t > 250)
t = GetTickCount();
}

int tt = GetTickCount() - st;

std::cout << "With: " << tt << " "
<< p << std::endl;
}

int main()
{
WithTickCount();
WithoutTickCount();

WithTickCount();
WithoutTickCount();

return 0;
}

Lord Crc

unread,
Mar 24, 2004, 7:52:02 AM3/24/04
to
On Wed, 24 Mar 2004 09:05:16 +0100, "Bob" <b...@somewhere.ch> wrote:

>Could it be that you were runnning under the debugger
>when doing the tests?

I ran the app from the console. Doing it again, i get the same
numbers. I also ran your code, here's the result

C# With: 11422 False
C# Without: 8859 False

(same numbers i get, in my first post, i had winamp playing duing both
tests)

I have an AMD 1600xp running on win2k. Could it be a amd/p4 thing?

- Asbjørn

Bob

unread,
Mar 24, 2004, 2:14:36 PM3/24/04
to

> I have an AMD 1600xp running on win2k. Could it be a amd/p4 thing?

Interesting. Can you try the c++ version also?
I guess the hw abstraction layer is different for intel and amd,
so maybe that's the problem. Would be interesting to see if it
differs on AMD running windows xp, maybe that is better.


Lord Crc

unread,
Mar 24, 2004, 3:59:16 PM3/24/04
to
On Wed, 24 Mar 2004 20:14:36 +0100, "Bob" <b...@somewhere.ch> wrote:

>> I have an AMD 1600xp running on win2k. Could it be a amd/p4 thing?
>
>Interesting. Can you try the c++ version also?

Same with a win32 version of the c++ code. Would be interesting to try
an amd on xp to see the diff indeed.

- Asbjørn

Bob

unread,
Mar 25, 2004, 1:57:41 PM3/25/04
to

> >> I have an AMD 1600xp running on win2k. Could it be a amd/p4 thing?
> >
> >Interesting. Can you try the c++ version also?
>
> Same with a win32 version of the c++ code. Would be interesting to try
> an amd on xp to see the diff indeed.

It certainly would. If anyone has access to such a configuration and
can give it a try and post results here that would be great.

Lord Crc

unread,
Mar 25, 2004, 3:52:53 PM3/25/04
to
On Thu, 25 Mar 2004 19:57:41 +0100, "Bob" <b...@somewhere.ch> wrote:

>> Same with a win32 version of the c++ code. Would be interesting to try
>> an amd on xp to see the diff indeed.
>
>It certainly would. If anyone has access to such a configuration and
>can give it a try and post results here that would be great.

Got a friend to try the win32 version on an amd on winxp. He got the
same difference that i got. So it's obviously an amd / p4 issue.

Well, now we know :)

- Asbjørn

Ray Beckett

unread,
Mar 25, 2004, 4:15:22 PM3/25/04
to
This may be stating the obvious, but was the version you and your friend ran
a release version or debug? Not just run out of the debugger, but compiled
as a release version. Also, what are the speeds of your processors? This
could have an effect on the overall time, but not necessarily the ratio
between the 2 runs.

"Lord Crc" <lor...@hotmail.com> wrote in message

news:qjh660hcqillkd07c...@4ax.com...

Lord Crc

unread,
Mar 25, 2004, 7:50:51 PM3/25/04
to
On Thu, 25 Mar 2004 13:15:22 -0800, "Ray Beckett"
<raybe...@hotmail.com> wrote:

>This may be stating the obvious, but was the version you and your friend ran
>a release version or debug? Not just run out of the debugger, but compiled
>as a release version. Also, what are the speeds of your processors? This
>could have an effect on the overall time, but not necessarily the ratio
>between the 2 runs.

Release, same exe, and both were executed from the command line.

cpu speed are roughly the same, i forget what he had, but i got 1600+
and i think he had that or 1800+

- asbjørn

0 new messages