Jump to content
  • Advertisement
Sign in to follow this  
ynm

What kind of optimization makes C++ faster than C#?

This topic is 2109 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

 

Just out of curiosity, I heard that game engine is mostly written in C++ because it is faster. But I don't know what kind of optimization C++ can offer over C#, can someone give some highlights so I can have general ideas of it

 

Regards

Share this post


Link to post
Share on other sites
Advertisement

C++ operates at a lower level of abstraction than C#. In C++, you could (if you wanted to) trivially fill an array with machine code, cast it to a function and run that code (it would no longer have any amount of portability at that point).

C# compiles to a bytecode that wasn't the machine code of any processor (I say 'wasn't' because I haven't followed C# in a while; they may have built one since). C# programs are run by what is often called an interpreter even though C# runtime has always compiled to machine code on the fly. In a C++ program, the progammer has manual access to freeing memory (as well as the pointers to/within it). A C# program uses the garbage collector to take care of freeing memory (as in, C# doesn't have a 'delete' operator, just 'new').

 

Some people might even argue that C# could be faster because C# gets compiled on the fly, the runtime knows exactly what the best actual machine instructions are for the users exact hardware (as opposed to a C++ compiler having to target some lower denominator of CPU like no-SSE, unless you actually provide multiple binaries for users to choose from or users compile themselves).

 

The fact that a C++ process will never slow down, use an extra thread (or *gasp* pause) for a garbage collection is probably one of the best reasons for people who like control. I thought was going to come up with better arguments, but other than memory access and allocation, it's late and I'm drawing a blank. The runtime compiling C# bytecode on the fly takes time too, and I imagine there's a threshold of how many interprets of the function before it decides to compile.

Edited by beans222

Share this post


Link to post
Share on other sites
there is no particular reason other than language age and general direction. C++ compilers are older and always had performances as their main objective where C# compilers are younger and never had raw performances as their main objective.
The 2 systems have just different agendas.. C++ favors runtime performance over programmers' productivity, C#'s balance is more to favor productivity over runtime performance.

Final note.. no language will make an engine "faster". Programmers write engines, good programmers will write a "faster" engine in C# than some inexperienced programmer using C++. I don't think the reason to adopt C++ in game programming has much to do with performance at all, it's more down to easiness to interact other low level libraries, existing code and resources (developers) reuse and lack of a performing C# runtime on consoles. Edited by kunos

Share this post


Link to post
Share on other sites

It will be interesting to see how much the garbage collectors performance improves with asynchronous operation over the coming years. I've read some recent articles that suggest it is markedly improved.

Share this post


Link to post
Share on other sites
GC is another topic that always pops up in these kind of discussions... IMO is pure non-sense. GC won't trigger if you don't "new" stuff, and will be VERY fast if you don't have objects with medium life expectancy.. it's just a matter to take some time to understand how the system works and how you can make it work for you... it's much easier to learn to deal with .NET's GC than learning proper memory management in C++, simple or through the 6-7 "smart" pointers available.
Just as you try to avoid new and delete in your game loop in C++, avoid newing class objects in C# and GC won't cause any troubles.

 

But really what you're suggesting here is that to "solve" the problem of the GC needing to halt all threads and needing an unknown amount of time to complete, that you do "manual memory management" and try to avoid invoking the GC, which also means designing around ctors/dtors and doing init/cleanup of your objects yourself so you can reuse instances. IMO that's a lot easier to do when there is no GC to worry about, and you reintroduce the problems GC was meant to solve (ie dangling pointers).

Share this post


Link to post
Share on other sites
GC is another topic that always pops up in these kind of discussions... IMO is pure non-sense. GC won't trigger if you don't "new" stuff, and will be VERY fast if you don't have objects with medium life expectancy.. it's just a matter to take some time to understand how the system works and how you can make it work for you... it's much easier to learn to deal with .NET's GC than learning proper memory management in C++, simple or through the 6-7 "smart" pointers available.
Just as you try to avoid new and delete in your game loop in C++, avoid newing class objects in C# and GC won't cause any troubles.

 

But really what you're suggesting here is that to "solve" the problem of the GC needing to halt all threads and needing an unknown amount of time to complete, that you do "manual memory management" and try to avoid invoking the GC, which also means designing around ctors/dtors and doing init/cleanup of your objects yourself so you can reuse instances. IMO that's a lot easier to do when there is no GC to worry about, and you reintroduce the problems GC was meant to solve (ie dangling pointers).

 

I am not suggesting that. "Young" objects are collected by the GC without stopping the world... so those shouldn't create problems at all.

What I was saying is: be sensible... just as you are sensible with C++. And, if you really get in trouble with the GC, use the available techniques to avoid that (ie. object pools). Again, I don't see this being any more difficult than writing a custom allocator in C++.

I wrote a quite complex simulator using C# and never had any problem whatsoever with GC and/or stutters.. actualy, scratch that, I have never had any problem with any of my C# stuff with GC stutters... and I don't use object pools or any other trickery.. just try to be sensible in what I do.. understand the differences between structs and classes in C# goes a long way.

Share this post


Link to post
Share on other sites

Portability is the big one for C#, but as for why it's considered 'slower', a VM compiled language like C# has to be translated at runtime, so an operation in native machine code will always have a significant advantage in speed (although a good VM can overcome that with caching). The simple reason is that a simple CPU instruction will execute at least twice as fast as a VM language instruction that has to be translated and then executed. There's more work to do for every single instruction, so you don't get the same speed unless the VM uses tricks to get that speed for you.

 

That said, modern machines, as was mentioned, can execute horrifically suboptimal code at near instantaneous speeds, so there's no reason to avoid C# unless you're doing something very low-level that needs to be blazing fast for some reason. Even in those cases you can find ways of bending C# to your will if you must. My only real gripe with C# is that it isn't Ruby. If I'm using a VM language I want it to JIT compile from raw scripts that read like Terry Pratchett novels and I want it do some of the crazy stuff that Ruby can get away with such as dynamically redefining classes at runtime or that beautiful, horrible monster known as eval().

 

C# is taken a lot more seriously than Ruby, though. <sad panda>

Edited by Khatharr

Share this post


Link to post
Share on other sites

you dont seem to understand how C# runtime works at all, so your claim are as wrong as it gets.

Every single C# function gets compiled to native code by the JIT the first time it is invoked, from that point on, that function is running native code period. So the "more work to do for every instruction" is just... uninformed and uninformative.

This has been the case for ages, since Java started doing it loooong time ago.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!