Can you write code directly in CIL ???

A

Andreas Mueller

Peter said:
I already know this.

No, you obviously don't. The problem is not that the GC will take any
memory from your method, but that it is running in a separate thread. So
lets say you method executes in 1/10 s. When garbage collection occurs,
it will take way longer, simply because your method will halt in the
middle of something and resume when the GC is done. So from inside your
method, the execution time was still 1/10, but from the outside the
execution time is way longer ( A little bit like theory of relativity
:) ).

Relying on the GC to do or not to do something is a capital sin in .NET.
One thing that it can not do is to reclaim memory that is
still in use.
Correct, it will not try to get you memory, however it will stop you
thread if it wants to
I remember reading the algorithm. It is some sort of aging system.
In any case even if my memory needs to be constantly checked to see if it is
still in use, I only need a single monolithic large block.
Yea, and while t checks and sees that it is not allowed to touch you
monolithic large block, you method will pause and take longer than 1/10s.
One thing that I do
know about GC, is that it is ONLY invoked when memory runs out, and is needed,
otherwise it is never invoked.
One thing that you must know when developing managed code, is that you
*never* know when the GC is invoked.
Watch your performance counters for garbage collection. You'll be
surprised how busy the area :)

[snip]

HTH,
Andy
 
J

Jon Skeet [C# MVP]

Abubakar said:
btw what search engine are you using? It maybe socking for some people but
few days back I was searching some thread and for the same keywords google
could not find the post but msn search (search.msn.com) did :)

groups.google.com, which is what I always use for newsgroup posts.
(Note: not just "web google".) It'll be there somewhere, but I just
can't find it at the moment...
 
W

Willy Denoyette [MVP]

Andreas Mueller said:
Peter said:
I already know this.

No, you obviously don't. The problem is not that the GC will take any
memory from your method, but that it is running in a separate thread. So
lets say you method executes in 1/10 s. When garbage collection occurs, it
will take way longer, simply because your method will halt in the middle
of something and resume when the GC is done. So from inside your method,
the execution time was still 1/10, but from the outside the execution time
is way longer ( A little bit like theory of relativity :) ).

Relying on the GC to do or not to do something is a capital sin in .NET.
One thing that it can not do is to reclaim memory that is still in use.
Correct, it will not try to get you memory, however it will stop you
thread if it wants to
I remember reading the algorithm. It is some sort of aging system. In any
case even if my memory needs to be constantly checked to see if it is
still in use, I only need a single monolithic large block.
Yea, and while t checks and sees that it is not allowed to touch you
monolithic large block, you method will pause and take longer than 1/10s.
One thing that I do know about GC, is that it is ONLY invoked when memory
runs out, and is needed, otherwise it is never invoked.
One thing that you must know when developing managed code, is that you
*never* know when the GC is invoked.
Watch your performance counters for garbage collection. You'll be
surprised how busy the area :)

[snip]

HTH,
Andy

Andreas,

The only time the GC runs (un-forced) is when the creation of an object on
the GC heap would overrun the gen0 heap threshold. When this happens the GC
runs on the same thread as the object creator. That means that the GC won't
run as long as you don't create objects instances.
Note that this assumes there is no external memory pressure when there are
extra GC heap segments allocated, this would force the CLR to start a full
collection.

Willy.
 
W

Willy Denoyette [MVP]

Abubakar said:
I hope that the new C#(2.0) compiler is better at this.

Actually he is, that doesn't mean he generates "perfect" IL, whatever that
may be.
I ran a bunch of (things I keep around since v1.0) benchmarks comparing
managed C++/CLI and C# and found that the RTM build generates almost
identical IL where the previous C# version (even the v2 beta1) did generate
(some) less optimal IL. But even then the performance delta never exceeded
some 5%.
Note that comparing MC++ with C# isn't a fair comparison as the MC++
compiler may emit non verifiable IL, while C# cannot. I tried hand-tweaking
IL and came to the conclusion that it's a waste of time (at least in v2),
most of the time the performance gains are nil.

Willy.
 
P

Peter Olcott

Pohihihi said:
Your benchmarking on perfomance is bit off posting to posting. If it is 100
lines of code in asm then surely it will be performing better but how many
lines of .NET conversion of it. But if you are saying 100 lines of code in
.Net then I wonder how many lines of instruction code your .net code is
creating to execute it several million times in a given second or 10 of a
second or which ever benchmark is correct.
It is currently writtten is Visual C++ 6.0 I tried compiling it with Visual C++
7.0, but this compiler produces poorer code quality by failing to inline
functions. My discussion of .NET is hypothetical. I am going to translate the
unmanaged C++ into managed C#. It is about 100 lines of unmanaged C++ now. This
will translate into about 100 lines of managed C#.
Well anyways, seems like you know the ground you are playing on so for the
answer for your original question, yes you can write the whole program in IL.
I will be interested in knowing how you optimized it.




