C++ performance vs. Java/C#

2018-12-31 21:14发布

My understanding is that C/C++ produces native code to run on a particular machine architecture. Conversely, languages like Java and C# run on top of a virtual machine which abstracts away the native architecture. Logically it would seem impossible for Java or C# to match the speed of C++ because of this intermediate step, however I've been told that the latest compilers ("hot spot") can attain this speed or even exceed it.

Perhaps this is more of a compiler question than a language question, but can anyone explain in plain English how it is possible for one of these virtual machine languages to perform better than a native language?

30条回答
千与千寻千般痛.
2楼-- · 2018-12-31 21:38

Generally, C# and Java can be just as fast or faster because the JIT compiler -- a compiler that compiles your IL the first time it's executed -- can make optimizations that a C++ compiled program cannot because it can query the machine. It can determine if the machine is Intel or AMD; Pentium 4, Core Solo, or Core Duo; or if supports SSE4, etc.

A C++ program has to be compiled beforehand usually with mixed optimizations so that it runs decently well on all machines, but is not optimized as much as it could be for a single configuration (i.e. processor, instruction set, other hardware).

Additionally certain language features allow the compiler in C# and Java to make assumptions about your code that allows it to optimize certain parts away that just aren't safe for the C/C++ compiler to do. When you have access to pointers there's a lot of optimizations that just aren't safe.

Also Java and C# can do heap allocations more efficiently than C++ because the layer of abstraction between the garbage collector and your code allows it to do all of its heap compression at once (a fairly expensive operation).

Now I can't speak for Java on this next point, but I know that C# for example will actually remove methods and method calls when it knows the body of the method is empty. And it will use this kind of logic throughout your code.

So as you can see, there are lots of reasons why certain C# or Java implementations will be faster.

Now this all said, specific optimizations can be made in C++ that will blow away anything that you could do with C#, especially in the graphics realm and anytime you're close to the hardware. Pointers do wonders here.

So depending on what you're writing I would go with one or the other. But if you're writing something that isn't hardware dependent (driver, video game, etc), I wouldn't worry about the performance of C# (again can't speak about Java). It'll do just fine.

One the Java side, @Swati points out a good article:

https://www.ibm.com/developerworks/library/j-jtp09275

查看更多
孤独总比滥情好
4楼-- · 2018-12-31 21:41

I don't know either...my Java programs are always slow. :-) I've never really noticed C# programs being particularly slow, though.

查看更多
永恒的永恒
5楼-- · 2018-12-31 21:42

One of the most significant JIT optimizations is method inlining. Java can even inline virtual methods if it can guarantee runtime correctness. This kind of optimization usually cannot be performed by standard static compilers because it needs whole-program analysis, which is hard because of separate compilation (in contrast, JIT has all the program available to it). Method inlining improves other optimizations, giving larger code blocks to optimize.

Standard memory allocation in Java/C# is also faster, and deallocation (GC) is not much slower, but only less deterministic.

查看更多
ら面具成の殇う
6楼-- · 2018-12-31 21:45

JIT (Just In Time Compiling) can be incredibly fast because it optimizes for the target platform.

This means that it can take advantage of any compiler trick your CPU can support, regardless of what CPU the developer wrote the code on.

The basic concept of the .NET JIT works like this (heavily simplified):

Calling a method for the first time:

  • Your program code calls a method Foo()
  • The CLR looks at the type that implements Foo() and gets the metadata associated with it
  • From the metadata, the CLR knows what memory address the IL (Intermediate byte code) is stored in.
  • The CLR allocates a block of memory, and calls the JIT.
  • The JIT compiles the IL into native code, places it into the allocated memory, and then changes the function pointer in Foo()'s type metadata to point to this native code.
  • The native code is ran.

Calling a method for the second time:

  • Your program code calls a method Foo()
  • The CLR looks at the type that implements Foo() and finds the function pointer in the metadata.
  • The native code at this memory location is ran.

As you can see, the 2nd time around, its virtually the same process as C++, except with the advantage of real time optimizations.

That said, there are still other overhead issues that slow down a managed language, but the JIT helps a lot.

查看更多
君临天下
7楼-- · 2018-12-31 21:45

The virtual machine languages are unlikely to outperform compiled languages but they can get close enough that it doesn't matter, for (at least) the following reasons (I'm speaking for Java here since I've never done C#).

1/ The Java Runtime Environment is usually able to detect pieces of code that are run frequently and perform just-in-time (JIT) compilation of those sections so that, in future, they run at the full compiled speed.

2/ Vast portions of the Java libraries are compiled so that, when you call a library function, you're executing compiled code, not interpreted. You can see the code (in C) by downloading the OpenJDK.

3/ Unless you're doing massive calculations, much of the time your program is running, it's waiting for input from a very slow (relatively speaking) human.

4/ Since a lot of the validation of Java bytecode is done at the time of loading the class, the normal overhead of runtime checks is greatly reduced.

5/ At the worst case, performance-intensive code can be extracted to a compiled module and called from Java (see JNI) so that it runs at full speed.

In summary, the Java bytecode will never outperform native machine language, but there are ways to mitigate this. The big advantage of Java (as I see it) is the HUGE standard library and the cross-platform nature.

查看更多
登录 后发表回答