Java Faster Than C++?
jg21 writes "The Java platform has a stigma of being a poor performer, but these new performance benchmark tests suggest otherwise. CS major Keith Lea took time out from his studies at student at Rensselaer Polytechnic Institute in upstate New York's Tech Valley to take the benchmark code for C++ and Java from Doug Bagley's now outdated (Fall 2001) "Great Computer Language Shootout" and run the tests himself. His conclusions include 'no one should ever run the client JVM when given the choice,' and 'Java is significantly faster than optimized C++ in many cases.' Very enterprising performance benchmarking work. Lea is planning next on updating the benchmarks with VC++ compiler on Windows, with JDK 1.5 beta, and might also test with Intel C++ Compiler. This is all great - the more people who know about present-day Java performance, the better.""
The great thing about language benchmarks is that there are so many to choose from...
...on x86? Please! Wake me up when someone who knows enough about C++ to pick a decent x86 compiler runs some benchmarks.
Doesn't it make you feel good to know that our freedoms are protected by politicans, lawyers and journalists.
Java and C++ are language. Languages aren't "faster" or "slower", but compilers for them might be. I find it somewhat underhanded to put the languages in the header when it's really comparing compilers.
Not to mention, inter-language compiler benchmark[et]ing is notoriously difficult to get 'right'. The programs tested are often stupid (doesn't do anything meaningful), or constructed by a person with more skill/bias for one language than the other.
If you care about run-time speed when using gcc you compile with -O3.
I'd like to see the benchmarks redone with this.
It's been ages since I've programmed in C++, but it's good to know see these favorable comparisons. I think about the Struts/Hibernate/Oracle applications I write today and shudder when I imagine what how difficult it would be to have to develop web applications in C++. C++ will be around forever and certainly has its place, but long live Java.
There seem to be some unanswered questions here..
- How equivalent were the benchmarks? Where they programmed in an optimum way for their respective compilers and libraries? I'm sure the java ones were.. what about the C++ ones? The author states he doesn't understand G++ very well.
G++ is also known to not produce the best results.
"I rant it with -O2"
My guess is many of the tests were not implemented properly in c++.
The main clue would be this... I can understand java having better than expected performance.. but there is no way I can accept that java is that much FASTER than properly done C++... it doesn't make any sense.
Im sorry but someone who says "I've never been very good at decoding GCC's error messages" is not competent enough to perform performance comparison. This performance test is a shame and shouldnt be taken seriously.
-----
One is born into aristocracy, but mediocrity can only be achieved through hard work.
That's Great! I can't figure out GCC's error messages, but I offer definitive proof that Java is faster than C++. Nice.
You're measuring startup time, not execution speed.
Duh.
Comparing one C++ compiler (gcc) against the Java JVM on one operating system is not much of a test. I love Java, but this is almost something like microsoft would do. Test one specific OS, compiler, and configuration, and then make a blind, far-reaching statement. A fair test would include several platforms and compilers.
From methcall.cpp:
int
main(int argc, char *argv[]) {
int n = ((argc == 2) ? atoi(argv[1]) : 1);
bool val = true;
>> Toggle *toggle = new Toggle(val);
for (int i=0; i<n; i++) {
val = toggle->activate().value();
}
cout << ((val) ? "true" : "false") << endl;
delete toggle;
val = true;
NthToggle *ntoggle = new NthToggle(val, 3);
for (int i=0; i<n; i++) {
val = ntoggle->activate().value();
}
cout << ((val) ? "true" : "false") << endl;
>> delete ntoggle;
return 0;
}
Why allocate and deallocate an object within the scope of a function? Well, in C++, there's no reason, so this is bad code. You can just declare it as a non-pointer and it lives in stack space. But guess what? You can't do that in Java: all objects are allocated on the heap.
That, and using cout instead of printf, are probably why this is slower than the "equivalent" Java.
-_-_-
There are 0x40000000 types of people: those who understand 32-bit IEEE 754 floating point, and those who don't.
Please point me to a source which verifies your claim.
The Internet is full. Go Away!!!
This would be much more meaninful if you had used fputs() instead of write() in the C version.
As for "several orders of magnitude," I call bullshit. There's no way in hell the standard C++ IO functions are hundreds of times slower unless they're extremely badly written. Which leads me to another reason why this example sucks: there can be different implementations of the standard libraries.
In conclusion, this "comparison" is a stinky pile of shit, and should be ignored. And it's not even on topic, since it doesn't have a Java version.
The JIT has run-time path information that g++ does not and can put parts of the hot path together so that they are the same page in cache. YEEEHAW
All you programmers that say you can do anything in Java/C#/etc are terrible.
Actually you can do most anything in those languages. Although for performance, and desgin reasons you may wish to use something else depending on the application.
You have no respect for code. Learn assembly and then we'll talk.
I know assembly, and fun as it is, it isn't well suited for high level projects where code reuse and mantainability are important. By the way, I have no respect for someone who knows assembly and thinks it is difficult. It isn't. And it certainly isn't graceful or elegant, but I love it all the same.
I believe that Sun's javac bootstraps itself just like gcc does. That would be your java compiler written in Java.
_Jikes_, OTOH, is written in C++. But that's not really the official Java compiler by a long shot.
Your second requirement is absolutely bizarre. Does this mean you're not taking languages like Lisp, Prolog, Python, and Perl seriously, too? Those are all very nice languages for doing stuff in, but I'm pretty sure id never wrote a 3D engine in them. In fact, I was under the impression that id has never written a 3D engine in C++, either. Should we not take C++ seriously?
IMHO: The measure of a language is not how easy it is to write an arbitrary application in it. It's how easy it is to write something for which the language was designed to do.
-Erwos
Plausible conjecture should not be misrepresented as proof positive.
A few examples
1) Java has bounds checking for arrays, C++ doesn't. This is specified in the language. This affects performance.
2) Java has garbage collection, C++ doesn't. This is specified in the language. This affects performance.
Also, the specification of Java says that it should be compiled to byte code and executed in a JVM.
So the "language" certainly affects performance.
The Internet is full. Go Away!!!
I can say after using SWT in the Pocket PC platform that it sucks. The widgets are primitive, lack any real model implementation, they brake compatibility between minor versions, the most advanced things are done in the Eclipse UI packages not in the widget toolkit and the code you end up writting is ugly.
Elaboration:
No model: with swt you get the widget as a UI object with a field of type Object that you may or may not use as a reference to the object dislpayed. You ahve to write the code that updates th view when the underlying object changes and hende there is not real MVC pattern there. You can do it yourself. Imagine the huge pile of repeated effort in many projects around the world.
Primitive widgets: the table widget is just a string grid. No masked text input, and it goes on and on.
Ugly code: they use public fields for setting state to widgets not constructors or factory methods or even setters. They have integer constants for decribing widgets and you have to use those and see them. Creating a label requires using new Label(SWT.LABEL) and creating a horizontal Line is new Label(SWT.LABEL | SWT.HORIZONTAL). So much for hiding complexity.
There are 4 type of layout managers, the initialization is verbose and in fact only 1 are relevant, GridLayout, the other 3 are special cases of the former.
The more advanced widgets are not in SWT, only in the Eclipse centered custom libraried. The SWT mantainers say those classes are for use in the eclipse UI and they don't mean thme to be general purpose, use thej if they fit, but don't ask for improvements.
The only way SWT is justified is when you have very low resources (a pocket pc) or need to compile with gjc. Otherwise, Swing is way better even when it is far from pefect.
Why did he use only -O2?
-O3 adds function inlining and register renaming.
Also, some of the code doesn't look too much of a test of the language, but more of a test of the libraries. Both versions of hash rely on the library implementations, and it looks like hash.cpp does an extra strdup that the java version doesn't. I don't know either of the hash libraries well enough, but I don't see why this significant slowdown would be necessary in the gcc version.
HIV Crosses Species Barrier... into Muppets
Just becuase you can't write a kernel in it doesn't mean the language is worthless. There are many things that you can do very easily in Java that would be more difficult in other languages, and Java makes it impossible to write many security bugs that plague other languages. You can't do EVERYTHING in Java, but you can do quite a bit.
Gcc is designed for compatibility with a wide range of architectures, and is not optimized for a single one. He also (apparantly) used stock glibc from Red Hat. And only one "test", the method call test, showed java to be a real winner. And even then, it's server-side Java, which is meaning less when you talk about it as a day-to-day dev language (ie; creating standalone client-side apps).
Intel's (heavily optimized) C++ compiler should be a damn sight faster, and so should VC++.
This "comparison" is so limited in scope and meaning, that this writeup should be considered a troll.
Hell, read his lead-in:
Ie; I set out to prove Java is teh awesome and c++ is teh suck!
If anything it proves something I've known intuitively for a long time. gcc does not produce x86 code that's as fast as it could be. That's a trade-off for it being able to compile for every friggin cpu under the sun.
I can't wait till RMS takes personal offense and goes on the attack.
I don't need no instructions to know how to rock!!!!
Well, yes, but the GUI issues are something completely different -- specifically, that Sun has no clue how to write a decent widget set, and insists on going either too far in one direction (AWT -- only supplying widgets available natively on every supported platform) or too far in another (Swing -- emulating every widget even on platforms where they're available natively).
These benchmarks *didn't* include things like opening windows and so forth, and I think that's appropriate. Anyone who cares about writing a graphical Java app with decent performance should be using a different widget set anyhow, like IBM's SWT.
Okay, so how could I make a blanket statement like that? In this case, the author of the paper merely used a compiler switch in gcc (-o2). That doesn't mean his c++ was highly optimized. It just means he told the compiler to do its best. If you really wanted to highly optimize c++, you would study the compiler and how it works, and you would profile the actual assembly that the compiler generates to make sure that it didn't do anything unexpected. Given *any* algorithm, I can come up with a c++ implementation that is faster than a Java implementation. Period.
The java compiler actually compiles to a virtual opcode format, which is then interpreted by the java virtual machine at runtime. Imagine if you needed to talk to someone on the phone, but instead of talking to them, you had to talk through an intermediary. Is there any possible way that it could be faster than talking to the person directly?
Now, I'll be the first to point out that a badly implemented c++ algorithm could be much slower than a well implemented Java algorithm, but I'll take the pepsi challenge with well written code any time, and win.
Relying on benchmarks and code somebody else wrote doesn't prove anything. Did he get down and dirty with the compiler and look at the generated assembly code? No, he did not.
Move along, there's nothing to see here.
WWJD? JWRTFA!
But until it is bundled by default with the JVM and JDKs, it will still be hassle to get SWT working for normal users. If Sun replaced the swing toolkit with SwingWT and linked it to SWT, I would think there would be a great improvement in performance of most Java GUI apps (and most of them really do suck - the only good one I have seen is MoneyDance).
If one program uses profiling information to run faster than another, it runs faster nonetheless. I agree with other posters that this is comparing compilation & runtime environments rather than languages, but when I care about how fast a program runs I care about how fast it runs, not how fast it would run in some hypothetical nonexistent environment. C++ would probably be faster if it had some kind of JIT environment to run in, but it doesn't, and as a developer trying to write fast software, that's what I care about.
That said, I doubt the performance differences are enough to affect my decision about what language to use, unless I am writing some application that does enough computation that a person has to wait on the program, rather than the other way 'round.
> By the sounds of it you have no idea what a good GUI is. Skins and themes do not a pretty UI make.
Since Swing has all the GUI elements of every other toolkit, what would make a pretty UI if not skins/themes? A bad design can be done in any toolkit if the designer doesn't have a good sense of layout, etc.
Presumably the java compiler inlined the function call. Do the math-- 4e9 function calls in 2.5 seconds. That's 1.6e9 function calls per second. On a 3.0 GhZ machine that's two cycles per call, so they're probably all inlined.
In response to what many of you have and will write:
.class to native code you really have native code directly executing.
-- there is not necessarily any "extra layer" created by the JVM. the whole idea is that the JVM is actually a run-time compiler, and when it's done compiling the
-- the JVM runtime compiler can perform optimizations that are not available to a C++ compiler. for example, if the JVM realizes that there is only one instance loaded of an abstract/virtual class it can compile all the code that accesses it statically against that single code, as if there were no inheritence at all, saving a pointer reference. a C++ compiler can never do that because it does not know what you will link against.
-- Many of you are simply going to find ways to criticize Java because you are religious. You used to criticize performance, and if that is taken away from you, you will say it was never really important and criticize something else. You need to think whether or not you are being objective and rational, or simply theocratic.
-- Yes you could likely optimize the C++ code better. Some suggested replacing the inefficient cout's with printf's but that is really eliminating the ++ part of the C++ language. If you can't take advantage of C++'s OO features then there isn't any point in comparing the language with Java--without those higher level features you are programming in the 70's. Guess what, assembler is even faster. So it is fair to compare C++'s high level features with Java.
-- Repeat: Some of you are simply religious.
until one can write an OS kernel in it, Java is still not what I would personally look to for the future of software development.
That's a silly thing to say.
How many OS kernels are going to be written in the next ten years? And how many business applications? And the ratio of the latter to the former is what, 10,000 to 1?
The -server mode of java causes the JVM to recompile code for the most used code path. I have not looked at the exact code for each of the tests, but in many cases this can result in the JVM optimizing out the code completely. You have to be extremely careful when doing benchmarking of languages like java because the JVM is able to dynamically recompile the code to remove the actual work, if the results of that work are never used.
~Giliath
When C/C++ uses profiling it will only ever produce one "best case" compilation for a given function.
With any JIT system you have the opertunity to use the profiling information from a given "window" of the execution so there is the possibility of having more than one compilation for a function.
Now, I do not know how sophisticated JAVA JIT compilers have become but this is one area where JIT will have an upper hand over a static compiler.
OTOH, these tests do not look like there is enough significant variation in the execution path for profiling to make a large difference.
No, I'm not being ironic.
I'm tired of some programmers expecting to be worshipped because they know assembly.
Assembly isn't all that.
For some uses, it is the right tool. For 99.9%+ it most definitely isn't.
The Internet is full. Go Away!!!
For example, Java with its JIT can easily match a C compiler on bit-banging and number crunching small data sets when there's no memory allocation going on. However, that isn't what most people are waiting for when they run typical interactive applications.
If a system is not I/O bound, most applications tend to be doing a lot of string manipulation or similar operations on small objects. When Java operates on strings, it tends to create, discard and garbage-collect a large number of short-lived string objects because Java's strings are immutable. This consumes quite a bit of CPU and memory.
Some C++ applications are written the same way. Many KDE applications are rather sluggish, probably because they are taking advantage of a lot of automatic management of a lot of QT objects. STL-based C++ apps can also be sluggish if you use high-level containers like tree maps without a keen awareness about what kinds of extra copying and thrashing can happen under the hood when you use them. Even in C, if you use high-level libraries, you can get sluggish performance, as some of the more bloated Gnome apps demonstrate.
However, C++ programs, even STL-based ones, may also be written in a different style that takes advantage of mutable strings and handles object allocation manually. This tends to reuse data structures in place, eliminating memory management overhead, and it has the very important effect of keeping caches and page tables much more localized. This is more bug-prone than the alternative, but can provide a substantial performance improvement that Java can't hope to touch on a similar dataset. The drawback is that the app is much more likely to crash unless it was written by a top-notch developer; in fact, this kind of programming is the cause of many of the security problems plaguing the various OSes over the years.
(People often point out that nobody writes kernels in Java. That's because they tend to be written using the manual memory management style with as many static data structures as possible to squeeze out more performance. People don't use popular high-level C++ libraries to write kernels for the same reasons.)
Bottom line, the answer to which language is faster will always be "it depends". It depends on what the program is doing, and it depends on how the program was written. A couple of datapoints from a language shootout don't help to resolve the issues.
Unix GUIs are far easier to implement with Java than with C++. Athena/Xlib are a huge fargin' hassle and no-one ever gets the widgets right. Motif is too expensive to license.
You really need to look into Qt. It's much easier to use than Swing.
Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
You are once again spouting the tired old line that Sun is the master of Java. Not at all true, Java's fate is controlled by a whole host of companies - including IBM. Take a look at the reality of Java platform evolution at the Java Community Process web site.
It's a standards body just like any other, just more open.
P.S. - Aside from that gripe being wrong, I agree with the other poster that you should look into Objective-C to address other issues. Look for "GnuSTEP" for cross-platform objective C GUI work. It's just nicer to use on a Mac as they have very good tools (though in fairness I have never looked at what GnuSTEP tools might be around, I just can't imagine them being quite as good as the tools Apple has sunk so much effort into!).
"There is more worth loving than we have strength to love." - Brian Jay Stanley
I had similar experiences writing a Swing app around six years ago (just around the release of 1.2). At first the Swing app was a little slow, but after a number of rounds of profiling and tuning it was really, really fast - with an MDI interfance and a lot of heavily customized controls on very busy forms. The app worked great even on slower computers, and was well received by the client.
There is no reason Java has to be slow. It's just prone to having a lot of layers stuck on things when they might not need to be. As you say, for a lot of work people are doing J2EE stuff may well be overkill (though even that can work with simialr efforts to tune).
Basically, with any VM app tuning is key. As C# people are only just now starting to realize... a shame the tools there are a lot more primitive that what Java has to offer.
"There is more worth loving than we have strength to love." - Brian Jay Stanley
What concerns me most is the amount of memory it requires. In theory, once the requisite stuff is loaded into memory, Java byte code can be processed at nearly the same rate that C++ code is. Depending on the bytecode and assembly that are generated in each case, Java or C++ could end up being faster. I think it's obvious that Java incurs some overhead in translating the bytecode, which ought to slow it down *some*, but that amount can be minimized.
On the other hand, Java takes a great deal of memory. If C++ had a dedicated server sitting in memory, ready to execute commands for it, it probably would speed up execution, but that wouldn't mean C++ were faster.
After accepting the memory hit for Java, the performance on things like apps servers seems to be pretty decent. I have yet to use a java client application, however, where I didn't feel that it was sluggish (even after loading). There are only two explanations: all java code is written poorly, or Java inherently causes a performance hit.
As we abstract languages more and more, we see performance hits for increased functionality and ease of developing. We also see that, because of the easier development, it is easier to improve scalability and use more efficient algorithms. It is rare that a program cannot be sped up by hand-optimizing the assembly, but it is also rare that anyone has time to design the much more critical optimized algorithms at such a low level. Therefore, I predict that eventually Java (or something like it) will be embraced as programmer time matters more than speed of execution.
The one thing that disturbs me about Java is that, while in C++, it is easy to change the assembly while maintaining the C/C++ code, in Java, you are tied to platform-independent code, which prevents you from doing platform specific optimizations. You have to depend on the native java implementations and/or widget toolkits for those kind of things. And so far, although the situation is improving, I've been pretty unhappy with the speed and my ability to improve it.
-Dan
C++ is as cross platform as the libraries you use. The game code i'm writing so far (it's a simple game, doesn't have any assmebly or optimisation... just a keen like side scroller) compiles under both windows and linux. Using the same make file. How? I use SDL for everything. I've had equally pleasent experiences with Qt. Portability in C and C++ is all based on the libraries.
Of course being able to compile on multiple platforms and being cross platform aren't the same thing but I still think that it is in the benefit of people producing software for Linux specifically, to write code that will port to Windows without to much avail (who the hell uses \?)
The Neo-Bohemian Techno-Socialist
Whew, there's seems to be a lot of denial running through this thread. "An interpreted language just can't possibly be as fast or faster as a compiled language! So I just don't care what the empirical results say, no matter how badly or well done they are, it just can't possibly be!"
I think some of you are overlooking the fact that a VM running byte code is capable of doing optimizations that a compiled language just can't possibly do. A compiled language can only be optimized at compile time. Those optimizations may be very sophisticated, but they can never be any better than an educated guess about what's going to happen at runtime.
But a VM is capable of determining exactly what is happening at runtime; it doesn't have to guess. And thus it is able to optimize those sections of code that really are, in true fact, impacting performance most severely. In can do this by compiling those sections to machine code, thus exploiting precisely the advantage that a compiled language is alleged to have by its very nature. And other kinds of optimizations, the kind that a compiler traditionally does, can be performed on those sections as well.
Of course there are scenarios where runtime optimization doesn't win much, for example in a program that is run once on a small amount of data and then stopped, so that the profiler doesn't get much useful info to work with. This is why Java is more likely to have benefits like this in long-running server processes.
And of course a conscientious C++ programmer will run a profiler on his program on a lot of sample data, and go about optimizing the slowest parts. A conscientious Java programmer should do that too. But an interpreted language has the advantage that the VM can do a lot of that work for you, and always does it at runtime, which is when it really counts.
Always keep a sapphire in your mind
A langauge in and of itself does not determine the speed. It's how that language is implemented/compiled. There's no reason why Java SHOULD be slower as long as it is compiled to the machine's architecture, and not to byte code. ... but then that destroys the purpose of Java.
"he drew his sword Ringil that glittered like ice... and he wounded Morgoth with seven wounds..."
That line made my blood curdle. Of all the UNIX apps I've used, the ones that were written in Java are my least favorite and least used apps. I prefer apps written in C with a toolkit like Qt or Gtk+. Both of those are exceptionally fast and modern looking. Toolkits like WxWindows compile natively with no extra dynamic libraries required and are crossplatform.
But as anyone really using *NIX knows (yes I'm talking about you gentoo, sourcemage, LFS and slackware guys), you always pick the app written in C before the app linked against libstdc++. It may sound elitist but it just seems that people writing in C know what they're doing and take the time to write more solid code. Not to say you can't write a crapwagon C program, perhaps its just easier to fuck it up when you're writing C++.
To go back to your line that made me choke, "I wish all Unix GUIs were done in Java." Perhaps large one-off or custom design software could benefit from Java. But I think this is the minority not the rule. The apps I use on a daily basis are the window manager, xterms, media players, web browsers, document viewing/creation apps, etc. These types of apps have matured over the last 10 years and are all (the ones I use at least) written in C. That is why I can use X and actually do work with no problems on my P133 laptop. Compare that to OpenOffice, Limewire, etc al that I would not touch with a 10' pole for fear of my laptop shutting itself quickly and breaking off my fingers in retaliation.
>A VM otoh does get this capability for free. ;)
TANSTAAFL
> Java enforces garbage collection, and thus optionally gets the particular performance gain
Err... whether garbage collection gains or looses you performance depends very much on your application. I am not convinced that any garbage collector can even be theoretically faster than automatic variables.
>As was pointed out, one of the strenghts of C/C++ are pass-by-value....
After programming in C++ for 14 years, I don't think I've heard that one before
>The fact that you have to explicity declare a c++ parameter as pass-by-reference suggests that those interested in "good programming practices" (tm) will only make a pass-by-reference if you intend to modify it's contents
const &? Ever heard of const references before? I don't feel qualified to judge your Java programming, but it's evident you're not particularly familiar with C++.
I'd be interested to know how you have more control over the design of 3rd party libraries in Java than in C++.
no taxation without representation!
Here is an excerpt from the article for this story: Lea used G++ (GCC) 3.3.1 20030930 (with glibc 2.3.2-98) for the C++, with the -O2 flag (for both i386 and i686). He compiled the Java code normally with the Sun Java 1.4.2_01 compiler, and ran it with the Sun 1.4.2_01 JVM. He ran the tests on Red Hat Linux 9 / Fedora Test1 with the 2.4.20-20.9 kernel on a T30 laptop. The laptop "has a Pentium 4 mobile chip, 512MB of memory, a sort of slow disk," he notes.
What this shows is that GCC's implementation of C++ is slower than an interpreted language like Java. This does not show that C++ is slower than Java.
----
Notes on Stuff
Actually, you're wrong, at least in part. Due to lack of specificity, I'd say that invalidates your argument.
It's all about *where* and *how* Java is used.
As someone who has done application development with both Java and C++ (as well as C, and others), here is how it works (assuming equivalent levels of code quality regardless of language):
For a non-GUI application, Java can be made to run nearly as fast as C++, with a slight startup penalty, and while utilizing decidedly more RAM.
For a GUI applicaton, Java will run considerably slower than a C++ application, and use significantly more RAM.
What does this mean?
Java works great for back-end applications, for web applications, etc. Especially if you take into consideration it's startup penalty (time needed to start the JVM) and run your java program persistently, Java can definitely be fast enough for this.
As for GUI applications, Java is only an ideal choice if you absolutely need something that is fully cross-platform (without using multiple binaries for each), for small applications, or for situations where you can gaurantee that the client machine will have a LOT of RAM, and a fairly modern CPU.
Now, use which ever langauge makes the most sense for what you're doing, and let's get back to coding, okay?
Topher
I just went through and tested the hash2 benchmark and found that I was correct. The C++ version slaughters the Java version (even in "server" mode). This is completely different than what this dude's page shows.
Here is the "correct" code for hash2.cpp:
#include <stdio.h>
#include <iostream>
#include <ext/hash_map>
using namespace std;
using namespace __gnu_cxx;
struct eqstr {
bool operator()(const char* s1, const char* s2) const {
return strcmp(s1, s2) == 0;
}
};
struct hashme
{
size_t operator()(const char* s) const
{
size_t i;
for (i = 0; *s; s++)
i = 31 * i + *s;
return i;
}
};
int
main(int argc, char *argv[]) {
int n = ((argc == 2) ? atoi(argv[1]) : 1);
char buf[16];
typedef hash_map<const char*, int, hashme, eqstr> HM;
HM hash1, hash2;
for (int i=0; i<10000; i++) {
sprintf(buf, "foo_%d", i);
hash1[strdup(buf)] = i;
}
for (int i=0; i<n; i++) {
for (HM::iterator k = hash1.begin(); k != hash1.end(); ++k) {
hash2[(*k).first] += k->second;
}
}
cout << hash1["foo_1"] << " " << hash1["foo_9999"] << " "
<< hash2["foo_1"] << " " << hash2["foo_9999"] << endl;
}
The ratio of people to cake is too big
It might become less significant.
But I get cranky when I click a button and the application doesn't, y'know, appear.
If I have to wait for 19 seconds for anything to appear, I'm not going to be a happy camper, ignoring what technical reasons cause the slowdown.
Furthermore, from a technical standpoint, Java has a number of fundamental performance flaws:
* Java bounds-checks all array accesses. This is pretty par for the course for safe languages, and it's a good bet that compilers optimize some of this out, but it's a hit.
* Java technically can avoid rapid allocation/deallocation by use of object pools and use of primitives and the like. However, it's *very easy* to have an excessive number of allocation/deallocations. The language definitely encourages this.
* Java lacks generics (I haven't checked out 1.5, not sure whether this can provide performance improvements). This is bad because casting and hence run-time typechecking has to take place every time an object in a container is accessed.
Plus, Java eats memory for breakfast. Yes, memory is cheap and all that, but as a user, I'd definitely take a C/C++ app over a Java app any day.
Java's great for lightweight networking, it's nice that it has a cross-platform GUI, and it's good for rapid development due to the scads of library functionality.
The problem is that it got way overhyped as a C/C++ replacement (which it isn't) or even a good choice for general application development (including horizontal-market client stuff) which it isn't.
May we never see th
Thank you! I am not the only one that noticed that these are not even equivilant code. Using sprintf when you expect speed is stupid. sprintf is for simplicity. Making 5 function calls in the middle of a for loop when once would have been fine is also stupid. Also Gxx type compilers are KNOWN to be slower. They are getting better. But the 3.3 branch is more of a staging for better things to come. I would be interested in the same thing done with the intel compiler. WITH all the sub libraries compiled with the intel compiler.
.net could catch up to C performance is interesting though. The code in these enviroents could be self tuning themselves. Did he prove that? I do not think so. NOT with that code.
Sure the code does the same thing. But the few code bits I looked at are not identical. To be a 'fair' test. All the functions need to be written in the same file. Then with *VERY* minimal changes work in both java and C. It wasn't even C++ code. Also if he used the G++ compiler? That is *KNOWN* to be very slow. They rewrote the sucker for 3.4. All the functions need to be called in the same way. All the loops need to be walked the same way. Etc...
This test is bogus. I was willing to give the dude a listen. He even tries to defend what he does wrong. Its almost pathetic. For example he talks about GCC vs Visual studio. Then goes on to use G++. Interesting... Another good thing he does to 'obscure' the issues is to use overloads in C++ yet use method calls in Java. overloads are much slower. Usually firing off all sorts of copy constructors. Method calls are much faster. He even admits it C++ is faster in one case. Well that ONE case is about the only one where he has apples to apples. The rest are not. Also his 'method call' test is not the same thing. He did it in such a way that fires at least 2 copy constructors in the C++ way yet returns direct objects in the java way. C++ is slower in those cases. Well DUH.
The idea that java or
It is like I have always said. C/C++ does not produce awsome code. It lets you produce awsome code. But if your not carefull it lets you produce extreemly BAD code. It does not hold your hand. It has never claimed to. I could with a little bit of work (not as hard as some people would assume) produce the EXACT oposite results of what he got.
A fun one:
Java:
C++:
The C++ version could have been written IDENTICALLY (except for the 'public' modifier on the definition) to the Java version, but it was not. I'm not sure what the compiled difference might be, but there is a difference between these two bits of code, notably that in the C++ version there is a tertiary operator evaluated as an argument to a call to Ack, where this is not the case in the Java version. I would guess that this would be a more difficult thing for a compiler to figure out.
The differences in the methcall sources are even worse; in the C++ version of NthToggle, there are unnecessary dereferences of the this pointer that will kill performance, as well as in the call to new NthToggle(val, 3) in the C++ version is written with the coded constant new NthToggle(true,3) in the java version! It's hardly fair to compare things of this nature.
The trouble with benchmarking different languages is hard enough due to inherent differences between languages; it's not really enlightening to introduce artificial differences such as these.
"There are a dozen opinions on a matter until you know the truth. Then there is only one." - CS Lewis (paraprhase)
sprintf(buf, "%x", i);
It must parse the "%x" and determine what it's trying to do. So it decides, at runtime, you want to translate an integer value into a hexidecimal string. Of course if there's an error at runtime in the string "..." it must generate an error. How 'bout using strtol?
Now let's look at the java version:
Integer.toString(i, 16)
Ok, here we have something that is strongly typed so of course it will be faster. At runtime the java compiler _knows_ what it's dealing with and it knows it must invoke the hexadecimal conversion code.
Note that these statements are within loops.
Just one example, that was the first file I looked at. I don't think they have quite optimized the C++ code IMO. Plus the C++ library is notoriously slow, I would recommend rogue wave or your homegrown C++ classes.
I think the lesson here is it's very easy to write slow C++ code while it's very easy to write fast Java code.
Gimme any C++ code here and I'll profile it/speed it up and get it as fast if not faster than java.
2 years and no mod points. Join reddit. Because openness is good.
It should also be mentioned that the java language requires specific overhead to be included that C++ and C do not. Even if compiled down to sleak assembly, Java is still saddled with doing bounds checking.
The rest of the performance improvements are in the compiler optimizations and libraries which are mostly tangential to the language itself. If the compiler is clever enough to take "for (x=0, i=0; i<100; ++i) x+=5;" and substitute this for "x=500;", then great, but it should not be confused with an endorsement of the language itself.
Furthermore, I had no difficulty modifying the C++ code to outperform or at least meet the results of the server-side JVM using G++. In the cases where Java had any lead whatsoever, the code was so trivial that the JVM could virtually precompute the result. I don't see this as being useful because in the real-world, nothing I write is so trivial that this is possible. If it was, I would have done it myself. I believe this largely explains the discrepency between these "tests" and my actual experience.
-Hope
double gold = (1.0 + sqrt(5)) / 2.0;
int fibonacci(int n)
{
return floor(gold * n);
}
While you make several good points. I do have some counter-points.
A VM otoh does get this capability for free.
Let me qualify this as saying you don't have to do or pay for anything extra to achieve this.
Err... whether garbage collection gains or looses you performance depends very much on your application. I am not convinced that any garbage collector can even be theoretically faster than automatic variables.
By automatic, if you mean stack-resident variables, then I agree (with the caveat of dangerous code design), but if you mean malloc'd variables, then I don't see what the problem is. malloc has to worry about a great number of things, not least of which is memory fragmentation. I happen to have done a non-trivial amount of research on memory allocators; though I am no expert. Memory allocators can be optimized for allocation speed, fragmentation efficiency, concurrency, cache coherence, etc. but not all (obviously). As it happens, a copying garbage collector gives you all of the above EXCEPT when your buffer runs out; and thereby requires a garbage collection. So long as you you have large heap and you're not worried about the latency from garbage collection, then copying collectors are VERY fast. Allocation is literally a mutex lock, a stack-pointer range check, a stack-pointer increment, then a mutex unlock.
Now, because latency is often a real issue, most modern GC's apply additional complexity/logic which slows down the normal case to minimize the worst case; e.g. generational garbage collection which may require read or write boundry op-codes inserted. But code-wise, these varients are identical. Thus you achieve a flexibility not possible in a dynamic-memory-egnostic system such as c/c++.
I'd be interested to know how you have more control over the design of 3rd party libraries in Java than in C++
I didn't really mean design, but environment; Specifically in terms of the dynamic memory allocator. But, just to make the differentiation complete, java allows byte-code load-time modification. This is very common in "aspect oriented programming" such as in the database realm (JBoss/OJB) or object proxying. In Java, by introspection you can prepend/append/search-replace method calls or even individual instructions as need be. Note that this isn't any different than a custom pre-processor for C, but tends to be cleaner and thus doesn't require the [3rd party] coder to adhere to a particular convention.. Moreoever, this works on already shipped binaries, as opposed to requireing preprocessing to occur on the original source code.
-Michael
but that's nto the same thing as saying "Java is faster than C++". The benchmarks in question are bout execution speed, not development speed.
Some of the benchmarks could have been far better implmented with code no more complex than what was arleady used on the c++ side... that's the issue here.
"java is faster for lazy coders" is a fair statement.. but not really what a benchmark tries to asess.
Sure cout is done twice, but it uses 'endl' where '\n' would do. 'endl' flushes the stream, which pretty much kills cache behavior. When the disk/console is orders of magnitude slower than the CPU, a single 'endl' can indeed kill performance.
As for new/delete, they can also be very slow, depending on the current memory layout, etc. More importantly, they violate the C++ programming paradigm (local objects not allocated on the heap) and hence are indicators that this isn't a very good C++ programmer, and hence he isn't qualified to make a reasonable comparison.
Shoot, the last time I did the Java/C++ flamewar I found that Python was faster than both (reading and sorting strings).
That's not a bug in the tests, it's a feature.
;)
;)
That's simply not true if you expect benchmarks to reflect real world applications. Sure, it might be true for trivial utilities but for applications that stay alive for long periods of time chugging along, which is probably the majority of the worlds useful applications, it makes the results invalid. Or, at a minimum, sets greatly unrealistic expectations.
The theory behind garbage collection isn't just that it allows the programmer to avoid the effort of watching when to delete things. It's that garbage collection can actually improve performance on certain workloads.
This is true..."on some workloads". I certainly recognize that fact. I hoped I had more or less pointed that out in my original message. At any rate, for real world workloads, I would offer that such expectations are not realistic.
Forcing a garbage collection for every delete is completely unfair, since it does a full scan of memory, as opposed to just twiddling bits to free a single data value.
Well, technically, even with the 1:1 implementation, it's not forcing collection. It's actually hinting to the GC system, that it should consider doing so. The GC is 100% free to ignore such a request. This is per the java specifications. Which, makes plenty of sense because doing so tends to greatly increase the window where GC can improve performance in various workloads. The problem is, I honestly don't know where implementation and specification lay. I've read many times that it actually does ONLY result in a hint to collect. Unless you can prove otherwise, I'm apt to lean in that direction. Which, actually means that the 1:1 implementation is a more realisitic apples to apples comparison. Can I prove that? No. I'm still hoping a java guru will come in with some insightful tidbits.
There's no memory leak for these benchmarks... both C++ and Java free all memory used when the process exits. Perhaps you'd prefer a longer-running test with lot of garbage generation (forcing gc to run at some point).
Yes, I'm aware that there are no leaks. That's not my complaint. My complaint is that just about every java benchmark I've ever seen is so artificially small that they all appear to purposely avoid GC ever becoming part of the benchmark. Since most major applications simple don't start, run for 20 seconds and exit, I don't consider the presumed bevaior to be valid.
The secondary point I was attempting to raise (along with awareness to the hidden gc issue) is that once Java is forced to start collecting, it's pays a significant cost. A cost, I'd hazzard a guess, that brings about the common complaints of Java. And that, I offer, is the difference between labratory tests and real world application.
It's neither a bug, nor is a feature. It's a difference, and possibly a testing methodology flaw.
And on certain workloads it can decrease performance. Coders that know their languages should recognise the difference between the two memory allocation methods, and adjust their code accordingly. I seriously doubt you'd claim that java's garbage collector is always faster than manual memory management.
Perhaps, but it's also unfair to have a 'benchmark' that always pays the penalty of C++ memory allocation and deallocation, but never pays the penalty of Java memory allocation and deallocation.
Just because the memory is freed back to the system after termination doesn't mean it isn't a memory leak. It's a bad practice to allocation memory and not free it when you're writing C or C++ code. A longer running process would probably be more fair, or even a garbage collect at the end of execution. After all, on 'real' programs, a garbage collection is quite likely.
I used up all my sick days, so I'm calling in dead.
Eh.... so for your counter example you choose a problem that is unsolvable in any language?
Did you just read about that in your computer science class or something? How does that relate to the question at hand? For any java implementation, of any algorithm, I (or someone else) can write a c++ implementation that is faster. Does this mean that I can solve problems in c++ that are unsolvable? Ummm.... no.
This is a common logical fallacy. Its Latin name is "Non-Sequitur". You'll probably get to that next year when you study logic.
WWJD? JWRTFA!
"Any sufficiently complicated C or Fortran program contains an ad hoc informally-specified bug-ridden slow implementation of half of Common Lisp." -- Philip Greenspun
/ took way too long to google
My understanding is that JVM performance has improved because they are now doing things like selecting the appropriate instruction set for the processor at runtime. This is opposed to natively complied languages which are typically compiled to support the lowest common denominator.
Something that is almost always ignored when comparing programming language is the actual cost of developing something in that language.
Sure, you can almost always produce faster software in a low-level language. But since there are no good tools for doing this, it costs to much. Developing software using a modern, state-of-the-art IDE like IntelliJ IDEA, NetBeans or Eclipse speeds up the actually development process and allows the programmers to focus on the design, rather than trying to understand an obscure low-level API.
And no, Visual Studio does not count as a state-of-the-art IDE...
I notice that much of the overhead is simply in making function calls.
Ackermann.cpp, for example, spends very little time actually calculating anything. Much of it's work includes all the overhead associated with making a function call.
Included in this overhead is management of the frame pointer. By using -fomit-frame-pointer, you avoid pushing the old ebp on the stack and a store of the current esp into ebp.
Ackermann runs about twice as fast with this simple optimization.
I saw this test a few days ago and wanted to check it out. The first thing I realize is that the source code is somewhat different even if Java has almost the same syntax as C++.
I understand that System.out.println(); is not in C++ but why have
instead ofI made the C++ code look like Java and got a 15% save. Problably even more if I had increased the number you call the program with. I looked at some of the other program and they have different code in them as well. So this test is bullshit it only shows that you can make slow programs in any language.
Calling System.gc() will usually result in a collection. The VM can't know whether a garbage collect will be useful, because only a full mark and sweep will reveal that. Thus, while the docs state that garbage collection will not necessarily happen after a call to System.gc(), all current VMs will do a full gc (AFAIK). That makes sense because the programmer can determine the need better than the VM.
/end rant
The JVM is designed to make most efficient use of the available RAM and calling System.gc() totally defeats that. To 'forbid' Java from doing it's thing is as fair as disallowing the C++ from using pointers, non-objects (except primitives) and other features which can't be found in Java. Obviously, that is wrong because those features make C++ what it is, just like (unforced) gc is an inherent part of Java.
The only way to determine what the effects are of garbage collection vs (de)allocation is to design a benchmark specifically for this purpose. For instance, you could handle some big images and see how fast each language can complete the benchmark. Another interesting benchmark is to handle a large amount of small objects. However, in the end, the effect of garbage collection on real world apps can differ greatly, depending on:
- the total amount of memory the app can use
- the number of allocated objects
- the size of objects
- the lifetime of objects (Java is far more efficient with short-lived objects, for which it uses a mini-heap and mini-gc)
- the workload of the app (can it do garbage collection during a time of low load?)
The results can differ greatly depending on the particular situation that you are looking at. Of course, it is true in general that it is rare for a language to be better on all fronts, so you always need to look at what you want to do and how well the language is suited to do that. That is also the reason why I hate broad generalizations like:
Sadly, I'm once again seriously disappointed in Java.
Just because the benchmark is flawed, doesn't mean that Java was somehow bad. Especially since your benchmark was a thousand times more flawed. Since you have shown little knowledge about Java (every beginning Java programmer learns that you should avoid calling gc directly), I suggest you stop making these stupid comments.
Garbage collection has long be heralded as a faster solution than explicit new/delete handling of memory allocation. Adding System.gc() is dumb. Escape analysis in the JVM means explicit deletes are placed in where an object clearly doesn't escape a particular level of Java's scope. You can improve GC and escape analysis by assigning object references the value of null.
very good point.
so, you took it back to Java, and biased the test in favor of C++ by running way too many gc's, which, as you point out don't even mean anything because the gc doesn't get invoked immediately. by adding System.gc() to the Java side of the test, you in fact added some kind of randomizer to the code. you don't know what System.gc() does - it's a notification that the gc may run, yes. But you don't know what exactly the system will do after it's called. For all you know, it could stall for a couple of seconds. Or it could count all objects in memory. Or... anything. You added a random delay to the Java side of things.
and, lo and behold, you "proved" that c++ is faster. now, if the original comparison was biased, this was surely worse.
a better test would probably be to let the c++ side never collect anything. and to stop the watch before java starts collecting (just use a huge max. heap size and set it to use the traditional gc and it won't collect anything for a while).
Regarding the article: It's kind of silly to count the JVM startup delay in the tests. Because for some things it will matter, e.g. programs that get run, then shut down again zillions of times. That's why you can't write command line tools in Java. For other things it won't matter at all because they get started once and then continue running (client-GUI software, server app). Also, new JVMs from Apple (and Sun, in the future) just won't have the startup delay because they will statically link precompiled versions of the java class library (rt.jar).
IMHO, speed matters only in one area: When doing calculations in tight loops. There, i believe Java is just as good as c++ because the hotspot compiler actually works and will generate fast, optimized assembler code out of the java loop.
I did some unrelated speed tests within Java (checking the overhead of final method calls - it turned out to be zero as it gets optimized away) and found out, to my surprise, that a simple calculation in a for-loop ran at 400 million loop iterations per second, or 1/3 of phyiscal machine speed (1.3GHz Pentium-M). I found that impressive. Come to think of it, it was probably exactly the DRAM access speed (i was accessing a huge array).
I'm sorry, but I am afraid you are wrong.
Well, I know the halting problem and I don't see how it relates to what you're saying. The conversion from recursive to iterative isn't arbitrarily complex, it's simple and mechanical. The easiest way is to simply use a stack to maintain the state of what were previously recursive calls.
This is still recursion. You have simply substituted one stack for another.
Anyways, all the halting problem implies is that an optimizer will never be able to find every situation where a particular optimization is applicable.
No, it implies much more than this.
Deciding whether two programs are equivalent(EQTM) is equivalent to ATM (the halting problem). (I'll give the series of proofs if anyone requests it.)
This means that there is no algorithmic way to transform recursive functions into iterative ones, and any substitution must be based upon matching of patterns pre-coded into the compiler.
NOTICE: This notice will appear at the bottom of all my slashdot posts.
What's important to note is that the differences introduced by the VM and the rest of Java's overhead are small enough now that, for headless applications, poor coding can easily bridge the difference. There's no huge, glaring, a priori reason to use C++ over Java for headless apps, and when you want your server code to be portable crossplatform you'll find a huge, glaring reason to use Java.
Now what this study obviously doesn't deal at all with GUI'd applications, and Sun's Swing in particular does nothing to help Java's reputation as a slow technology. There's a relatively interesting discussion at java.net called Swing Usability that points out some of these shortcomings. What the Swing team doesn't seem to understand is that slower than native means slow to most users.
And just like the comments in this thread point out, as long as you put a compatibility layer between code and execution, you're going to be slower by definition. With Swing, simple to overlook unoptimized coding practices do not easily spell the difference between implementations. Here, Java's speed and performance is visibly slower no matter how quickly the GUI-less logic behind is racing along. (Yes, SWT is a big help, but it's not part of the JDK and likely still won't be seen in, say, Limewire any time soon.)
It's all 0s and 1s. Or it's not.
The garbage collector runs in a low priority thread. If you just run some code that is doing nothing but calling System.gc(), then of course it will be called. However, if your code is actually trying to do something else, it really is just a "hint" as the other poster stated.
Your other assertion here is that a recursive algorithm rewritten iteratively is still recursive if you don't do anything more complicated than maintain the state with a stack. Well this is not true. A function that does not invoke itself is not recursive, period.
Depends how you define recursion. The prescence of a stack which maintains states means that the function *is* invoking itself. It's just doing so in the same frame on the main stack.
Externalizing the stack *is* more effecient. But it is still, in any meaningful sense of the term, recursive.
In fact just by looking at some (non-recursive) function that uses a stack, and judging that it could obviously be rewritten as recursion, you are finding an equivalance between them, which according to you is impossible.
You have misunderstood the meaning of the term "undecideable". Please see my other reply for the details of how this works.
NOTICE: This notice will appear at the bottom of all my slashdot posts.
Oh, wait, you can't do that because nobody can write Halting.
I guess that means there are some algorithms for which you can't write a faster C++ version.
Actually his statement still holds. No algorithm exists that can decide the halting problem, so he can still say "for all algorithms, a C++ implementation can be written that is faster than a Java implementation."
But don't let me get in the way of you admiring how wise you are.
Next time, try less rhetoric and more facts. "There exist lots of algorithms for which I can code a C++ implementation that's faster than a Java implementation" is good. The instant you make a unilateral statement like the one you just made, though, it shows that you don't know as much about computer science as you think you know.
Get off it. Apparently you don't know as much about logical reasoning as you thought, or even Computer Science since you tried to call the halting problem an algorithm. Not to mention that the word "unilateral" makes no sense in this context; you probably meant "unequivocal" or "unqualified." Shall I find more things to pick on?
(Normally I wouldn't be this pedantic, but you are ripping on someone else based on pedantry and being rewarded with +5.)
Fact: there exist cases where Java is faster due to its ability to optimize on the fly.
The whole point of this critique is that any run-time optimization that Java can perform, a human can perform when they write the algorithm. In the end, all programs are executed by running machine instructions, and any set of instructions that a JVM emits/executes, a human can write manually to achieve exactly the same performance.