Peter Olcott said:
Not only will it run several million times every second, but, it will
constantly access all of its memory. Can I write a .NET component using
purely unmanaged code? That would seem to be a contradiction in terms.

Pohihihi said:
IMHO and according to the following link GC is way better than traditional
memory mgmt. If method is running many million times a second (really??)
then GC will keep it. But as Nicholas said, running of GC is a overhead and
it is in control of CLR. Just because your code knows how much memory it
needs it really do not mean that it will always have that in hand. Again GC
is god here. If you want control of your code and how it behaves than leave
managed environment and go for traditional C++/C/ASM route, or as suggested
Interop.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/dotnetperftechs.asp
section -->
"Myth: Garbage Colloction Is Always Slower Than Doing It by Hand"





message Peter,

You are missing the point completely. If you implement your code as
managed code, even in IL, you can't stop a GC no matter what. Your thread
is going to be pre-empted (in most situations, except if you have the GC
running on a separate thread) and it WILL stop and it WILL affect your
performance when it happens.

Just because your code knows how much memory it needs doesn't mean that
you can pre-empt a GC. If it happens, it's going to happen, and there is
nothing you can do about it. Your 100-line function isn't going to be able
to stop it, and the CLR isn't going to care what your function is doing.

You can't just pretend its not going to happen. It does, and it will,
and you can't stop it. This isn't a choice you have if you are running
managed code, whether you do it in IL or not.

This is what it means to have ^managed^ code. The CLR is going to
provide a good number of services, but you are going to have to pay for
them, and should be aware of how they impact your code.

This is why I recommended that you use interop with your unmanaged code.
You will have your performance requirements fufilled, and not have to worry
about doing something that will ultimately be self-defeating.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


in message Peter,

You don't understand a fundamental concept to .NET and CIL. Yes,
there are compilers that will perform optimization of IL to a certain
degree.

However, when the managed code is run, the CLR will take the CIL and
then compile it into native code. At this point in time, it is free to
optimize, or not optimize, or mangle your code in any way you want when
making the transition from CIL to native code.

When you are dealing with assembly language in general, you have
complete control of what is going on, memory allocation, deallocation,
execution, etc, etc. With the CLR, this is taken out of your hands to a
degree.

I don't care about these things they are not effecting my performance.
What is effecting my performance are things such as the compiler failing
to inline my functions code, and unnecessary overhead in the translation
of a switch statement. My function will be always executed several million
times every second. It must run concurrently with other applications.


For example, have you considered, what happens when a Garbage
Collection (GC) occurs while your function is running? If it is in
complete managed code, then there is nothing that you can do about it,
and your function will resume running when the GC is complete. Depending
on what is happening on the machine at the time, combined with what your
program is doing, etc, etc, it is very feasible that your code will take
more than 1/10th of a second.
My code knows exactly how much memory it needs at load time. It needs all
of this memory the whole time that it executes. It would make no sense to
have any garbage collection of my code's memory in this case. I want my
code to be implemented as a .ET component.


Just because it looks like assembly language, don't assume that CIL is
assembly language. There are some very different things going on under
the hood.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I want to be able to stick with purely managed code, if possible. I just
need this 100 line function to run as fast as if it was hand tweaked
assembly language. I have examined CIL, for the most part it is
essentially assembly language. From what I understand any optimizations
take place before the CIL is generated. When I designed this system (in
1998) I had hand tweaked assembly language in mind for this crucial
function all along.

in message Peter,

Not at all. When the CLR gets a hold of the JIT, it is free to
perform any optimizations it deems necessary, and that might not
necessarily be in line with what you are expecting.

My recommendation would be to use Managed C++ to create a wrapper to
your unmanaged code which uses It Just Works (IJW, seriously). You
should get a managed interface, and the best possible performance (for
this specific situation, not all situations) between managed an
unmanaged code.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I need the best possible execution speed. I have found that there is a
large difference in the quality of the code generated by the various
compilers. I have 16,000 hours of development time in my current
project. There is a 100 line function that must take no longer than
1/10 second to execute. I can just barely achieve this with MSVC++ 6.0.
MSVC++ 7.0 has had some of its optimizations disabled. I eventually
will need to port this to C# .NET. This is a case where hand tweaked
assembly language would be appropriate. I figured that hand tweaked CIL
would be the .NET equivalent of hand tweaked assembly language.

"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote in message Peter,

You can write it, but you would have to create a module with IL,
and then compile that into your assembly (or just write the whole
assembly).

Also, what optimizations do you think you can make? Ultimately,
you suffer from the fact that Windows is not a real-time OS, and
nothing you can do will change that. On top of that, the JIT is
what's going to optimize your code again after you try to, so you
might actually end up hurting yourself more than helping yourself.

If you post the code you are trying to optimize, we can try and
tell you where you might make some improvements, but dipping down to
the IL level is most likely not going to help you much.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Cab you write code directly in the Common Intermediate language? I
need to optimize a critical real-time function.
 
P

Peter Olcott

Abubakar said:
Hi,

ofcourse you can, by now you may even have done it. Just write few *.il
lines and pass it to ilasm (that comes with the sdk) and you'll get the
managed binary.

although Nicholas tried explaning. I have just few things to add.

1- If you look at the shared source implementation of .net, ie, SSCLI (aka
ROTOR), you wont find a single *.il file that microsoft devs had to write in
order to acheive better performance. The max they did to write fast code as
a .net code was to write the unsafe C# code (which uses pointers). Beyond
that, places that needed to get maximum efficiency like JIT, they used a
pure c++ code and in very few places, x86 assembly code was used. I think if
those developers could acheive anything significant by writing il directly,
they would have done that.
What I had in mind was to write the best possible code in C++ and have the best
compiler translate this into assembly language. The best compiler so far seems
to be Visual C++ 6.0. Some of the optimizations in 7.0 are disabled, in
particular function inlining. Then I was going to hand tweak this generated
assembly language. Then as a final step I was going to translate this into CIL.
2- C# compiler is as clever in generating msil as anyone can possibly get. I
False assumption when one examines the benchmarks of managed C++ against managed
C#, Managed C++ does significantly better in at least some cases.
 
P

Peter Olcott

Jon Skeet said:
This is entirely untrue. I believe the MC++ compiler generates better
IL than the C# compiler, for a start. For a second thing, I remember a
post a long time ago by someone who wanted to be able to embed IL in
his C#. We asked him whether he was sure it would produce a performance
improvement, and he produced his hand-tweaked IL and the IL generated
by the C# compiler - and the hand-tweaked IL was about twice as fast.

Good to know, thanks. This is the knid of validation that I was looking for.
 
P

Peter Olcott

Andreas Mueller said:
No, you obviously don't. The problem is not that the GC will take any memory
from your method, but that it is running in a separate thread. So lets say you
method executes in 1/10 s. When garbage collection occurs, it will take way
longer, simply because your method will halt in the middle of something and
resume when the GC is done. So from inside your method, the execution time was
still 1/10, but from the outside the execution time is way longer ( A little
bit like theory of relativity :) ).

That is find as long as my code does not take more than 1/10 second total. When
I called my code real-time, this was a close approximation of the truth, rather
than precisely true.
Relying on the GC to do or not to do something is a capital sin in .NET.
One thing that it can not do is to reclaim memory that is still in use.
Correct, it will not try to get you memory, however it will stop you thread if
it wants to
I remember reading the algorithm. It is some sort of aging system. In any
case even if my memory needs to be constantly checked to see if it is still
in use, I only need a single monolithic large block.
Yea, and while t checks and sees that it is not allowed to touch you
monolithic large block, you method will pause and take longer than 1/10s.
One thing that I do know about GC, is that it is ONLY invoked when memory
runs out, and is needed, otherwise it is never invoked.
One thing that you must know when developing managed code, is that you *never*
know when the GC is invoked.
Watch your performance counters for garbage collection. You'll be surprised
how busy the area :)

[snip]

HTH,
Andy
 
P

Peter Olcott

Willy Denoyette said:
Andreas Mueller said:
Peter said:
message
Peter,

I highly recommend that you read up on how Garbage Collection works
exactly.


I already know this.

No, you obviously don't. The problem is not that the GC will take any memory
from your method, but that it is running in a separate thread. So lets say
you method executes in 1/10 s. When garbage collection occurs, it will take
way longer, simply because your method will halt in the middle of something
and resume when the GC is done. So from inside your method, the execution
time was still 1/10, but from the outside the execution time is way longer
( A little bit like theory of relativity :) ).

Relying on the GC to do or not to do something is a capital sin in .NET.
One thing that it can not do is to reclaim memory that is still in use.
Correct, it will not try to get you memory, however it will stop you thread
if it wants to
I remember reading the algorithm. It is some sort of aging system. In any
case even if my memory needs to be constantly checked to see if it is still
in use, I only need a single monolithic large block.
Yea, and while t checks and sees that it is not allowed to touch you
monolithic large block, you method will pause and take longer than 1/10s.
One thing that I do know about GC, is that it is ONLY invoked when memory
runs out, and is needed, otherwise it is never invoked.
One thing that you must know when developing managed code, is that you
*never* know when the GC is invoked.
Watch your performance counters for garbage collection. You'll be surprised
how busy the area :)

[snip]

HTH,
Andy

Andreas,

The only time the GC runs (un-forced) is when the creation of an object on the
GC heap would overrun the gen0 heap threshold. When this happens the GC runs
on the same thread as the object creator. That means that the GC won't run as
long as you don't create objects instances.
Note that this assumes there is no external memory pressure when there are
extra GC heap segments allocated, this would force the CLR to start a full
collection.

Willy.
So it is like I said. My program will not implicitly invoke a garbage collection
cycle after it begins executing, if it needs a single fixed block of memory the
whole time that it is executing.
 
W

Willy Denoyette [MVP]

Peter Olcott said:
Willy Denoyette said:
Andreas Mueller said:
Peter Olcott wrote:

"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote in message
Peter,

I highly recommend that you read up on how Garbage Collection works
exactly.


I already know this.

No, you obviously don't. The problem is not that the GC will take any
memory from your method, but that it is running in a separate thread. So
lets say you method executes in 1/10 s. When garbage collection occurs,
it will take way longer, simply because your method will halt in the
middle of something and resume when the GC is done. So from inside your
method, the execution time was still 1/10, but from the outside the
execution time is way longer ( A little bit like theory of relativity
:) ).

Relying on the GC to do or not to do something is a capital sin in .NET.

One thing that it can not do is to reclaim memory that is still in use.
Correct, it will not try to get you memory, however it will stop you
thread if it wants to
I remember reading the algorithm. It is some sort of aging system. In
any case even if my memory needs to be constantly checked to see if it
is still in use, I only need a single monolithic large block.
Yea, and while t checks and sees that it is not allowed to touch you
monolithic large block, you method will pause and take longer than
1/10s.
One thing that I do know about GC, is that it is ONLY invoked when
memory runs out, and is needed, otherwise it is never invoked.
One thing that you must know when developing managed code, is that you
*never* know when the GC is invoked.
Watch your performance counters for garbage collection. You'll be
surprised how busy the area :)

[snip]

HTH,
Andy

Andreas,

The only time the GC runs (un-forced) is when the creation of an object
on the GC heap would overrun the gen0 heap threshold. When this happens
the GC runs on the same thread as the object creator. That means that the
GC won't run as long as you don't create objects instances.
Note that this assumes there is no external memory pressure when there
are extra GC heap segments allocated, this would force the CLR to start a
full collection.

Willy.
So it is like I said. My program will not implicitly invoke a garbage
collection cycle after it begins executing, if it needs a single fixed
block of memory the whole time that it is executing.

Be careful, if your function allocates that "block of memory" from the GC
heap, it may get pre-empted by the CLR to perform a GC. You could force a GC
run by calling GC.Collect() before you call the method, but this won't
necessarily prevent a GC when you allocate a very large object in that
method.

Willy.
 
W

Willy Denoyette [MVP]

Peter Olcott said:
What I had in mind was to write the best possible code in C++ and have the
best compiler translate this into assembly language. The best compiler so
far seems to be Visual C++ 6.0. Some of the optimizations in 7.0 are
disabled, in particular function inlining. Then I was going to hand tweak
this generated assembly language. Then as a final step I was going to
translate this into CIL.

False assumption when one examines the benchmarks of managed C++ against
managed C#, Managed C++ does significantly better in at least some cases.

Not sure where you get this from? Did you actually run such benchmarks?
I did run many benchmarks, since v1.0 comparing both C# and Managed C++ (and
C++/CLI) and I never saw a delta (yes, for some C# is the winner) larger
than 5%, using v2 they are even smaller.



Willy.
 
N

Nicholas Paldino [.NET/C# MVP]

That's laughable, honestly, to think that 100 lines of C++ code will
translate into 100 lines of C# code. It's a pretty blanket statement which
can be shot down in a number of different ways.

Why not post the C++ code? Are you sure that all of the facilities that
are available to you in that C++ code are available in .NET? Do you have to
call other APIs? Are you sure there are all managed equivalents?

I think it's time to either post the code, or let the thread die.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Peter Olcott said:
Pohihihi said:
Your benchmarking on perfomance is bit off posting to posting. If it is
100 lines of code in asm then surely it will be performing better but how
many lines of .NET conversion of it. But if you are saying 100 lines of
code in .Net then I wonder how many lines of instruction code your .net
code is creating to execute it several million times in a given second or
10 of a second or which ever benchmark is correct.
It is currently writtten is Visual C++ 6.0 I tried compiling it with
Visual C++ 7.0, but this compiler produces poorer code quality by failing
to inline functions. My discussion of .NET is hypothetical. I am going to
translate the unmanaged C++ into managed C#. It is about 100 lines of
unmanaged C++ now. This will translate into about 100 lines of managed C#.
Well anyways, seems like you know the ground you are playing on so for
the answer for your original question, yes you can write the whole
program in IL. I will be interested in knowing how you optimized it.




Peter Olcott said:
Not only will it run several million times every second, but, it will
constantly access all of its memory. Can I write a .NET component using
purely unmanaged code? That would seem to be a contradiction in terms.

IMHO and according to the following link GC is way better than
traditional memory mgmt. If method is running many million times a
second (really??) then GC will keep it. But as Nicholas said, running
of GC is a overhead and it is in control of CLR. Just because your code
knows how much memory it needs it really do not mean that it will
always have that in hand. Again GC is god here. If you want control of
your code and how it behaves than leave managed environment and go for
traditional C++/C/ASM route, or as suggested Interop.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/dotnetperftechs.asp
section -->
"Myth: Garbage Colloction Is Always Slower Than Doing It by Hand"





"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote in message Peter,

You are missing the point completely. If you implement your code
as managed code, even in IL, you can't stop a GC no matter what. Your
thread is going to be pre-empted (in most situations, except if you
have the GC running on a separate thread) and it WILL stop and it WILL
affect your performance when it happens.

Just because your code knows how much memory it needs doesn't mean
that you can pre-empt a GC. If it happens, it's going to happen, and
there is nothing you can do about it. Your 100-line function isn't
going to be able to stop it, and the CLR isn't going to care what your
function is doing.

You can't just pretend its not going to happen. It does, and it
will, and you can't stop it. This isn't a choice you have if you are
running managed code, whether you do it in IL or not.

This is what it means to have ^managed^ code. The CLR is going to
provide a good number of services, but you are going to have to pay
for them, and should be aware of how they impact your code.

This is why I recommended that you use interop with your unmanaged
code. You will have your performance requirements fufilled, and not
have to worry about doing something that will ultimately be
self-defeating.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote in message Peter,

You don't understand a fundamental concept to .NET and CIL. Yes,
there are compilers that will perform optimization of IL to a
certain degree.

However, when the managed code is run, the CLR will take the CIL
and then compile it into native code. At this point in time, it is
free to optimize, or not optimize, or mangle your code in any way
you want when making the transition from CIL to native code.

When you are dealing with assembly language in general, you have
complete control of what is going on, memory allocation,
deallocation, execution, etc, etc. With the CLR, this is taken out
of your hands to a degree.

I don't care about these things they are not effecting my
performance. What is effecting my performance are things such as the
compiler failing to inline my functions code, and unnecessary
overhead in the translation of a switch statement. My function will
be always executed several million times every second. It must run
concurrently with other applications.


For example, have you considered, what happens when a Garbage
Collection (GC) occurs while your function is running? If it is in
complete managed code, then there is nothing that you can do about
it, and your function will resume running when the GC is complete.
Depending on what is happening on the machine at the time, combined
with what your program is doing, etc, etc, it is very feasible that
your code will take more than 1/10th of a second.
My code knows exactly how much memory it needs at load time. It needs
all of this memory the whole time that it executes. It would make no
sense to have any garbage collection of my code's memory in this
case. I want my code to be implemented as a .ET component.


Just because it looks like assembly language, don't assume that
CIL is assembly language. There are some very different things
going on under the hood.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I want to be able to stick with purely managed code, if possible. I
just need this 100 line function to run as fast as if it was hand
tweaked assembly language. I have examined CIL, for the most part it
is essentially assembly language. From what I understand any
optimizations take place before the CIL is generated. When I
designed this system (in 1998) I had hand tweaked assembly language
in mind for this crucial function all along.

"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote in message Peter,

Not at all. When the CLR gets a hold of the JIT, it is free to
perform any optimizations it deems necessary, and that might not
necessarily be in line with what you are expecting.

My recommendation would be to use Managed C++ to create a
wrapper to your unmanaged code which uses It Just Works (IJW,
seriously). You should get a managed interface, and the best
possible performance (for this specific situation, not all
situations) between managed an unmanaged code.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I need the best possible execution speed. I have found that there
is a large difference in the quality of the code generated by the
various compilers. I have 16,000 hours of development time in my
current project. There is a 100 line function that must take no
longer than 1/10 second to execute. I can just barely achieve this
with MSVC++ 6.0. MSVC++ 7.0 has had some of its optimizations
disabled. I eventually will need to port this to C# .NET. This is
a case where hand tweaked assembly language would be appropriate.
I figured that hand tweaked CIL would be the .NET equivalent of
hand tweaked assembly language.

"Nicholas Paldino [.NET/C# MVP]"
Peter,

You can write it, but you would have to create a module with
IL, and then compile that into your assembly (or just write the
whole assembly).

Also, what optimizations do you think you can make?
Ultimately, you suffer from the fact that Windows is not a
real-time OS, and nothing you can do will change that. On top
of that, the JIT is what's going to optimize your code again
after you try to, so you might actually end up hurting yourself
more than helping yourself.

If you post the code you are trying to optimize, we can try
and tell you where you might make some improvements, but dipping
down to the IL level is most likely not going to help you much.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Cab you write code directly in the Common Intermediate
language? I need to optimize a critical real-time function.
 
N

Nicholas Paldino [.NET/C# MVP]

I will second that the C++ compiler is better at optimizing IL output
than the C# compiler. However, as Willy stated, it will not always produce
verifiable code... I believe the article you were looking for is in MSDN
magazine.

But as a general statement, the C++ compiler generally has the best
optimizations (and for unmanaged code, with the new profile-guided
optimization, it's even cooler).
 
J

Jon Skeet [C# MVP]

Nicholas Paldino said:
I will second that the C++ compiler is better at optimizing IL output
than the C# compiler. However, as Willy stated, it will not always produce
verifiable code... I believe the article you were looking for is in MSDN
magazine.

No, the article was definitely someone posting in this group saying, "I
want to be able to embed IL in my C# code, here's why." He then
produced some better IL (which I suspect *was* verifiable) which the C#
compiler "could" have produced from the source C# (i.e. the behaviour
was identical).

I'm sure this will improve over time, but to be honest it's usually the
JIT that has more to do with optimisation IMO.
But as a general statement, the C++ compiler generally has the best
optimizations (and for unmanaged code, with the new profile-guided
optimization, it's even cooler).

Right.
 
P

Peter Olcott

Willy Denoyette said:
Peter Olcott said:
Willy Denoyette said:
Peter Olcott wrote:

in message
Peter,

I highly recommend that you read up on how Garbage Collection works
exactly.


I already know this.

No, you obviously don't. The problem is not that the GC will take any
memory from your method, but that it is running in a separate thread. So
lets say you method executes in 1/10 s. When garbage collection occurs, it
will take way longer, simply because your method will halt in the middle of
something and resume when the GC is done. So from inside your method, the
execution time was still 1/10, but from the outside the execution time is
way longer ( A little bit like theory of relativity :) ).

Relying on the GC to do or not to do something is a capital sin in .NET.

One thing that it can not do is to reclaim memory that is still in use.
Correct, it will not try to get you memory, however it will stop you thread
if it wants to
I remember reading the algorithm. It is some sort of aging system. In any
case even if my memory needs to be constantly checked to see if it is
still in use, I only need a single monolithic large block.
Yea, and while t checks and sees that it is not allowed to touch you
monolithic large block, you method will pause and take longer than 1/10s.
One thing that I do know about GC, is that it is ONLY invoked when memory
runs out, and is needed, otherwise it is never invoked.
One thing that you must know when developing managed code, is that you
*never* know when the GC is invoked.
Watch your performance counters for garbage collection. You'll be surprised
how busy the area :)

[snip]

HTH,
Andy
--
To email me directly, please remove the *NO*SPAM* parts below:
*NO*SPAM*xmen40@*NO*SPAM*gmx.net

Andreas,

The only time the GC runs (un-forced) is when the creation of an object on
the GC heap would overrun the gen0 heap threshold. When this happens the GC
runs on the same thread as the object creator. That means that the GC won't
run as long as you don't create objects instances.
Note that this assumes there is no external memory pressure when there are
extra GC heap segments allocated, this would force the CLR to start a full
collection.

Willy.
So it is like I said. My program will not implicitly invoke a garbage
collection cycle after it begins executing, if it needs a single fixed block
of memory the whole time that it is executing.

Be careful, if your function allocates that "block of memory" from the GC
heap, it may get pre-empted by the CLR to perform a GC. You could force a GC
run by calling GC.Collect() before you call the method, but this won't
necessarily prevent a GC when you allocate a very large object in that method.

I don't care about a GC before I begin running, or any other GC that I did not
invoke.
 
P

Peter Olcott

Willy Denoyette said:
Not sure where you get this from? Did you actually run such benchmarks?
I did run many benchmarks, since v1.0 comparing both C# and Managed C++ (and
C++/CLI) and I never saw a delta (yes, for some C# is the winner) larger than
5%, using v2 they are even smaller.



Willy.
I found it on the web, some of the differences were several-fold. I don't know
which versions.
 
P

Peter Olcott

Nicholas Paldino said:
I will second that the C++ compiler is better at optimizing IL output than
the C# compiler. However, as Willy stated, it will not always produce
verifiable code... I believe the article you were looking for is in MSDN
magazine.

What do you mean by verifiable code?
But as a general statement, the C++ compiler generally has the best
optimizations (and for unmanaged code, with the new profile-guided
optimization, it's even cooler).
 
P

Peter Olcott

Jon Skeet said:
No, the article was definitely someone posting in this group saying, "I
want to be able to embed IL in my C# code, here's why." He then
produced some better IL (which I suspect *was* verifiable) which the C#
compiler "could" have produced from the source C# (i.e. the behaviour
was identical).

I'm sure this will improve over time, but to be honest it's usually the
JIT that has more to do with optimisation IMO.

I wouldn't think that this would be the case for two reasons:
(1) CIL (for the most part) forms a one-to-one mapping with assembly language
(2) End users are waiting on the JIT to complete, no time to waste doing
optimizations that could have been done before the softwae shipped.
 
P

Peter Olcott

Nicholas Paldino said:
That's laughable, honestly, to think that 100 lines of C++ code will
translate into 100 lines of C# code. It's a pretty blanket statement which
can be shot down in a number of different ways.

Not any possible 100 lines of code, only the specific 100 lines of code that I
am referring to in my function. No OS calls. No memory management, just looping
and comparing.
Why not post the C++ code? Are you sure that all of the facilities that
are available to you in that C++ code are available in .NET? Do you have to
call other APIs? Are you sure there are all managed equivalents?

I think it's time to either post the code, or let the thread die.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Peter Olcott said:
Pohihihi said:
Your benchmarking on perfomance is bit off posting to posting. If it is 100
lines of code in asm then surely it will be performing better but how many
lines of .NET conversion of it. But if you are saying 100 lines of code in
.Net then I wonder how many lines of instruction code your .net code is
creating to execute it several million times in a given second or 10 of a
second or which ever benchmark is correct.
It is currently writtten is Visual C++ 6.0 I tried compiling it with Visual
C++ 7.0, but this compiler produces poorer code quality by failing to inline
functions. My discussion of .NET is hypothetical. I am going to translate the
unmanaged C++ into managed C#. It is about 100 lines of unmanaged C++ now.
This will translate into about 100 lines of managed C#.
Well anyways, seems like you know the ground you are playing on so for the
answer for your original question, yes you can write the whole program in
IL. I will be interested in knowing how you optimized it.




Not only will it run several million times every second, but, it will
constantly access all of its memory. Can I write a .NET component using
purely unmanaged code? That would seem to be a contradiction in terms.

IMHO and according to the following link GC is way better than traditional
memory mgmt. If method is running many million times a second (really??)
then GC will keep it. But as Nicholas said, running of GC is a overhead
and it is in control of CLR. Just because your code knows how much memory
it needs it really do not mean that it will always have that in hand.
Again GC is god here. If you want control of your code and how it behaves
than leave managed environment and go for traditional C++/C/ASM route, or
as suggested Interop.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/dotnetperftechs.asp
section -->
"Myth: Garbage Colloction Is Always Slower Than Doing It by Hand"





in message Peter,

You are missing the point completely. If you implement your code as
managed code, even in IL, you can't stop a GC no matter what. Your
thread is going to be pre-empted (in most situations, except if you have
the GC running on a separate thread) and it WILL stop and it WILL affect
your performance when it happens.

Just because your code knows how much memory it needs doesn't mean
that you can pre-empt a GC. If it happens, it's going to happen, and
there is nothing you can do about it. Your 100-line function isn't going
to be able to stop it, and the CLR isn't going to care what your function
is doing.

You can't just pretend its not going to happen. It does, and it will,
and you can't stop it. This isn't a choice you have if you are running
managed code, whether you do it in IL or not.

This is what it means to have ^managed^ code. The CLR is going to
provide a good number of services, but you are going to have to pay for
them, and should be aware of how they impact your code.

This is why I recommended that you use interop with your unmanaged
code. You will have your performance requirements fufilled, and not have
to worry about doing something that will ultimately be self-defeating.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


in message Peter,

You don't understand a fundamental concept to .NET and CIL. Yes,
there are compilers that will perform optimization of IL to a certain
degree.

However, when the managed code is run, the CLR will take the CIL and
then compile it into native code. At this point in time, it is free to
optimize, or not optimize, or mangle your code in any way you want when
making the transition from CIL to native code.

When you are dealing with assembly language in general, you have
complete control of what is going on, memory allocation, deallocation,
execution, etc, etc. With the CLR, this is taken out of your hands to
a degree.

I don't care about these things they are not effecting my performance.
What is effecting my performance are things such as the compiler failing
to inline my functions code, and unnecessary overhead in the translation
of a switch statement. My function will be always executed several
million times every second. It must run concurrently with other
applications.


For example, have you considered, what happens when a Garbage
Collection (GC) occurs while your function is running? If it is in
complete managed code, then there is nothing that you can do about it,
and your function will resume running when the GC is complete.
Depending on what is happening on the machine at the time, combined
with what your program is doing, etc, etc, it is very feasible that
your code will take more than 1/10th of a second.
My code knows exactly how much memory it needs at load time. It needs
all of this memory the whole time that it executes. It would make no
sense to have any garbage collection of my code's memory in this case. I
want my code to be implemented as a .ET component.


Just because it looks like assembly language, don't assume that CIL
is assembly language. There are some very different things going on
under the hood.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I want to be able to stick with purely managed code, if possible. I
just need this 100 line function to run as fast as if it was hand
tweaked assembly language. I have examined CIL, for the most part it is
essentially assembly language. From what I understand any optimizations
take place before the CIL is generated. When I designed this system (in
1998) I had hand tweaked assembly language in mind for this crucial
function all along.

"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote in message Peter,

Not at all. When the CLR gets a hold of the JIT, it is free to
perform any optimizations it deems necessary, and that might not
necessarily be in line with what you are expecting.

My recommendation would be to use Managed C++ to create a wrapper
to your unmanaged code which uses It Just Works (IJW, seriously). You
should get a managed interface, and the best possible performance
(for this specific situation, not all situations) between managed an
unmanaged code.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

I need the best possible execution speed. I have found that there is
a large difference in the quality of the code generated by the
various compilers. I have 16,000 hours of development time in my
current project. There is a 100 line function that must take no
longer than 1/10 second to execute. I can just barely achieve this
with MSVC++ 6.0. MSVC++ 7.0 has had some of its optimizations
disabled. I eventually will need to port this to C# .NET. This is a
case where hand tweaked assembly language would be appropriate. I
figured that hand tweaked CIL would be the .NET equivalent of hand
tweaked assembly language.

"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote in message Peter,

You can write it, but you would have to create a module with IL,
and then compile that into your assembly (or just write the whole
assembly).

Also, what optimizations do you think you can make? Ultimately,
you suffer from the fact that Windows is not a real-time OS, and
nothing you can do will change that. On top of that, the JIT is
what's going to optimize your code again after you try to, so you
might actually end up hurting yourself more than helping yourself.

If you post the code you are trying to optimize, we can try and
tell you where you might make some improvements, but dipping down
to the IL level is most likely not going to help you much.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Cab you write code directly in the Common Intermediate language? I
need to optimize a critical real-time function.
 
N

Nicholas Paldino [.NET/C# MVP]

I wouldn't worry about it, since you are not worried by the multiple
posts by multiple people in this thread telling you things that you don't
want to hear.

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Peter Olcott said:
Nicholas Paldino said:
I will second that the C++ compiler is better at optimizing IL output
than the C# compiler. However, as Willy stated, it will not always
produce verifiable code... I believe the article you were looking for is
in MSDN magazine.

What do you mean by verifiable code?
But as a general statement, the C++ compiler generally has the best
optimizations (and for unmanaged code, with the new profile-guided
optimization, it's even cooler).

--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Jon Skeet said:
It's a shame I can't find the newsgroup thread I'm thinking about - I
could give it a try with C# 2.0...

btw what search engine are you using? It maybe socking for some people
but
few days back I was searching some thread and for the same keywords
google
could not find the post but msn search (search.msn.com) did :)

groups.google.com, which is what I always use for newsgroup posts.
(Note: not just "web google".) It'll be there somewhere, but I just
can't find it at the moment...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top